@itrocks/mysql 0.0.5 → 0.0.6
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 +133 -1
- package/cjs/mysql.d.ts +5 -5
- package/cjs/mysql.js +18 -16
- package/esm/mysql.d.ts +5 -5
- package/esm/mysql.js +18 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,4 +6,136 @@
|
|
|
6
6
|
|
|
7
7
|
# mysql
|
|
8
8
|
|
|
9
|
-
Transforms model objects to and from
|
|
9
|
+
Transforms model objects to and from MySQL database records.
|
|
10
|
+
|
|
11
|
+
## Summary
|
|
12
|
+
|
|
13
|
+
The `@itrocks/mysql` package provides a seamless integration with MySQL storage, supporting the common
|
|
14
|
+
[@itrocks/storage](https://www.npmjs.com/package/@itrocks/storage) API
|
|
15
|
+
while enabling advanced features for efficient data handling.
|
|
16
|
+
|
|
17
|
+
## Standard API
|
|
18
|
+
|
|
19
|
+
The MySQL data source follows the standard [@itrocks/storage](https://www.npmjs.com/package/@itrocks/storage) API.
|
|
20
|
+
For detailed usage, please refer to the [official documentation](https://github.com/itrocks-ts/storage)
|
|
21
|
+
|
|
22
|
+
## Advanced Features
|
|
23
|
+
|
|
24
|
+
To fully utilize MySQL storage capabilities, integrate and configure the following advanced features:
|
|
25
|
+
|
|
26
|
+
### mysqlDependsOn
|
|
27
|
+
|
|
28
|
+
Configure custom behaviours for MySQL data operations. Example usage (the default):
|
|
29
|
+
```ts
|
|
30
|
+
import { mysqlDependsOn } from '@itrocks/mysql'
|
|
31
|
+
|
|
32
|
+
mysqlDependsOn({
|
|
33
|
+
applyReadTransformer: (record, property) => record[property],
|
|
34
|
+
applySaveTransformer: (object, property) => object[property],
|
|
35
|
+
columnOf: name => name.toLowerCase(),
|
|
36
|
+
componentOf: () => false,
|
|
37
|
+
ignoreTransformedValue: Symbol('ignoreTransformedValue'),
|
|
38
|
+
QueryFunction: class {},
|
|
39
|
+
queryFunctionCall: () => [undefined, ' = ?'],
|
|
40
|
+
storeOf: target => typeOf(target).name.toLowerCase()
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### applyReadTransformer
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
applyReadTransformer: <T extends object>(record: AnyObject, property: KeyOf<T>, object: T) => any
|
|
48
|
+
```
|
|
49
|
+
Transforms a property value when reading data from the database,
|
|
50
|
+
useful for deserialization or type conversion (e.g. string to Date).
|
|
51
|
+
|
|
52
|
+
**Parameters:**
|
|
53
|
+
- `record` ([AnyObject](https://github.com/itrocks-ts/class-type#anyobject)):
|
|
54
|
+
The data record from MySQL.
|
|
55
|
+
- `property` ([KeyOf<T>](https://github.com/itrocks-ts/class-type#keyof)):
|
|
56
|
+
The property to transform.
|
|
57
|
+
- `object` (T extends object):
|
|
58
|
+
The object being constructed.
|
|
59
|
+
It may be incomplete, as not all properties may have been transformed yet.
|
|
60
|
+
|
|
61
|
+
**Return value:**
|
|
62
|
+
- The transformed value of `property` to assign to `object`.
|
|
63
|
+
- Alternatively, return [ignoreTransformedValue](#ignoretransformedvalue)
|
|
64
|
+
to leave the property value unchanged in `object`.
|
|
65
|
+
|
|
66
|
+
### applySaveTransformer
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>, record: AnyObject) => any
|
|
70
|
+
```
|
|
71
|
+
Transforms a property value before saving to the database, e.g., for serialization (Date to string).
|
|
72
|
+
|
|
73
|
+
**Parameters:**
|
|
74
|
+
- `object` (T extends object):
|
|
75
|
+
The object being saved.
|
|
76
|
+
- `property` ([KeyOf<T>](https://github.com/itrocks-ts/class-type#keyof)):
|
|
77
|
+
The property to transform.
|
|
78
|
+
- `record` ([AnyObject](https://github.com/itrocks-ts/class-type#anyobject)):
|
|
79
|
+
The database record to save.
|
|
80
|
+
It may be incomplete, as not all properties may have been transformed yet.
|
|
81
|
+
|
|
82
|
+
**Return value:**
|
|
83
|
+
- The transformed value of `property` to assign to `record`.
|
|
84
|
+
- Alternatively, return [ignoreTransformedValue](#ignoretransformedvalue)
|
|
85
|
+
to exclude the property and its value from `record`.
|
|
86
|
+
|
|
87
|
+
### columnOf
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
columnOf: (property: string) => string
|
|
91
|
+
```
|
|
92
|
+
Maps a property name to a database column name, enabling custom naming conventions.
|
|
93
|
+
|
|
94
|
+
### componentOf
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
componentOf: <T extends object>(target: T, property: KeyOf<T>) => boolean
|
|
98
|
+
```
|
|
99
|
+
Determines whether a property represents a tightly bound component relationship (e.g., `one-to-one` or `many-to-one`).
|
|
100
|
+
Defining this function is highly recommended to ensure proper data access from your MySQL relational database.
|
|
101
|
+
|
|
102
|
+
By default, properties are assumed to represent related collections
|
|
103
|
+
(e.g., `many-to-many` or `one-to-many` relationships).
|
|
104
|
+
|
|
105
|
+
### ignoreTransformedValue
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
ignoreTransformedValue: any
|
|
109
|
+
```
|
|
110
|
+
This marker value is used to skip property transformation during read or save operations.
|
|
111
|
+
It is returned by your implementation of [applyReadTransformer](#applyreadtransformer)
|
|
112
|
+
and [applySaveTransformer](#applysavetransformer), as needed.
|
|
113
|
+
|
|
114
|
+
### QueryFunction
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
QueryFunction: Type<QF>
|
|
118
|
+
```
|
|
119
|
+
Specificies a custom query function type for advanced search operations.
|
|
120
|
+
|
|
121
|
+
### queryFunctionCall
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
queryFunctionCall: (value: QF) => [value: any, sql: string]
|
|
125
|
+
```
|
|
126
|
+
Processes custom query functions, returning the SQL fragment and associated values.
|
|
127
|
+
|
|
128
|
+
**Parameters:**
|
|
129
|
+
- `value`: An object of a class derived from the one defined by [QueryFunction](#queryfunction).
|
|
130
|
+
|
|
131
|
+
**Returns:**
|
|
132
|
+
- `value`: The value associated with the query function
|
|
133
|
+
- `sql`: The corresponding SQL fragment
|
|
134
|
+
|
|
135
|
+
### storeOf
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
storeOf: <T extends object>(target: ObjectOrType<T>) => string | false
|
|
139
|
+
```
|
|
140
|
+
Maps a class ([ObjectOrType](https://github.com/itrocks-ts/class-type#objectortype))
|
|
141
|
+
to its corresponding database table name, allowing for custom naming conventions.
|
package/cjs/mysql.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { Identifier, SearchType } from '@itrocks/storage';
|
|
|
6
6
|
import { Connection } from 'mariadb';
|
|
7
7
|
export declare const DEBUG = false;
|
|
8
8
|
interface Dependencies<QF extends object = object> {
|
|
9
|
-
applyReadTransformer: <T extends object>(
|
|
10
|
-
applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>,
|
|
9
|
+
applyReadTransformer: <T extends object>(record: AnyObject, property: KeyOf<T>, object: T) => any;
|
|
10
|
+
applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>, record: AnyObject) => any;
|
|
11
11
|
columnOf: (property: string) => string;
|
|
12
12
|
componentOf: <T extends object>(target: T, property: KeyOf<T>) => boolean;
|
|
13
13
|
ignoreTransformedValue: any;
|
|
@@ -16,6 +16,7 @@ interface Dependencies<QF extends object = object> {
|
|
|
16
16
|
storeOf: <T extends object>(target: ObjectOrType<T>) => string | false;
|
|
17
17
|
}
|
|
18
18
|
export declare function mysqlDependsOn<QF extends object = object>(dependencies: Partial<Dependencies<QF>>): void;
|
|
19
|
+
export { Mysql };
|
|
19
20
|
export default class Mysql extends DataSource {
|
|
20
21
|
config: {
|
|
21
22
|
host: string;
|
|
@@ -49,7 +50,6 @@ export default class Mysql extends DataSource {
|
|
|
49
50
|
save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
|
|
50
51
|
search<T extends object>(type: Type<T>, search?: SearchType<T>): Promise<Entity<T>[]>;
|
|
51
52
|
update<T extends object>(object: Entity<T>): Promise<Entity<T>>;
|
|
52
|
-
valuesFromDb<T extends object>(
|
|
53
|
-
valuesToDb<T extends object>(object: T
|
|
53
|
+
valuesFromDb<T extends object>(record: Entity<T>, type: Type<T>): Promise<Entity<T>>;
|
|
54
|
+
valuesToDb<T extends object>(object: T): Promise<[AnyObject, Function[]]>;
|
|
54
55
|
}
|
|
55
|
-
export {};
|
package/cjs/mysql.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEBUG = void 0;
|
|
3
|
+
exports.Mysql = exports.DEBUG = void 0;
|
|
4
4
|
exports.mysqlDependsOn = mysqlDependsOn;
|
|
5
5
|
const class_type_1 = require("@itrocks/class-type");
|
|
6
|
+
const class_type_2 = require("@itrocks/class-type");
|
|
6
7
|
const reflect_1 = require("@itrocks/reflect");
|
|
7
8
|
const storage_1 = require("@itrocks/storage");
|
|
8
9
|
const mariadb_1 = require("mariadb");
|
|
9
10
|
exports.DEBUG = false;
|
|
10
11
|
const depends = {
|
|
11
|
-
applyReadTransformer:
|
|
12
|
-
applySaveTransformer:
|
|
13
|
-
columnOf: name => name,
|
|
12
|
+
applyReadTransformer: (record, property) => record[property],
|
|
13
|
+
applySaveTransformer: (object, property) => object[property],
|
|
14
|
+
columnOf: name => name.toLowerCase(),
|
|
14
15
|
componentOf: () => false,
|
|
15
16
|
ignoreTransformedValue: Symbol('ignoreTransformedValue'),
|
|
16
17
|
QueryFunction: class {
|
|
17
18
|
},
|
|
18
19
|
queryFunctionCall: () => [undefined, ' = ?'],
|
|
19
|
-
storeOf:
|
|
20
|
+
storeOf: target => (0, class_type_2.typeOf)(target).name.toLowerCase()
|
|
20
21
|
};
|
|
21
22
|
function mysqlDependsOn(dependencies) {
|
|
22
23
|
Object.assign(depends, dependencies);
|
|
@@ -159,8 +160,9 @@ class Mysql extends storage_1.DataSource {
|
|
|
159
160
|
}
|
|
160
161
|
async search(type, search = {}) {
|
|
161
162
|
const connection = this.connection ?? await this.connect();
|
|
163
|
+
Object.setPrototypeOf(search, type.prototype);
|
|
162
164
|
const sql = this.propertiesToSearchSql(search);
|
|
163
|
-
const [values] = await this.valuesToDb(search
|
|
165
|
+
const [values] = await this.valuesToDb(search);
|
|
164
166
|
if (exports.DEBUG)
|
|
165
167
|
console.log('SELECT * FROM `' + depends.storeOf(type) + '`' + sql, '[', values, ']');
|
|
166
168
|
const rows = await connection.query('SELECT * FROM `' + depends.storeOf(type) + '`' + sql, Object.values(values));
|
|
@@ -179,32 +181,32 @@ class Mysql extends storage_1.DataSource {
|
|
|
179
181
|
}
|
|
180
182
|
return object;
|
|
181
183
|
}
|
|
182
|
-
async valuesFromDb(
|
|
184
|
+
async valuesFromDb(record, type) {
|
|
183
185
|
const object = (new type);
|
|
184
186
|
let property;
|
|
185
|
-
for (property in
|
|
186
|
-
const value = await depends.applyReadTransformer(
|
|
187
|
+
for (property in record) {
|
|
188
|
+
const value = await depends.applyReadTransformer(record, property, object);
|
|
187
189
|
if (value === depends.ignoreTransformedValue)
|
|
188
190
|
continue;
|
|
189
191
|
object[property] = value;
|
|
190
192
|
}
|
|
191
193
|
return object;
|
|
192
194
|
}
|
|
193
|
-
async valuesToDb(object
|
|
194
|
-
const typeObject = type ? new type : object;
|
|
195
|
+
async valuesToDb(object) {
|
|
195
196
|
const deferred = [];
|
|
196
|
-
const
|
|
197
|
-
for (const property of
|
|
198
|
-
const value = await depends.applySaveTransformer(
|
|
197
|
+
const record = {};
|
|
198
|
+
for (const property of Object.keys(object)) {
|
|
199
|
+
const value = await depends.applySaveTransformer(object, property, record);
|
|
199
200
|
if (value === depends.ignoreTransformedValue)
|
|
200
201
|
continue;
|
|
201
202
|
if ((0, class_type_1.isAnyFunction)(value)) {
|
|
202
203
|
deferred.push(value);
|
|
203
204
|
continue;
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
+
record[property] = value;
|
|
206
207
|
}
|
|
207
|
-
return [
|
|
208
|
+
return [record, deferred];
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
exports.default = Mysql;
|
|
212
|
+
exports.Mysql = Mysql;
|
package/esm/mysql.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { Identifier, SearchType } from '@itrocks/storage';
|
|
|
6
6
|
import { Connection } from 'mariadb';
|
|
7
7
|
export declare const DEBUG = false;
|
|
8
8
|
interface Dependencies<QF extends object = object> {
|
|
9
|
-
applyReadTransformer: <T extends object>(
|
|
10
|
-
applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>,
|
|
9
|
+
applyReadTransformer: <T extends object>(record: AnyObject, property: KeyOf<T>, object: T) => any;
|
|
10
|
+
applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>, record: AnyObject) => any;
|
|
11
11
|
columnOf: (property: string) => string;
|
|
12
12
|
componentOf: <T extends object>(target: T, property: KeyOf<T>) => boolean;
|
|
13
13
|
ignoreTransformedValue: any;
|
|
@@ -16,6 +16,7 @@ interface Dependencies<QF extends object = object> {
|
|
|
16
16
|
storeOf: <T extends object>(target: ObjectOrType<T>) => string | false;
|
|
17
17
|
}
|
|
18
18
|
export declare function mysqlDependsOn<QF extends object = object>(dependencies: Partial<Dependencies<QF>>): void;
|
|
19
|
+
export { Mysql };
|
|
19
20
|
export default class Mysql extends DataSource {
|
|
20
21
|
config: {
|
|
21
22
|
host: string;
|
|
@@ -49,7 +50,6 @@ export default class Mysql extends DataSource {
|
|
|
49
50
|
save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
|
|
50
51
|
search<T extends object>(type: Type<T>, search?: SearchType<T>): Promise<Entity<T>[]>;
|
|
51
52
|
update<T extends object>(object: Entity<T>): Promise<Entity<T>>;
|
|
52
|
-
valuesFromDb<T extends object>(
|
|
53
|
-
valuesToDb<T extends object>(object: T
|
|
53
|
+
valuesFromDb<T extends object>(record: Entity<T>, type: Type<T>): Promise<Entity<T>>;
|
|
54
|
+
valuesToDb<T extends object>(object: T): Promise<[AnyObject, Function[]]>;
|
|
54
55
|
}
|
|
55
|
-
export {};
|
package/esm/mysql.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { isAnyFunction } from '@itrocks/class-type';
|
|
2
|
-
import {
|
|
2
|
+
import { typeOf } from '@itrocks/class-type';
|
|
3
|
+
import { ReflectProperty } from '@itrocks/reflect';
|
|
3
4
|
import { DataSource } from '@itrocks/storage';
|
|
4
5
|
import { createConnection } from 'mariadb';
|
|
5
6
|
export const DEBUG = false;
|
|
6
7
|
const depends = {
|
|
7
|
-
applyReadTransformer:
|
|
8
|
-
applySaveTransformer:
|
|
9
|
-
columnOf: name => name,
|
|
8
|
+
applyReadTransformer: (record, property) => record[property],
|
|
9
|
+
applySaveTransformer: (object, property) => object[property],
|
|
10
|
+
columnOf: name => name.toLowerCase(),
|
|
10
11
|
componentOf: () => false,
|
|
11
12
|
ignoreTransformedValue: Symbol('ignoreTransformedValue'),
|
|
12
13
|
QueryFunction: class {
|
|
13
14
|
},
|
|
14
15
|
queryFunctionCall: () => [undefined, ' = ?'],
|
|
15
|
-
storeOf:
|
|
16
|
+
storeOf: target => typeOf(target).name.toLowerCase()
|
|
16
17
|
};
|
|
17
18
|
export function mysqlDependsOn(dependencies) {
|
|
18
19
|
Object.assign(depends, dependencies);
|
|
19
20
|
}
|
|
21
|
+
export { Mysql };
|
|
20
22
|
export default class Mysql extends DataSource {
|
|
21
23
|
config;
|
|
22
24
|
connection;
|
|
@@ -155,8 +157,9 @@ export default class Mysql extends DataSource {
|
|
|
155
157
|
}
|
|
156
158
|
async search(type, search = {}) {
|
|
157
159
|
const connection = this.connection ?? await this.connect();
|
|
160
|
+
Object.setPrototypeOf(search, type.prototype);
|
|
158
161
|
const sql = this.propertiesToSearchSql(search);
|
|
159
|
-
const [values] = await this.valuesToDb(search
|
|
162
|
+
const [values] = await this.valuesToDb(search);
|
|
160
163
|
if (DEBUG)
|
|
161
164
|
console.log('SELECT * FROM `' + depends.storeOf(type) + '`' + sql, '[', values, ']');
|
|
162
165
|
const rows = await connection.query('SELECT * FROM `' + depends.storeOf(type) + '`' + sql, Object.values(values));
|
|
@@ -175,31 +178,30 @@ export default class Mysql extends DataSource {
|
|
|
175
178
|
}
|
|
176
179
|
return object;
|
|
177
180
|
}
|
|
178
|
-
async valuesFromDb(
|
|
181
|
+
async valuesFromDb(record, type) {
|
|
179
182
|
const object = (new type);
|
|
180
183
|
let property;
|
|
181
|
-
for (property in
|
|
182
|
-
const value = await depends.applyReadTransformer(
|
|
184
|
+
for (property in record) {
|
|
185
|
+
const value = await depends.applyReadTransformer(record, property, object);
|
|
183
186
|
if (value === depends.ignoreTransformedValue)
|
|
184
187
|
continue;
|
|
185
188
|
object[property] = value;
|
|
186
189
|
}
|
|
187
190
|
return object;
|
|
188
191
|
}
|
|
189
|
-
async valuesToDb(object
|
|
190
|
-
const typeObject = type ? new type : object;
|
|
192
|
+
async valuesToDb(object) {
|
|
191
193
|
const deferred = [];
|
|
192
|
-
const
|
|
193
|
-
for (const property of
|
|
194
|
-
const value = await depends.applySaveTransformer(
|
|
194
|
+
const record = {};
|
|
195
|
+
for (const property of Object.keys(object)) {
|
|
196
|
+
const value = await depends.applySaveTransformer(object, property, record);
|
|
195
197
|
if (value === depends.ignoreTransformedValue)
|
|
196
198
|
continue;
|
|
197
199
|
if (isAnyFunction(value)) {
|
|
198
200
|
deferred.push(value);
|
|
199
201
|
continue;
|
|
200
202
|
}
|
|
201
|
-
|
|
203
|
+
record[property] = value;
|
|
202
204
|
}
|
|
203
|
-
return [
|
|
205
|
+
return [record, deferred];
|
|
204
206
|
}
|
|
205
207
|
}
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"mariadb": "^3.4",
|
|
11
11
|
"typescript": "~5.6"
|
|
12
12
|
},
|
|
13
|
-
"description": "Transforms model objects to and from
|
|
13
|
+
"description": "Transforms model objects to and from MySQL database records",
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@types/node": "^22.10"
|
|
16
16
|
},
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"build:esm": "tsc -p tsconfig.esm.json"
|
|
59
59
|
},
|
|
60
60
|
"types": "./esm/mysql.d.ts",
|
|
61
|
-
"version": "0.0.
|
|
61
|
+
"version": "0.0.6"
|
|
62
62
|
}
|