@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 CHANGED
@@ -6,4 +6,136 @@
6
6
 
7
7
  # mysql
8
8
 
9
- Transforms model objects to and from storage systems.
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&lt;T&gt;](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&lt;T&gt;](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>(object: T, property: KeyOf<T>, data: AnyObject) => any;
10
- applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>, data: AnyObject) => any;
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>(row: Entity<T>, type: Type<T>): Promise<Entity<T>>;
53
- valuesToDb<T extends object>(object: T, type?: Type<T>): Promise<[AnyObject, Function[]]>;
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: value => value,
12
- applySaveTransformer: value => value,
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: () => false
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, type);
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(row, type) {
184
+ async valuesFromDb(record, type) {
183
185
  const object = (new type);
184
186
  let property;
185
- for (property in row) {
186
- const value = await depends.applyReadTransformer(object, property, row);
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, type) {
194
- const typeObject = type ? new type : object;
195
+ async valuesToDb(object) {
195
196
  const deferred = [];
196
- const values = {};
197
- for (const property of type ? Object.keys(object) : new reflect_1.ReflectClass(object).propertyNames) {
198
- const value = await depends.applySaveTransformer(typeObject, property, values);
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
- values[property] = value;
206
+ record[property] = value;
206
207
  }
207
- return [values, deferred];
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>(object: T, property: KeyOf<T>, data: AnyObject) => any;
10
- applySaveTransformer: <T extends object>(object: T, property: KeyOf<T>, data: AnyObject) => any;
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>(row: Entity<T>, type: Type<T>): Promise<Entity<T>>;
53
- valuesToDb<T extends object>(object: T, type?: Type<T>): Promise<[AnyObject, Function[]]>;
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 { ReflectClass, ReflectProperty } from '@itrocks/reflect';
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: value => value,
8
- applySaveTransformer: value => value,
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: () => false
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, type);
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(row, type) {
181
+ async valuesFromDb(record, type) {
179
182
  const object = (new type);
180
183
  let property;
181
- for (property in row) {
182
- const value = await depends.applyReadTransformer(object, property, row);
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, type) {
190
- const typeObject = type ? new type : object;
192
+ async valuesToDb(object) {
191
193
  const deferred = [];
192
- const values = {};
193
- for (const property of type ? Object.keys(object) : new ReflectClass(object).propertyNames) {
194
- const value = await depends.applySaveTransformer(typeObject, property, values);
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
- values[property] = value;
203
+ record[property] = value;
202
204
  }
203
- return [values, deferred];
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 mysql records",
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.5"
61
+ "version": "0.0.6"
62
62
  }