@wxn0brp/db-core 0.4.0 → 0.5.0-alpha.1
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/dist/base/actions.d.ts +6 -7
- package/dist/base/actions.js +5 -6
- package/dist/base/custom.d.ts +7 -7
- package/dist/base/custom.js +5 -3
- package/dist/customFileCpu.d.ts +7 -8
- package/dist/customFileCpu.js +18 -20
- package/dist/db/memory.d.ts +5 -5
- package/dist/db/memory.js +3 -3
- package/dist/db/multiStorage.d.ts +5 -5
- package/dist/db/multiStorage.js +9 -11
- package/dist/db/routedStorage.d.ts +5 -5
- package/dist/db/routedStorage.js +1 -1
- package/dist/db/valthera.d.ts +19 -24
- package/dist/db/valthera.js +52 -27
- package/dist/helpers/addId.d.ts +1 -1
- package/dist/helpers/addId.js +1 -1
- package/dist/helpers/{collectionManager.d.ts → collection.d.ts} +14 -11
- package/dist/helpers/collection.js +59 -0
- package/dist/helpers/executor.d.ts +2 -4
- package/dist/helpers/executor.js +1 -3
- package/dist/helpers/forge.d.ts +15 -4
- package/dist/helpers/forge.js +2 -2
- package/dist/helpers/gen.d.ts +17 -1
- package/dist/helpers/gen.js +36 -30
- package/dist/helpers/relation.d.ts +5 -2
- package/dist/helpers/relation.js +44 -33
- package/dist/index.d.ts +11 -13
- package/dist/index.js +7 -8
- package/dist/types/data.d.ts +0 -1
- package/dist/types/fileCpu.d.ts +6 -7
- package/dist/types/options.d.ts +3 -3
- package/dist/types/query.d.ts +12 -0
- package/dist/types/relation.d.ts +1 -1
- package/dist/types/valthera.d.ts +22 -14
- package/dist/utils/action.d.ts +2 -2
- package/dist/utils/hasFields.d.ts +1 -1
- package/dist/utils/hasFields.js +1 -1
- package/dist/utils/hasFieldsAdvanced.d.ts +1 -1
- package/dist/utils/hasFieldsAdvanced.js +2 -2
- package/dist/utils/updateFindObject.d.ts +1 -1
- package/dist/utils/updateFindObject.js +1 -1
- package/dist/utils/updateObject.d.ts +1 -1
- package/dist/utils/updateObject.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/helpers/collectionManager.js +0 -62
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { Arg, Search, Updater } from "../types/arg.js";
|
|
2
|
+
import { Data } from "../types/data.js";
|
|
2
3
|
import { DbFindOpts, FindOpts } from "../types/options.js";
|
|
3
4
|
import { VContext } from "../types/types.js";
|
|
4
|
-
import Data from "../types/data.js";
|
|
5
5
|
import { UpdateOneOrAdd, ValtheraCompatible } from "../types/valthera.js";
|
|
6
|
-
export declare class
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export declare class Collection<D = Data> {
|
|
7
|
+
db: ValtheraCompatible;
|
|
8
|
+
collection: string;
|
|
9
9
|
constructor(db: ValtheraCompatible, collection: string);
|
|
10
10
|
/**
|
|
11
11
|
* Add data to a database.
|
|
12
12
|
*/
|
|
13
|
-
add(data: Arg<D>, id_gen
|
|
13
|
+
add(data: Arg<D>, id_gen: true): Promise<D>;
|
|
14
|
+
add(data: Arg<D>, id_gen?: true): Promise<D & {
|
|
15
|
+
_id: string;
|
|
16
|
+
}>;
|
|
14
17
|
/**
|
|
15
18
|
* Find data in a database.
|
|
16
19
|
*/
|
|
@@ -22,25 +25,25 @@ export declare class CollectionManager<D = Data> {
|
|
|
22
25
|
/**
|
|
23
26
|
* Update data in a database.
|
|
24
27
|
*/
|
|
25
|
-
update(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<
|
|
28
|
+
update(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<D[]>;
|
|
26
29
|
/**
|
|
27
30
|
* Update one data entry in a database.
|
|
28
31
|
*/
|
|
29
|
-
updateOne(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<
|
|
32
|
+
updateOne(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<D>;
|
|
30
33
|
/**
|
|
31
34
|
* Remove data from a database.
|
|
32
35
|
*/
|
|
33
|
-
remove(search: Search<D>, context?: VContext): Promise<
|
|
36
|
+
remove(search: Search<D>, context?: VContext): Promise<D[]>;
|
|
34
37
|
/**
|
|
35
38
|
* Remove one data entry from a database.
|
|
36
39
|
*/
|
|
37
|
-
removeOne(search: Search<D>, context?: VContext): Promise<
|
|
40
|
+
removeOne(search: Search<D>, context?: VContext): Promise<D>;
|
|
38
41
|
/**
|
|
39
42
|
* Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
|
|
40
43
|
*/
|
|
41
|
-
updateOneOrAdd(search: Search<D>, updater: Updater<D>, { add_arg, context, id_gen }?: UpdateOneOrAdd<D>): Promise<
|
|
44
|
+
updateOneOrAdd(search: Search<D>, updater: Updater<D>, { add_arg, context, id_gen }?: UpdateOneOrAdd<D>): Promise<D>;
|
|
42
45
|
/**
|
|
43
46
|
* Asynchronously removes one entry in a database or adds a new one if it doesn't exist. Usage e.g. for toggling a flag.
|
|
44
47
|
*/
|
|
45
|
-
toggleOne(search: Search<D>, data?: Arg<D>, context?: VContext): Promise<
|
|
48
|
+
toggleOne(search: Search<D>, data?: Arg<D>, context?: VContext): Promise<D>;
|
|
46
49
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export class Collection {
|
|
2
|
+
db;
|
|
3
|
+
collection;
|
|
4
|
+
constructor(db, collection) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
this.collection = collection;
|
|
7
|
+
}
|
|
8
|
+
add(data, id_gen) {
|
|
9
|
+
return this.db.add({ collection: this.collection, data, id_gen });
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Find data in a database.
|
|
13
|
+
*/
|
|
14
|
+
find(search = {}, options = {}, findOpts = {}, context = {}) {
|
|
15
|
+
return this.db.find({ collection: this.collection, search, dbFindOpts: options, findOpts, context });
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Find one data entry in a database.
|
|
19
|
+
*/
|
|
20
|
+
findOne(search = {}, findOpts = {}, context = {}) {
|
|
21
|
+
return this.db.findOne({ collection: this.collection, search, findOpts, context });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Update data in a database.
|
|
25
|
+
*/
|
|
26
|
+
update(search, updater, context = {}) {
|
|
27
|
+
return this.db.update({ collection: this.collection, search, updater, context });
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Update one data entry in a database.
|
|
31
|
+
*/
|
|
32
|
+
updateOne(search, updater, context = {}) {
|
|
33
|
+
return this.db.updateOne({ collection: this.collection, search, updater, context });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Remove data from a database.
|
|
37
|
+
*/
|
|
38
|
+
remove(search, context = {}) {
|
|
39
|
+
return this.db.remove({ collection: this.collection, search, context });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Remove one data entry from a database.
|
|
43
|
+
*/
|
|
44
|
+
removeOne(search, context = {}) {
|
|
45
|
+
return this.db.removeOne({ collection: this.collection, search, context });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
|
|
49
|
+
*/
|
|
50
|
+
updateOneOrAdd(search, updater, { add_arg = {}, context = {}, id_gen = true } = {}) {
|
|
51
|
+
return this.db.updateOneOrAdd({ collection: this.collection, search, updater, add_arg, context, id_gen });
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Asynchronously removes one entry in a database or adds a new one if it doesn't exist. Usage e.g. for toggling a flag.
|
|
55
|
+
*/
|
|
56
|
+
toggleOne(search, data = {}, context = {}) {
|
|
57
|
+
return this.db.toggleOne({ collection: this.collection, search, data, context });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface Task {
|
|
1
|
+
export interface Task {
|
|
2
2
|
func: Function;
|
|
3
3
|
param: any[];
|
|
4
4
|
resolve: Function;
|
|
@@ -8,7 +8,7 @@ interface Task {
|
|
|
8
8
|
* A simple executor for queuing and executing asynchronous operations sequentially.
|
|
9
9
|
* @class
|
|
10
10
|
*/
|
|
11
|
-
declare class
|
|
11
|
+
export declare class Executor {
|
|
12
12
|
quote: Task[];
|
|
13
13
|
isExecuting: boolean;
|
|
14
14
|
/**
|
|
@@ -25,5 +25,3 @@ declare class ExecutorC {
|
|
|
25
25
|
*/
|
|
26
26
|
execute(): Promise<void>;
|
|
27
27
|
}
|
|
28
|
-
export default ExecutorC;
|
|
29
|
-
export { ExecutorC as executorC };
|
package/dist/helpers/executor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A simple executor for queuing and executing asynchronous operations sequentially.
|
|
3
3
|
* @class
|
|
4
4
|
*/
|
|
5
|
-
class
|
|
5
|
+
export class Executor {
|
|
6
6
|
quote;
|
|
7
7
|
isExecuting;
|
|
8
8
|
/**
|
|
@@ -42,5 +42,3 @@ class ExecutorC {
|
|
|
42
42
|
this.isExecuting = false;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
export default ExecutorC;
|
|
46
|
-
export { ExecutorC as executorC };
|
package/dist/helpers/forge.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import Data from "../types/data.js";
|
|
1
|
+
import { Collection } from "./collection.js";
|
|
2
|
+
import { Data } from "../types/data.js";
|
|
3
3
|
import { ValtheraCompatible } from "../types/valthera.js";
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
4
|
+
import { ValtheraClass } from "../db/valthera.js";
|
|
5
|
+
export declare function forgeValthera<T extends string>(target: ValtheraClass): ValtheraClass & {
|
|
6
|
+
[K in T]: Collection;
|
|
7
|
+
};
|
|
8
|
+
export declare function forgeValthera<T extends string>(target: ValtheraCompatible): ValtheraCompatible & {
|
|
9
|
+
[K in T]: Collection;
|
|
10
|
+
};
|
|
11
|
+
export declare function forgeTypedValthera<T extends Record<string, Data>>(target: ValtheraClass): ValtheraClass & {
|
|
12
|
+
[K in keyof T]: Collection<T[K]>;
|
|
13
|
+
};
|
|
14
|
+
export declare function forgeTypedValthera<T extends Record<string, Data>>(target: ValtheraCompatible): ValtheraCompatible & {
|
|
15
|
+
[K in keyof T]: Collection<T[K]>;
|
|
16
|
+
};
|
package/dist/helpers/forge.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Collection } from "./collection.js";
|
|
2
2
|
export function forgeValthera(target) {
|
|
3
3
|
return new Proxy(target, {
|
|
4
4
|
get(target, prop, receiver) {
|
|
5
5
|
if (prop in target) {
|
|
6
6
|
return Reflect.get(target, prop, receiver);
|
|
7
7
|
}
|
|
8
|
-
const collection = new
|
|
8
|
+
const collection = new Collection(target, prop);
|
|
9
9
|
target[prop] = collection;
|
|
10
10
|
return collection;
|
|
11
11
|
},
|
package/dist/helpers/gen.d.ts
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { Id } from "../types/Id.js";
|
|
2
|
+
export declare function getIdData(): {
|
|
3
|
+
usedIds: Map<any, any>;
|
|
4
|
+
lastId: Id;
|
|
5
|
+
recentIdsTimestamps: number[];
|
|
6
|
+
startIndex: number;
|
|
7
|
+
lastGeneratedMs: number;
|
|
8
|
+
lastRandomValue: number;
|
|
9
|
+
};
|
|
10
|
+
export type IdData = ReturnType<typeof getIdData>;
|
|
2
11
|
/**
|
|
3
12
|
* Generates a unique random identifier based on time and parts.
|
|
4
13
|
*
|
|
5
14
|
* @param {number[]} [parts] - an array of lengths of parts of the identifier
|
|
6
15
|
* @returns {Id} - a new unique identifier
|
|
7
16
|
*/
|
|
8
|
-
export
|
|
17
|
+
export declare function genId(parts?: number[], idData?: {
|
|
18
|
+
usedIds: Map<any, any>;
|
|
19
|
+
lastId: Id;
|
|
20
|
+
recentIdsTimestamps: number[];
|
|
21
|
+
startIndex: number;
|
|
22
|
+
lastGeneratedMs: number;
|
|
23
|
+
lastRandomValue: number;
|
|
24
|
+
}): Id;
|
package/dist/helpers/gen.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export function getIdData() {
|
|
2
|
+
return {
|
|
3
|
+
usedIds: new Map(),
|
|
4
|
+
lastId: undefined,
|
|
5
|
+
recentIdsTimestamps: [],
|
|
6
|
+
startIndex: 0,
|
|
7
|
+
lastGeneratedMs: 0,
|
|
8
|
+
lastRandomValue: 0,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const defaultIdData = getIdData();
|
|
7
12
|
/**
|
|
8
13
|
* Generates a unique random identifier based on time and parts.
|
|
9
14
|
*
|
|
10
15
|
* @param {number[]} [parts] - an array of lengths of parts of the identifier
|
|
11
16
|
* @returns {Id} - a new unique identifier
|
|
12
17
|
*/
|
|
13
|
-
export
|
|
18
|
+
export function genId(parts = null, idData = defaultIdData) {
|
|
14
19
|
if (parts === null)
|
|
15
20
|
parts = [1, 1];
|
|
16
21
|
const time = getTime();
|
|
@@ -18,17 +23,17 @@ export default function genId(parts = null) {
|
|
|
18
23
|
time,
|
|
19
24
|
partsSchema: parts,
|
|
20
25
|
s: 0,
|
|
21
|
-
});
|
|
26
|
+
}, idData);
|
|
22
27
|
return id;
|
|
23
28
|
}
|
|
24
29
|
/**
|
|
25
30
|
* Generates a unique random identifier based on time and parts.
|
|
26
31
|
*/
|
|
27
|
-
function getUniqueRandom(opts) {
|
|
32
|
+
function getUniqueRandom(opts, idData) {
|
|
28
33
|
while (true) {
|
|
29
34
|
let minValue = 0;
|
|
30
|
-
if (lastId) {
|
|
31
|
-
const parts = lastId.split("-");
|
|
35
|
+
if (idData.lastId) {
|
|
36
|
+
const parts = idData.lastId.split("-");
|
|
32
37
|
const lastTime = parts.shift();
|
|
33
38
|
if (lastTime === opts.time) {
|
|
34
39
|
const int36 = parts.join("");
|
|
@@ -36,13 +41,13 @@ function getUniqueRandom(opts) {
|
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
const partsLengthSum = opts.partsSchema.reduce((acc, num) => acc + num, 0);
|
|
39
|
-
const partsData = generateBase36InRange(minValue, partsLengthSum);
|
|
44
|
+
const partsData = generateBase36InRange(minValue, partsLengthSum, idData);
|
|
40
45
|
const parts = splitStringByArray(opts.partsSchema, partsData);
|
|
41
46
|
const id = [opts.time, ...parts].join("-");
|
|
42
|
-
if (!
|
|
43
|
-
|
|
44
|
-
setTimeout(() =>
|
|
45
|
-
lastId = id;
|
|
47
|
+
if (!idData.usedIds.has(id)) {
|
|
48
|
+
idData.usedIds.set(id, true);
|
|
49
|
+
setTimeout(() => idData.usedIds.delete(id), 1000);
|
|
50
|
+
idData.lastId = id;
|
|
46
51
|
return id;
|
|
47
52
|
}
|
|
48
53
|
opts.s++;
|
|
@@ -56,13 +61,14 @@ function getUniqueRandom(opts) {
|
|
|
56
61
|
* Tracks the current load of the application by counting the number of ids that have been generated in the last second.
|
|
57
62
|
* @returns The number of ids that have been generated in the last second.
|
|
58
63
|
*/
|
|
59
|
-
function trackLoad() {
|
|
64
|
+
function trackLoad(idData) {
|
|
60
65
|
const now = Date.now();
|
|
61
|
-
recentIdsTimestamps.push(now);
|
|
62
|
-
while (startIndex < recentIdsTimestamps.length &&
|
|
63
|
-
startIndex
|
|
66
|
+
idData.recentIdsTimestamps.push(now);
|
|
67
|
+
while (idData.startIndex < idData.recentIdsTimestamps.length &&
|
|
68
|
+
idData.recentIdsTimestamps[idData.startIndex] < now - 1) {
|
|
69
|
+
idData.startIndex++;
|
|
64
70
|
}
|
|
65
|
-
return recentIdsTimestamps.length - startIndex;
|
|
71
|
+
return idData.recentIdsTimestamps.length - idData.startIndex;
|
|
66
72
|
}
|
|
67
73
|
/**
|
|
68
74
|
* Generates a base-36 encoded string with a specified length based on a random value within a range.
|
|
@@ -77,27 +83,27 @@ function trackLoad() {
|
|
|
77
83
|
* @param length - The length of the resulting base-36 string.
|
|
78
84
|
* @returns A base-36 encoded string representation of the random value, padded to the specified length.
|
|
79
85
|
*/
|
|
80
|
-
function generateBase36InRange(minValue, length) {
|
|
86
|
+
function generateBase36InRange(minValue, length, idData) {
|
|
81
87
|
const maxValue = Math.pow(36, length) - 1;
|
|
82
|
-
const load = trackLoad();
|
|
88
|
+
const load = trackLoad(idData);
|
|
83
89
|
const currentMs = Date.now();
|
|
84
|
-
if (load < 3 || currentMs !== lastGeneratedMs) {
|
|
85
|
-
lastRandomValue = biasedRandomInRange(minValue, maxValue);
|
|
86
|
-
lastGeneratedMs = currentMs;
|
|
90
|
+
if (load < 3 || currentMs !== idData.lastGeneratedMs) {
|
|
91
|
+
idData.lastRandomValue = biasedRandomInRange(minValue, maxValue);
|
|
92
|
+
idData.lastGeneratedMs = currentMs;
|
|
87
93
|
}
|
|
88
94
|
else {
|
|
89
95
|
const rand = Math.random();
|
|
90
96
|
if (rand < 0.6) {
|
|
91
|
-
lastRandomValue += 1;
|
|
97
|
+
idData.lastRandomValue += 1;
|
|
92
98
|
}
|
|
93
99
|
else if (rand < 0.9) {
|
|
94
|
-
lastRandomValue += 2;
|
|
100
|
+
idData.lastRandomValue += 2;
|
|
95
101
|
}
|
|
96
102
|
else {
|
|
97
|
-
lastRandomValue = biasedRandomInRange(lastRandomValue, maxValue);
|
|
103
|
+
idData.lastRandomValue = biasedRandomInRange(idData.lastRandomValue, maxValue);
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
|
-
return lastRandomValue.toString(36).padStart(length, "0");
|
|
106
|
+
return idData.lastRandomValue.toString(36).padStart(length, "0");
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
109
|
* Generates a random number between the specified range, but with a bias towards the lower
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Search } from "../types/arg.js";
|
|
2
2
|
import { DbFindOpts } from "../types/options.js";
|
|
3
3
|
import { RelationTypes } from "../types/relation.js";
|
|
4
|
-
declare
|
|
4
|
+
export declare function pickByPath(obj: any, paths: string[][]): any;
|
|
5
|
+
export declare function autoSelect(rel: RelationTypes.RelationConfig, key: string): [string[] | undefined, boolean];
|
|
6
|
+
export declare function convertSearchObjToSearchArray(obj: Record<string, any>, parentKeys?: string[]): string[][];
|
|
7
|
+
export declare function processRelations(dbs: RelationTypes.DBS, cfg: RelationTypes.Relation, data: any, parentList?: any[] | null): Promise<void>;
|
|
8
|
+
export declare class Relation {
|
|
5
9
|
dbs: RelationTypes.DBS;
|
|
6
10
|
constructor(dbs: RelationTypes.DBS);
|
|
7
11
|
findOne(path: RelationTypes.Path, search: Search, relations: RelationTypes.Relation, select?: string[][] | Record<string, any>): Promise<any>;
|
|
8
12
|
find(path: RelationTypes.Path, search: Search, relations: RelationTypes.Relation, select?: string[][] | Record<string, any>, dbFindOpts?: DbFindOpts): Promise<any[]>;
|
|
9
13
|
}
|
|
10
|
-
export default Relation;
|
package/dist/helpers/relation.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function pickByPath(obj, paths) {
|
|
1
|
+
export function pickByPath(obj, paths) {
|
|
2
2
|
const result = {};
|
|
3
3
|
for (const path of paths) {
|
|
4
4
|
let src = obj;
|
|
@@ -19,14 +19,14 @@ function pickByPath(obj, paths) {
|
|
|
19
19
|
}
|
|
20
20
|
return result;
|
|
21
21
|
}
|
|
22
|
-
function autoSelect(rel, key) {
|
|
22
|
+
export function autoSelect(rel, key) {
|
|
23
23
|
const select = Array.isArray(rel.select) ? [...rel.select] : undefined;
|
|
24
24
|
const shouldDelete = select && !select.includes(key);
|
|
25
25
|
if (shouldDelete)
|
|
26
26
|
select.push(key);
|
|
27
27
|
return [select, shouldDelete];
|
|
28
28
|
}
|
|
29
|
-
function convertSearchObjToSearchArray(obj, parentKeys = []) {
|
|
29
|
+
export function convertSearchObjToSearchArray(obj, parentKeys = []) {
|
|
30
30
|
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
31
31
|
const currentPath = [...parentKeys, key];
|
|
32
32
|
if (!value) {
|
|
@@ -40,7 +40,7 @@ function convertSearchObjToSearchArray(obj, parentKeys = []) {
|
|
|
40
40
|
}
|
|
41
41
|
}, []);
|
|
42
42
|
}
|
|
43
|
-
async function processRelations(dbs, cfg, data, parentList = null) {
|
|
43
|
+
export async function processRelations(dbs, cfg, data, parentList = null) {
|
|
44
44
|
if (!data && !parentList)
|
|
45
45
|
return;
|
|
46
46
|
const batchMode = Array.isArray(parentList);
|
|
@@ -49,19 +49,22 @@ async function processRelations(dbs, cfg, data, parentList = null) {
|
|
|
49
49
|
if (!cfg.hasOwnProperty(key))
|
|
50
50
|
continue;
|
|
51
51
|
const rel = cfg[key];
|
|
52
|
-
const { pk = "_id", fk = "_id", type = "1", path, as = key, select,
|
|
53
|
-
const [dbKey,
|
|
52
|
+
const { pk = "_id", fk = "_id", type = "1", path, as = key, select, dbFindOpts = {}, through } = rel;
|
|
53
|
+
const [dbKey, collection] = path;
|
|
54
54
|
const db = dbs[dbKey];
|
|
55
55
|
if (type === "1") {
|
|
56
56
|
const keys = [...new Set(targets.map(i => i[pk]))];
|
|
57
57
|
const [selectSafe, deleteSelect] = autoSelect(rel, fk);
|
|
58
|
-
const results = await db.find(
|
|
58
|
+
const results = await db.find({
|
|
59
|
+
collection,
|
|
60
|
+
search: { $in: { [fk]: keys } },
|
|
61
|
+
findOpts: { select: selectSafe }
|
|
62
|
+
});
|
|
59
63
|
const map = new Map(results.map(row => [row[fk], row]));
|
|
60
64
|
for (const item of targets) {
|
|
61
65
|
const result = map.get(item[pk]) || null;
|
|
62
|
-
if (result && rel.relations)
|
|
66
|
+
if (result && rel.relations)
|
|
63
67
|
await processRelations(dbs, rel.relations, result);
|
|
64
|
-
}
|
|
65
68
|
if (deleteSelect && result)
|
|
66
69
|
delete result[fk];
|
|
67
70
|
item[as] = result;
|
|
@@ -72,13 +75,15 @@ async function processRelations(dbs, cfg, data, parentList = null) {
|
|
|
72
75
|
const [selectSafe, deleteSelect] = autoSelect(rel, fk);
|
|
73
76
|
for (const item of targets) {
|
|
74
77
|
const id = item[pk];
|
|
75
|
-
if (!cache.has(id))
|
|
76
|
-
cache.set(id, await db.findOne(
|
|
77
|
-
|
|
78
|
+
if (!cache.has(id))
|
|
79
|
+
cache.set(id, await db.findOne({
|
|
80
|
+
collection,
|
|
81
|
+
search: { [fk]: id },
|
|
82
|
+
findOpts: { select: selectSafe }
|
|
83
|
+
}));
|
|
78
84
|
const result = cache.get(id) || null;
|
|
79
|
-
if (result && rel.relations)
|
|
85
|
+
if (result && rel.relations)
|
|
80
86
|
await processRelations(dbs, rel.relations, result);
|
|
81
|
-
}
|
|
82
87
|
if (deleteSelect && result)
|
|
83
88
|
delete result[fk];
|
|
84
89
|
item[as] = result;
|
|
@@ -87,31 +92,40 @@ async function processRelations(dbs, cfg, data, parentList = null) {
|
|
|
87
92
|
else if (type === "1n") {
|
|
88
93
|
const ids = targets.map(i => i[pk]);
|
|
89
94
|
const [selectSafe, deleteSelect] = autoSelect(rel, fk);
|
|
90
|
-
const results = await db.find(
|
|
95
|
+
const results = await db.find({
|
|
96
|
+
collection,
|
|
97
|
+
search: { $in: { [fk]: ids } },
|
|
98
|
+
dbFindOpts,
|
|
99
|
+
findOpts: { select: selectSafe }
|
|
100
|
+
});
|
|
91
101
|
const grouped = results.reduce((acc, row) => {
|
|
92
102
|
const id = row[fk];
|
|
93
103
|
(acc[id] ||= []).push(row);
|
|
94
104
|
return acc;
|
|
95
105
|
}, {});
|
|
96
|
-
for (const item of targets)
|
|
106
|
+
for (const item of targets)
|
|
97
107
|
item[as] = grouped[item[pk]] || [];
|
|
98
|
-
|
|
99
|
-
if (rel.relations) {
|
|
108
|
+
if (rel.relations)
|
|
100
109
|
await Promise.all(results.map(row => processRelations(dbs, rel.relations, row)));
|
|
101
|
-
}
|
|
102
110
|
if (deleteSelect)
|
|
103
111
|
for (const r of results)
|
|
104
112
|
delete r[fk];
|
|
105
113
|
}
|
|
106
114
|
else if (type === "nm") {
|
|
107
|
-
if (!through || !through.table || !through.pk || !through.fk)
|
|
115
|
+
if (!through || !through.table || !through.pk || !through.fk)
|
|
108
116
|
throw new Error(`Relation type "nm" requires a defined "through" in "${key}"`);
|
|
109
|
-
}
|
|
110
117
|
for (const item of targets) {
|
|
111
118
|
const pivotDb = dbs[through.db || dbKey];
|
|
112
|
-
const pivots = await pivotDb.find(
|
|
119
|
+
const pivots = await pivotDb.find({
|
|
120
|
+
collection: through.table,
|
|
121
|
+
search: { [through.pk]: item[pk] }
|
|
122
|
+
});
|
|
113
123
|
const ids = pivots.map(p => p[through.fk]);
|
|
114
|
-
const related = await db.find(
|
|
124
|
+
const related = await db.find({
|
|
125
|
+
collection,
|
|
126
|
+
search: { $in: { [fk]: ids } },
|
|
127
|
+
findOpts: { select }
|
|
128
|
+
});
|
|
115
129
|
item[as] = related;
|
|
116
130
|
if (rel.relations) {
|
|
117
131
|
await Promise.all(related.map(row => processRelations(dbs, rel.relations, row)));
|
|
@@ -123,33 +137,30 @@ async function processRelations(dbs, cfg, data, parentList = null) {
|
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
}
|
|
126
|
-
class Relation {
|
|
140
|
+
export class Relation {
|
|
127
141
|
dbs;
|
|
128
142
|
constructor(dbs) {
|
|
129
143
|
this.dbs = dbs;
|
|
130
144
|
}
|
|
131
145
|
async findOne(path, search, relations, select) {
|
|
132
|
-
const [dbKey,
|
|
146
|
+
const [dbKey, collection] = path;
|
|
133
147
|
const db = this.dbs[dbKey];
|
|
134
|
-
const data = await db.findOne(
|
|
148
|
+
const data = await db.findOne({ collection, search });
|
|
135
149
|
if (!data)
|
|
136
150
|
return null;
|
|
137
|
-
if (typeof select === "object" && !Array.isArray(select))
|
|
151
|
+
if (typeof select === "object" && !Array.isArray(select))
|
|
138
152
|
select = convertSearchObjToSearchArray(select);
|
|
139
|
-
}
|
|
140
153
|
await processRelations(this.dbs, relations, data);
|
|
141
154
|
return select ? pickByPath(data, select) : data;
|
|
142
155
|
}
|
|
143
156
|
async find(path, search, relations, select, dbFindOpts = {}) {
|
|
144
|
-
const [dbKey,
|
|
157
|
+
const [dbKey, collection] = path;
|
|
145
158
|
const db = this.dbs[dbKey];
|
|
146
|
-
const data = await db.find(
|
|
159
|
+
const data = await db.find({ collection, search, dbFindOpts });
|
|
147
160
|
if (relations)
|
|
148
161
|
await processRelations(this.dbs, relations, null, data);
|
|
149
|
-
if (typeof select === "object" && !Array.isArray(select))
|
|
162
|
+
if (typeof select === "object" && !Array.isArray(select))
|
|
150
163
|
select = convertSearchObjToSearchArray(select);
|
|
151
|
-
}
|
|
152
164
|
return select ? data.map(d => pickByPath(d, select)) : data;
|
|
153
165
|
}
|
|
154
166
|
}
|
|
155
|
-
export default Relation;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export {
|
|
12
|
-
export type { RelationTypes, ValtheraCompatible, ValtheraTypes, };
|
|
13
|
-
export type Id = import("./types/Id.js").Id;
|
|
1
|
+
export { CustomFileCpu } from "./customFileCpu.js";
|
|
2
|
+
export { createMemoryValthera, ValtheraMemory } from "./db/memory.js";
|
|
3
|
+
export { ValtheraClass } from "./db/valthera.js";
|
|
4
|
+
export { forgeTypedValthera, forgeValthera } from "./helpers/forge.js";
|
|
5
|
+
export { genId } from "./helpers/gen.js";
|
|
6
|
+
export { Relation } from "./helpers/relation.js";
|
|
7
|
+
export { convertIdToUnix, sortByIds } from "./utils/id.js";
|
|
8
|
+
export type { ValtheraTypes } from "./types/export.js";
|
|
9
|
+
export type { Id } from "./types/Id.js";
|
|
10
|
+
export type { RelationTypes } from "./types/relation.js";
|
|
11
|
+
export type { ValtheraCompatible } from "./types/valthera.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export { createMemoryValthera, CustomFileCpu, forgeTypedValthera, forgeValthera, genId, Relation, ValtheraClass, ValtheraMemory, sortByIds, convertIdToUnix, };
|
|
1
|
+
export { CustomFileCpu } from "./customFileCpu.js";
|
|
2
|
+
export { createMemoryValthera, ValtheraMemory } from "./db/memory.js";
|
|
3
|
+
export { ValtheraClass } from "./db/valthera.js";
|
|
4
|
+
export { forgeTypedValthera, forgeValthera } from "./helpers/forge.js";
|
|
5
|
+
export { genId } from "./helpers/gen.js";
|
|
6
|
+
export { Relation } from "./helpers/relation.js";
|
|
7
|
+
export { convertIdToUnix, sortByIds } from "./utils/id.js";
|
package/dist/types/data.d.ts
CHANGED
package/dist/types/fileCpu.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Search, Updater } from "./arg.js";
|
|
2
|
-
import Data from "./data.js";
|
|
2
|
+
import { Data } from "./data.js";
|
|
3
3
|
import { FindOpts } from "./options.js";
|
|
4
4
|
import { VContext } from "./types.js";
|
|
5
|
-
interface FileCpu {
|
|
5
|
+
export interface FileCpu {
|
|
6
6
|
/**
|
|
7
7
|
* Asynchronously adds an entry to a file.
|
|
8
8
|
* @param file The path to the file.
|
|
@@ -18,7 +18,7 @@ interface FileCpu {
|
|
|
18
18
|
* @param findOpts Additional options for searching.
|
|
19
19
|
* @returns A promise resolving to an array of found entries, or `false` if the file does not exist.
|
|
20
20
|
*/
|
|
21
|
-
find(file: string, search: Search, context?: VContext, findOpts?: FindOpts): Promise<
|
|
21
|
+
find(file: string, search: Search, context?: VContext, findOpts?: FindOpts): Promise<Data[]>;
|
|
22
22
|
/**
|
|
23
23
|
* Asynchronously finds one entry in a file based on search criteria.
|
|
24
24
|
* @param file The path to the file.
|
|
@@ -27,7 +27,7 @@ interface FileCpu {
|
|
|
27
27
|
* @param findOpts Additional options for searching.
|
|
28
28
|
* @returns A promise resolving to the found entry or `false` if not found.
|
|
29
29
|
*/
|
|
30
|
-
findOne(file: string, search: Search, context?: VContext, findOpts?: FindOpts): Promise<
|
|
30
|
+
findOne(file: string, search: Search, context?: VContext, findOpts?: FindOpts): Promise<Data | false>;
|
|
31
31
|
/**
|
|
32
32
|
* Asynchronously removes entries from a file based on search criteria.
|
|
33
33
|
* @param file The path to the file.
|
|
@@ -36,7 +36,7 @@ interface FileCpu {
|
|
|
36
36
|
* @param one If `true`, removes only the first matching entry.
|
|
37
37
|
* @returns A promise resolving to `true` if at least one entry was removed, otherwise `false`.
|
|
38
38
|
*/
|
|
39
|
-
remove(file: string, one: boolean, search: Search, context?: VContext): Promise<
|
|
39
|
+
remove(file: string, one: boolean, search: Search, context?: VContext): Promise<Data[]>;
|
|
40
40
|
/**
|
|
41
41
|
* Asynchronously updates entries in a file based on search criteria and an updater function or object.
|
|
42
42
|
* @param file The path to the file.
|
|
@@ -46,6 +46,5 @@ interface FileCpu {
|
|
|
46
46
|
* @param one If `true`, updates only the first matching entry.
|
|
47
47
|
* @returns A promise resolving to `true` if at least one entry was updated, otherwise `false`.
|
|
48
48
|
*/
|
|
49
|
-
update(file: string, one: boolean, search: Search, updater: Updater, context?: VContext): Promise<
|
|
49
|
+
update(file: string, one: boolean, search: Search, updater: Updater, context?: VContext): Promise<Data[]>;
|
|
50
50
|
}
|
|
51
|
-
export default FileCpu;
|
package/dist/types/options.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import ActionsBase from "../base/actions.js";
|
|
2
|
-
import
|
|
1
|
+
import { ActionsBase } from "../base/actions.js";
|
|
2
|
+
import { Executor } from "../helpers/executor.js";
|
|
3
3
|
import { KeysMatching } from "./utils.js";
|
|
4
4
|
export interface DbOpts {
|
|
5
5
|
maxFileSize?: number;
|
|
6
6
|
dbAction?: ActionsBase;
|
|
7
|
-
executor?:
|
|
7
|
+
executor?: Executor;
|
|
8
8
|
numberId?: boolean;
|
|
9
9
|
}
|
|
10
10
|
export interface DbFindOpts<T = any> {
|