@itrocks/mysql 0.0.20 → 0.0.22
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/cjs/mysql.d.ts +2 -0
- package/cjs/mysql.js +65 -10
- package/esm/mysql.d.ts +2 -0
- package/esm/mysql.js +62 -7
- package/package.json +1 -1
package/cjs/mysql.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare class Mysql extends DataSource {
|
|
|
30
30
|
database: string;
|
|
31
31
|
};
|
|
32
32
|
connection?: Connection;
|
|
33
|
+
saveQueue: WeakMap<object, Promise<void | Entity<object>>>;
|
|
33
34
|
constructor(config: {
|
|
34
35
|
host: string;
|
|
35
36
|
user: string;
|
|
@@ -51,6 +52,7 @@ export declare class Mysql extends DataSource {
|
|
|
51
52
|
}>[]>;
|
|
52
53
|
readCollectionIds<T extends object, PT extends object>(object: Entity<T>, property: KeyOf<T>, type?: Type<PT>): Promise<Identifier[]>;
|
|
53
54
|
readMultiple<T extends object>(type: Type<T>, ids: Identifier[]): Promise<Entity<T>[]>;
|
|
55
|
+
runSerialized<T extends object>(object: MayEntity<T>, task: () => Promise<Entity<T>>): Promise<Entity<T>>;
|
|
54
56
|
save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
|
|
55
57
|
saveCollection<T extends object>(object: Entity<T>, property: KeyOf<T>, value: (Identifier | MayEntity)[]): Promise<void>;
|
|
56
58
|
saveComponents<T extends object>(object: Entity<T>, property: KeyOf<T>, components: (Identifier | MayEntity)[]): Promise<void>;
|
package/cjs/mysql.js
CHANGED
|
@@ -6,6 +6,8 @@ exports.mysqlDependsOn = mysqlDependsOn;
|
|
|
6
6
|
const class_type_1 = require("@itrocks/class-type");
|
|
7
7
|
const class_type_2 = require("@itrocks/class-type");
|
|
8
8
|
const class_type_3 = require("@itrocks/class-type");
|
|
9
|
+
const class_type_4 = require("@itrocks/class-type");
|
|
10
|
+
const composition_1 = require("@itrocks/composition");
|
|
9
11
|
const property_type_1 = require("@itrocks/property-type");
|
|
10
12
|
const reflect_1 = require("@itrocks/reflect");
|
|
11
13
|
const reflect_2 = require("@itrocks/reflect");
|
|
@@ -24,7 +26,7 @@ const depends = {
|
|
|
24
26
|
QueryFunction: class {
|
|
25
27
|
},
|
|
26
28
|
queryFunctionCall: () => [undefined, ' = ?'],
|
|
27
|
-
storeOf: target => (0,
|
|
29
|
+
storeOf: target => (0, class_type_4.typeOf)(target).name.toLowerCase()
|
|
28
30
|
};
|
|
29
31
|
function joinTableName(object1, object2) {
|
|
30
32
|
if (typeof object1 !== 'string')
|
|
@@ -39,6 +41,7 @@ function mysqlDependsOn(dependencies) {
|
|
|
39
41
|
class Mysql extends storage_1.DataSource {
|
|
40
42
|
config;
|
|
41
43
|
connection;
|
|
44
|
+
saveQueue = new WeakMap();
|
|
42
45
|
constructor(config) {
|
|
43
46
|
super();
|
|
44
47
|
this.config = config;
|
|
@@ -129,7 +132,7 @@ class Mysql extends storage_1.DataSource {
|
|
|
129
132
|
const propertyType = property.type;
|
|
130
133
|
if (propertyType instanceof property_type_1.CollectionType)
|
|
131
134
|
continue;
|
|
132
|
-
const propertyName = ((0,
|
|
135
|
+
const propertyName = ((0, class_type_3.isAnyType)(propertyType.type) && depends.storeOf(propertyType.type))
|
|
133
136
|
? property.name + 'Id'
|
|
134
137
|
: property.name;
|
|
135
138
|
const columnName = depends.columnOf(propertyName);
|
|
@@ -198,21 +201,73 @@ class Mysql extends storage_1.DataSource {
|
|
|
198
201
|
const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '` WHERE id IN (' + questionMarks + ')', ids);
|
|
199
202
|
return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
|
|
200
203
|
}
|
|
204
|
+
async runSerialized(object, task) {
|
|
205
|
+
const prev = this.saveQueue.get(object) || Promise.resolve();
|
|
206
|
+
const next = prev.then(task, task);
|
|
207
|
+
this.saveQueue.set(object, next.then(() => { this.saveQueue.delete(object); }, () => { this.saveQueue.delete(object); }));
|
|
208
|
+
return next;
|
|
209
|
+
}
|
|
201
210
|
async save(object) {
|
|
202
|
-
return this.
|
|
203
|
-
|
|
204
|
-
|
|
211
|
+
return this.runSerialized(object, async () => {
|
|
212
|
+
return this.isObjectConnected(object)
|
|
213
|
+
? this.update(object)
|
|
214
|
+
: this.insert(object);
|
|
215
|
+
});
|
|
205
216
|
}
|
|
206
217
|
async saveCollection(object, property, value) {
|
|
207
|
-
|
|
218
|
+
if (property.endsWith('Ids')) {
|
|
219
|
+
property = property.slice(0, -3);
|
|
220
|
+
}
|
|
221
|
+
return depends.componentOf(object, property)
|
|
208
222
|
? this.saveComponents(object, property, value)
|
|
209
223
|
: this.saveLinks(object, property, value);
|
|
210
224
|
}
|
|
211
225
|
async saveComponents(object, property, components) {
|
|
212
|
-
|
|
226
|
+
const connection = this.connection ?? await this.connect();
|
|
227
|
+
const propertyType = new reflect_2.ReflectProperty(object, property).collectionType.elementType.type;
|
|
228
|
+
const stored = await this.readCollectionIds(object, property, propertyType);
|
|
229
|
+
const saved = new Array;
|
|
230
|
+
let compositeProperty;
|
|
231
|
+
for (const component of components) {
|
|
232
|
+
if (typeof component !== 'object') {
|
|
233
|
+
saved.push(component);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (compositeProperty === undefined) {
|
|
237
|
+
const objectType = (0, class_type_4.typeOf)(object);
|
|
238
|
+
for (const candidate of new reflect_1.ReflectClass(component).properties) {
|
|
239
|
+
if (!(0, composition_1.compositeOf)(component, candidate.name))
|
|
240
|
+
continue;
|
|
241
|
+
const candidateType = candidate.type.type;
|
|
242
|
+
if (!(0, class_type_3.isAnyType)(candidateType))
|
|
243
|
+
continue;
|
|
244
|
+
if (!(0, class_type_1.inherits)(objectType, candidateType))
|
|
245
|
+
continue;
|
|
246
|
+
compositeProperty = candidate;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (compositeProperty) {
|
|
251
|
+
// @ts-ignore TS2322 Don't understand this error
|
|
252
|
+
component[compositeProperty.name] = object;
|
|
253
|
+
}
|
|
254
|
+
saved.push((await this.save(component)).id);
|
|
255
|
+
}
|
|
256
|
+
let componentTable;
|
|
257
|
+
for (const storedId of stored) {
|
|
258
|
+
if (saved.includes(storedId))
|
|
259
|
+
continue;
|
|
260
|
+
if (!componentTable) {
|
|
261
|
+
componentTable = depends.storeOf(propertyType);
|
|
262
|
+
if (!componentTable) {
|
|
263
|
+
throw 'Missing @Store on type ' + propertyType.name
|
|
264
|
+
+ ' used by @Component ' + new reflect_1.ReflectClass(object).name + '.' + property;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
await connection.query('DELETE FROM `' + componentTable + '` WHERE id = ?', [storedId]);
|
|
268
|
+
}
|
|
213
269
|
}
|
|
214
270
|
async saveLinks(object, property, links) {
|
|
215
|
-
property = property.endsWith('Ids') ? property.slice(0, -3) : property;
|
|
216
271
|
const connection = this.connection ?? await this.connect();
|
|
217
272
|
const objectTable = depends.storeOf(object);
|
|
218
273
|
const propertyType = new reflect_2.ReflectProperty(object, property).collectionType.elementType.type;
|
|
@@ -222,7 +277,7 @@ class Mysql extends storage_1.DataSource {
|
|
|
222
277
|
const objectColumn = depends.columnOf(objectTable) + '_id';
|
|
223
278
|
const objectId = object.id;
|
|
224
279
|
const stored = await this.readCollectionIds(object, property, propertyType);
|
|
225
|
-
const saved =
|
|
280
|
+
const saved = new Array;
|
|
226
281
|
for (const link of links) {
|
|
227
282
|
const linkId = (typeof link === 'object')
|
|
228
283
|
? (this.isObjectConnected(link) ? link.id : (await this.save(link)).id)
|
|
@@ -304,7 +359,7 @@ class Mysql extends storage_1.DataSource {
|
|
|
304
359
|
deferred.push((object) => this.saveCollection(object, property, value));
|
|
305
360
|
continue;
|
|
306
361
|
}
|
|
307
|
-
if ((0,
|
|
362
|
+
if ((0, class_type_2.isAnyFunction)(value)) {
|
|
308
363
|
deferred.push(value);
|
|
309
364
|
continue;
|
|
310
365
|
}
|
package/esm/mysql.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare class Mysql extends DataSource {
|
|
|
30
30
|
database: string;
|
|
31
31
|
};
|
|
32
32
|
connection?: Connection;
|
|
33
|
+
saveQueue: WeakMap<object, Promise<void | Entity<object>>>;
|
|
33
34
|
constructor(config: {
|
|
34
35
|
host: string;
|
|
35
36
|
user: string;
|
|
@@ -51,6 +52,7 @@ export declare class Mysql extends DataSource {
|
|
|
51
52
|
}>[]>;
|
|
52
53
|
readCollectionIds<T extends object, PT extends object>(object: Entity<T>, property: KeyOf<T>, type?: Type<PT>): Promise<Identifier[]>;
|
|
53
54
|
readMultiple<T extends object>(type: Type<T>, ids: Identifier[]): Promise<Entity<T>[]>;
|
|
55
|
+
runSerialized<T extends object>(object: MayEntity<T>, task: () => Promise<Entity<T>>): Promise<Entity<T>>;
|
|
54
56
|
save<T extends object>(object: MayEntity<T>): Promise<Entity<T>>;
|
|
55
57
|
saveCollection<T extends object>(object: Entity<T>, property: KeyOf<T>, value: (Identifier | MayEntity)[]): Promise<void>;
|
|
56
58
|
saveComponents<T extends object>(object: Entity<T>, property: KeyOf<T>, components: (Identifier | MayEntity)[]): Promise<void>;
|
package/esm/mysql.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { inherits } from '@itrocks/class-type';
|
|
1
2
|
import { isAnyFunction } from '@itrocks/class-type';
|
|
2
3
|
import { isAnyType } from '@itrocks/class-type';
|
|
3
4
|
import { typeOf } from '@itrocks/class-type';
|
|
5
|
+
import { compositeOf } from '@itrocks/composition';
|
|
4
6
|
import { CollectionType } from '@itrocks/property-type';
|
|
5
7
|
import { ReflectClass } from '@itrocks/reflect';
|
|
6
8
|
import { ReflectProperty } from '@itrocks/reflect';
|
|
@@ -34,6 +36,7 @@ export function mysqlDependsOn(dependencies) {
|
|
|
34
36
|
export class Mysql extends DataSource {
|
|
35
37
|
config;
|
|
36
38
|
connection;
|
|
39
|
+
saveQueue = new WeakMap();
|
|
37
40
|
constructor(config) {
|
|
38
41
|
super();
|
|
39
42
|
this.config = config;
|
|
@@ -193,21 +196,73 @@ export class Mysql extends DataSource {
|
|
|
193
196
|
const rows = await connection.query('SELECT ' + propertiesSql + ' FROM `' + depends.storeOf(type) + '` WHERE id IN (' + questionMarks + ')', ids);
|
|
194
197
|
return Promise.all(rows.map(row => this.valuesFromDb(row, type)));
|
|
195
198
|
}
|
|
199
|
+
async runSerialized(object, task) {
|
|
200
|
+
const prev = this.saveQueue.get(object) || Promise.resolve();
|
|
201
|
+
const next = prev.then(task, task);
|
|
202
|
+
this.saveQueue.set(object, next.then(() => { this.saveQueue.delete(object); }, () => { this.saveQueue.delete(object); }));
|
|
203
|
+
return next;
|
|
204
|
+
}
|
|
196
205
|
async save(object) {
|
|
197
|
-
return this.
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
return this.runSerialized(object, async () => {
|
|
207
|
+
return this.isObjectConnected(object)
|
|
208
|
+
? this.update(object)
|
|
209
|
+
: this.insert(object);
|
|
210
|
+
});
|
|
200
211
|
}
|
|
201
212
|
async saveCollection(object, property, value) {
|
|
202
|
-
|
|
213
|
+
if (property.endsWith('Ids')) {
|
|
214
|
+
property = property.slice(0, -3);
|
|
215
|
+
}
|
|
216
|
+
return depends.componentOf(object, property)
|
|
203
217
|
? this.saveComponents(object, property, value)
|
|
204
218
|
: this.saveLinks(object, property, value);
|
|
205
219
|
}
|
|
206
220
|
async saveComponents(object, property, components) {
|
|
207
|
-
|
|
221
|
+
const connection = this.connection ?? await this.connect();
|
|
222
|
+
const propertyType = new ReflectProperty(object, property).collectionType.elementType.type;
|
|
223
|
+
const stored = await this.readCollectionIds(object, property, propertyType);
|
|
224
|
+
const saved = new Array;
|
|
225
|
+
let compositeProperty;
|
|
226
|
+
for (const component of components) {
|
|
227
|
+
if (typeof component !== 'object') {
|
|
228
|
+
saved.push(component);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (compositeProperty === undefined) {
|
|
232
|
+
const objectType = typeOf(object);
|
|
233
|
+
for (const candidate of new ReflectClass(component).properties) {
|
|
234
|
+
if (!compositeOf(component, candidate.name))
|
|
235
|
+
continue;
|
|
236
|
+
const candidateType = candidate.type.type;
|
|
237
|
+
if (!isAnyType(candidateType))
|
|
238
|
+
continue;
|
|
239
|
+
if (!inherits(objectType, candidateType))
|
|
240
|
+
continue;
|
|
241
|
+
compositeProperty = candidate;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (compositeProperty) {
|
|
246
|
+
// @ts-ignore TS2322 Don't understand this error
|
|
247
|
+
component[compositeProperty.name] = object;
|
|
248
|
+
}
|
|
249
|
+
saved.push((await this.save(component)).id);
|
|
250
|
+
}
|
|
251
|
+
let componentTable;
|
|
252
|
+
for (const storedId of stored) {
|
|
253
|
+
if (saved.includes(storedId))
|
|
254
|
+
continue;
|
|
255
|
+
if (!componentTable) {
|
|
256
|
+
componentTable = depends.storeOf(propertyType);
|
|
257
|
+
if (!componentTable) {
|
|
258
|
+
throw 'Missing @Store on type ' + propertyType.name
|
|
259
|
+
+ ' used by @Component ' + new ReflectClass(object).name + '.' + property;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
await connection.query('DELETE FROM `' + componentTable + '` WHERE id = ?', [storedId]);
|
|
263
|
+
}
|
|
208
264
|
}
|
|
209
265
|
async saveLinks(object, property, links) {
|
|
210
|
-
property = property.endsWith('Ids') ? property.slice(0, -3) : property;
|
|
211
266
|
const connection = this.connection ?? await this.connect();
|
|
212
267
|
const objectTable = depends.storeOf(object);
|
|
213
268
|
const propertyType = new ReflectProperty(object, property).collectionType.elementType.type;
|
|
@@ -217,7 +272,7 @@ export class Mysql extends DataSource {
|
|
|
217
272
|
const objectColumn = depends.columnOf(objectTable) + '_id';
|
|
218
273
|
const objectId = object.id;
|
|
219
274
|
const stored = await this.readCollectionIds(object, property, propertyType);
|
|
220
|
-
const saved =
|
|
275
|
+
const saved = new Array;
|
|
221
276
|
for (const link of links) {
|
|
222
277
|
const linkId = (typeof link === 'object')
|
|
223
278
|
? (this.isObjectConnected(link) ? link.id : (await this.save(link)).id)
|
package/package.json
CHANGED