@wxn0brp/db-core 0.1.5 → 0.2.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/README.md CHANGED
@@ -12,6 +12,10 @@ It is **not recommended** to install this module separately unless you plan to c
12
12
  npm install @wxn0brp/db-core
13
13
  ```
14
14
 
15
+ ## Documentation
16
+
17
+ See the [documentation](docs/README.md) for more information about the API and usage.
18
+
15
19
  ## License
16
20
 
17
21
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,27 @@
1
+ import ActionsBase from "../base/actions.js";
2
+ import { VQuery } from "../types/query.js";
3
+ export type MatchRule = string | RegExp | ((query: VQuery) => boolean);
4
+ export interface RouteEntry {
5
+ match: MatchRule;
6
+ backends: ActionsBase[];
7
+ }
8
+ export declare class RoutedStorage extends ActionsBase {
9
+ rules: RouteEntry[];
10
+ defaultBackend: ActionsBase[];
11
+ constructor(rules: RouteEntry[], defaultBackend: ActionsBase | ActionsBase[]);
12
+ _matchBackends(config: VQuery): ActionsBase[];
13
+ _withAll<T>(config: VQuery, fn: (b: ActionsBase) => Promise<T>, gather?: boolean): Promise<T>;
14
+ _withFirst<T>(config: VQuery, fn: (b: ActionsBase) => Promise<T>): Promise<T>;
15
+ init(...args: any[]): Promise<void>;
16
+ add(config: VQuery): Promise<import("../types/data.js").Data>;
17
+ find(config: VQuery): Promise<import("../types/data.js").Data[]>;
18
+ findOne(config: VQuery): Promise<import("../types/data.js").Data>;
19
+ update(config: VQuery): Promise<boolean>;
20
+ updateOne(config: VQuery): Promise<boolean>;
21
+ remove(config: VQuery): Promise<boolean>;
22
+ removeOne(config: VQuery): Promise<boolean>;
23
+ ensureCollection(config: VQuery): Promise<boolean>;
24
+ issetCollection(config: VQuery): Promise<boolean>;
25
+ removeCollection(config: VQuery): Promise<boolean>;
26
+ getCollections(): Promise<string[]>;
27
+ }
@@ -0,0 +1,82 @@
1
+ import ActionsBase from "../base/actions.js";
2
+ export class RoutedStorage extends ActionsBase {
3
+ rules;
4
+ defaultBackend;
5
+ constructor(rules, defaultBackend) {
6
+ super();
7
+ this.rules = rules;
8
+ this.defaultBackend = Array.isArray(defaultBackend) ? defaultBackend : [defaultBackend];
9
+ }
10
+ _matchBackends(config) {
11
+ const matched = [];
12
+ const { collection } = config;
13
+ for (const rule of this.rules) {
14
+ const { match, backends } = rule;
15
+ if ((typeof match === "string" && (match === collection) || match === "*") ||
16
+ (match instanceof RegExp && match.test(collection)) ||
17
+ (typeof match === "function" && match(config))) {
18
+ matched.push(...backends);
19
+ }
20
+ }
21
+ if (matched.length === 0)
22
+ matched.push(...this.defaultBackend);
23
+ return matched;
24
+ }
25
+ async _withAll(config, fn, gather = false) {
26
+ const backends = this._matchBackends(config);
27
+ if (gather) {
28
+ return await Promise.all(backends.map(fn)).then(res => res[0]);
29
+ }
30
+ else {
31
+ for (const b of backends)
32
+ await fn(b);
33
+ return undefined;
34
+ }
35
+ }
36
+ async _withFirst(config, fn) {
37
+ const [first] = this._matchBackends(config);
38
+ return await fn(first);
39
+ }
40
+ async init(...args) {
41
+ const all = new Set(this.rules.flatMap(r => r.backends));
42
+ await Promise.all(Array.from(all).map(b => b.init?.(...args)));
43
+ }
44
+ async add(config) {
45
+ const res = await this._withFirst(config, b => b.add(config));
46
+ await this._withAll({ ...config, data: res }, b => b.add({ ...config, data: res }));
47
+ return res;
48
+ }
49
+ async find(config) {
50
+ return this._withFirst(config, b => b.find(config));
51
+ }
52
+ async findOne(config) {
53
+ return this._withFirst(config, b => b.findOne(config));
54
+ }
55
+ async update(config) {
56
+ return this._withAll(config, b => b.update(config), true);
57
+ }
58
+ async updateOne(config) {
59
+ return this._withAll(config, b => b.updateOne(config), true);
60
+ }
61
+ async remove(config) {
62
+ return this._withAll(config, b => b.remove(config), true);
63
+ }
64
+ async removeOne(config) {
65
+ return this._withAll(config, b => b.removeOne(config), true);
66
+ }
67
+ async ensureCollection(config) {
68
+ return this._withAll(config, b => b.ensureCollection(config), true);
69
+ }
70
+ async issetCollection(config) {
71
+ return this._withFirst(config, b => b.issetCollection(config));
72
+ }
73
+ async removeCollection(config) {
74
+ return this._withAll(config, b => b.removeCollection(config), true);
75
+ }
76
+ async getCollections() {
77
+ const all = await Promise.all(Array.from(new Set(this.rules.flatMap(r => r.backends)))
78
+ .map(b => b.getCollections()));
79
+ const merged = new Set(all.flat());
80
+ return Array.from(merged);
81
+ }
82
+ }
@@ -2,12 +2,12 @@ import { VEE } from "@wxn0brp/event-emitter";
2
2
  import ActionsBase from "../base/actions.js";
3
3
  import CollectionManager from "../helpers/CollectionManager.js";
4
4
  import executorC from "../helpers/executor.js";
5
- import { Arg, Search, Updater } from "../types/arg.js";
5
+ import { Search, Updater } from "../types/arg.js";
6
6
  import Data from "../types/data.js";
7
7
  import { DbFindOpts, DbOpts, FindOpts } from "../types/options.js";
8
8
  import { VQuery } from "../types/query.js";
9
9
  import { VContext } from "../types/types.js";
10
- import { ValtheraCompatible } from "../types/valthera.js";
10
+ import { UpdateOneOrAdd, ValtheraCompatible } from "../types/valthera.js";
11
11
  type DbActionsFns = keyof {
12
12
  [K in keyof ActionsBase as ActionsBase[K] extends (...args: any[]) => any ? K : never]: any;
13
13
  };
@@ -49,11 +49,11 @@ declare class ValtheraClass implements ValtheraCompatible {
49
49
  /**
50
50
  * Find data in a database.
51
51
  */
52
- find<T = Data>(collection: string, search?: Search<T>, context?: VContext, dbFindOpts?: DbFindOpts<T>, findOpts?: FindOpts<T>): Promise<T[]>;
52
+ find<T = Data>(collection: string, search?: Search<T>, dbFindOpts?: DbFindOpts<T>, findOpts?: FindOpts<T>, context?: VContext): Promise<T[]>;
53
53
  /**
54
54
  * Find one data entry in a database.
55
55
  */
56
- findOne<T = Data>(collection: string, search?: Search<T>, context?: VContext, findOpts?: FindOpts<T>): Promise<T>;
56
+ findOne<T = Data>(collection: string, search?: Search<T>, findOpts?: FindOpts<T>, context?: VContext): Promise<T>;
57
57
  /**
58
58
  * Update data in a database.
59
59
  */
@@ -73,7 +73,7 @@ declare class ValtheraClass implements ValtheraCompatible {
73
73
  /**
74
74
  * Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
75
75
  */
76
- updateOneOrAdd<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, add_arg?: Arg, context?: VContext, id_gen?: boolean): Promise<boolean>;
76
+ updateOneOrAdd<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, { add_arg, context, id_gen }: UpdateOneOrAdd<T>): Promise<boolean>;
77
77
  /**
78
78
  * Removes a database collection from the file system.
79
79
  */
@@ -66,13 +66,13 @@ class ValtheraClass {
66
66
  /**
67
67
  * Find data in a database.
68
68
  */
69
- async find(collection, search = {}, context = {}, dbFindOpts = {}, findOpts = {}) {
69
+ async find(collection, search = {}, dbFindOpts = {}, findOpts = {}, context = {}) {
70
70
  return await this.execute("find", { collection, search, context, dbFindOpts, findOpts });
71
71
  }
72
72
  /**
73
73
  * Find one data entry in a database.
74
74
  */
75
- async findOne(collection, search = {}, context = {}, findOpts = {}) {
75
+ async findOne(collection, search = {}, findOpts = {}, context = {}) {
76
76
  return await this.execute("findOne", { collection, search, context, findOpts });
77
77
  }
78
78
  /**
@@ -102,7 +102,7 @@ class ValtheraClass {
102
102
  /**
103
103
  * Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
104
104
  */
105
- async updateOneOrAdd(collection, search, updater, add_arg = {}, context = {}, id_gen = true) {
105
+ async updateOneOrAdd(collection, search, updater, { add_arg = {}, context = {}, id_gen = true }) {
106
106
  return await this.execute("updateOneOrAdd", { collection, search, updater, add_arg, context, id_gen });
107
107
  }
108
108
  /**
@@ -2,7 +2,7 @@ import { Arg, Search, Updater } from "../types/arg.js";
2
2
  import { DbFindOpts, FindOpts } from "../types/options.js";
3
3
  import { VContext } from "../types/types.js";
4
4
  import Data from "../types/data.js";
5
- import { ValtheraCompatible } from "../types/valthera.js";
5
+ import { UpdateOneOrAdd, ValtheraCompatible } from "../types/valthera.js";
6
6
  declare class CollectionManager<D = Data> {
7
7
  private db;
8
8
  private collection;
@@ -14,11 +14,11 @@ declare class CollectionManager<D = Data> {
14
14
  /**
15
15
  * Find data in a database.
16
16
  */
17
- find<T = Data>(search?: Search<T & D>, context?: VContext, options?: DbFindOpts<T & Data>, findOpts?: FindOpts<T & Data>): Promise<T[]>;
17
+ find<T = Data>(search?: Search<T & D>, options?: DbFindOpts<T & Data>, findOpts?: FindOpts<T & Data>, context?: VContext): Promise<T[]>;
18
18
  /**
19
19
  * Find one data entry in a database.
20
20
  */
21
- findOne<T = Data>(search?: Search<T & Data>, context?: VContext, findOpts?: FindOpts<T & Data>): Promise<T>;
21
+ findOne<T = Data>(search?: Search<T & Data>, findOpts?: FindOpts<T & Data>, context?: VContext): Promise<T>;
22
22
  /**
23
23
  * Update data in a database.
24
24
  */
@@ -38,6 +38,6 @@ declare class CollectionManager<D = Data> {
38
38
  /**
39
39
  * Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
40
40
  */
41
- updateOneOrAdd<T = Data>(search: Search<T & Data>, updater: Updater<T & Data>, add_arg?: Arg<T & Data>, context?: VContext, id_gen?: boolean): Promise<boolean>;
41
+ updateOneOrAdd<T = Data>(search: Search<T & Data>, updater: Updater<T & Data>, { add_arg, context, id_gen }: UpdateOneOrAdd<T & Data>): Promise<boolean>;
42
42
  }
43
43
  export default CollectionManager;
@@ -14,14 +14,14 @@ class CollectionManager {
14
14
  /**
15
15
  * Find data in a database.
16
16
  */
17
- async find(search = {}, context = {}, options = {}, findOpts = {}) {
18
- return await this.db.find(this.collection, search, context, options, findOpts);
17
+ async find(search = {}, options = {}, findOpts = {}, context = {}) {
18
+ return await this.db.find(this.collection, search, options, findOpts, context);
19
19
  }
20
20
  /**
21
21
  * Find one data entry in a database.
22
22
  */
23
- async findOne(search = {}, context = {}, findOpts = {}) {
24
- return await this.db.findOne(this.collection, search, context, findOpts);
23
+ async findOne(search = {}, findOpts = {}, context = {}) {
24
+ return await this.db.findOne(this.collection, search, findOpts, context);
25
25
  }
26
26
  /**
27
27
  * Update data in a database.
@@ -50,8 +50,8 @@ class CollectionManager {
50
50
  /**
51
51
  * Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
52
52
  */
53
- async updateOneOrAdd(search, updater, add_arg = {}, context = {}, id_gen = true) {
54
- return await this.db.updateOneOrAdd(this.collection, search, updater, add_arg, context, id_gen);
53
+ async updateOneOrAdd(search, updater, { add_arg = {}, context = {}, id_gen = true }) {
54
+ return await this.db.updateOneOrAdd(this.collection, search, updater, { add_arg, context, id_gen });
55
55
  }
56
56
  }
57
57
  export default CollectionManager;
@@ -5,6 +5,6 @@ declare class Relation {
5
5
  dbs: RelationTypes.DBS;
6
6
  constructor(dbs: RelationTypes.DBS);
7
7
  findOne(path: RelationTypes.Path, search: Search, relations: RelationTypes.Relation, select?: string[][] | Record<string, any>): Promise<any>;
8
- find(path: RelationTypes.Path, search: Search, relations: RelationTypes.Relation, select?: string[][] | Record<string, any>, findOpts?: DbFindOpts): Promise<any[]>;
8
+ find(path: RelationTypes.Path, search: Search, relations: RelationTypes.Relation, select?: string[][] | Record<string, any>, dbFindOpts?: DbFindOpts): Promise<any[]>;
9
9
  }
10
10
  export default Relation;
@@ -32,7 +32,7 @@ function convertSearchObjToSearchArray(obj, parentKeys = []) {
32
32
  if (!value) {
33
33
  return acc;
34
34
  }
35
- else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
35
+ else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
36
36
  return [...acc, ...convertSearchObjToSearchArray(value, currentPath)];
37
37
  }
38
38
  else {
@@ -87,7 +87,7 @@ async function processRelations(dbs, cfg, data, parentList = null) {
87
87
  else if (type === "1n") {
88
88
  const ids = targets.map(i => i[pk]);
89
89
  const [selectSafe, deleteSelect] = autoSelect(rel, fk);
90
- const results = await db.find(coll, { $in: { [fk]: ids } }, {}, findOpts || {}, { select: selectSafe });
90
+ const results = await db.find(coll, { $in: { [fk]: ids } }, findOpts || {}, { select: selectSafe });
91
91
  const grouped = results.reduce((acc, row) => {
92
92
  const id = row[fk];
93
93
  (acc[id] ||= []).push(row);
@@ -105,7 +105,7 @@ async function processRelations(dbs, cfg, data, parentList = null) {
105
105
  }
106
106
  else if (type === "nm") {
107
107
  if (!through || !through.table || !through.pk || !through.fk) {
108
- throw new Error(`Relation type "nm" requires a defined 'through' in '${key}'`);
108
+ throw new Error(`Relation type "nm" requires a defined "through" in "${key}"`);
109
109
  }
110
110
  for (const item of targets) {
111
111
  const pivotDb = dbs[through.db || dbKey];
@@ -140,10 +140,10 @@ class Relation {
140
140
  await processRelations(this.dbs, relations, data);
141
141
  return select ? pickByPath(data, select) : data;
142
142
  }
143
- async find(path, search, relations, select, findOpts = {}) {
143
+ async find(path, search, relations, select, dbFindOpts = {}) {
144
144
  const [dbKey, coll] = path;
145
145
  const db = this.dbs[dbKey];
146
- const data = await db.find(coll, search, {}, findOpts);
146
+ const data = await db.find(coll, search, dbFindOpts);
147
147
  if (relations)
148
148
  await processRelations(this.dbs, relations, null, data);
149
149
  if (typeof select === "object" && !Array.isArray(select)) {
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ import { ValtheraTypes } from "./types/export.js";
7
7
  import { RelationTypes } from "./types/relation.js";
8
8
  import { ValtheraCompatible } from "./types/valthera.js";
9
9
  import { forgeTypedValthera, forgeValthera } from "./helpers/forge.js";
10
- import { sortByIds } from "./utils/sortId.js";
11
- export { createMemoryValthera, CustomFileCpu, forgeTypedValthera, forgeValthera, genId, Relation, ValtheraClass, ValtheraMemory, sortByIds, };
10
+ import { sortByIds, convertIdToUnix } from "./utils/id.js";
11
+ export { createMemoryValthera, CustomFileCpu, forgeTypedValthera, forgeValthera, genId, Relation, ValtheraClass, ValtheraMemory, sortByIds, convertIdToUnix, };
12
12
  export type { RelationTypes, ValtheraCompatible, ValtheraTypes, };
13
13
  export type Id = import("./types/Id.js").Id;
package/dist/index.js CHANGED
@@ -4,5 +4,5 @@ import ValtheraClass from "./db/valthera.js";
4
4
  import genId from "./helpers/gen.js";
5
5
  import Relation from "./helpers/relation.js";
6
6
  import { forgeTypedValthera, forgeValthera } from "./helpers/forge.js";
7
- import { sortByIds } from "./utils/sortId.js";
8
- export { createMemoryValthera, CustomFileCpu, forgeTypedValthera, forgeValthera, genId, Relation, ValtheraClass, ValtheraMemory, sortByIds, };
7
+ import { sortByIds, convertIdToUnix } from "./utils/id.js";
8
+ export { createMemoryValthera, CustomFileCpu, forgeTypedValthera, forgeValthera, genId, Relation, ValtheraClass, ValtheraMemory, sortByIds, convertIdToUnix, };
@@ -10,14 +10,19 @@ export interface ValtheraCompatible {
10
10
  ensureCollection(collection: string): Promise<boolean>;
11
11
  issetCollection(collection: string): Promise<boolean>;
12
12
  add<T = Data>(collection: string, data: Arg<T>, id_gen?: boolean): Promise<T>;
13
- find<T = Data>(collection: string, search: Search<T>, context?: VContext, options?: DbFindOpts<T>, findOpts?: FindOpts<T>): Promise<T[]>;
14
- findOne<T = Data>(collection: string, search: Search<T>, context?: VContext, findOpts?: FindOpts<T>): Promise<T | null>;
13
+ find<T = Data>(collection: string, search?: Search<T>, options?: DbFindOpts<T>, findOpts?: FindOpts<T>, context?: VContext): Promise<T[]>;
14
+ findOne<T = Data>(collection: string, search?: Search<T>, findOpts?: FindOpts<T>, context?: VContext): Promise<T | null>;
15
15
  update<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, context?: VContext): Promise<boolean>;
16
16
  updateOne<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, context?: VContext): Promise<boolean>;
17
17
  remove<T = Data>(collection: string, search: Search<T>, context?: VContext): Promise<boolean>;
18
18
  removeOne<T = Data>(collection: string, search: Search<T>, context?: VContext): Promise<boolean>;
19
19
  removeCollection(collection: string): Promise<boolean>;
20
- updateOneOrAdd<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, add_arg?: Arg<T>, context?: VContext, id_gen?: boolean): Promise<boolean>;
20
+ updateOneOrAdd<T = Data>(collection: string, search: Search<T>, updater: Updater<T>, opts: UpdateOneOrAdd<T>): Promise<boolean>;
21
+ }
22
+ export interface UpdateOneOrAdd<T> {
23
+ add_arg?: Arg<T>;
24
+ id_gen?: boolean;
25
+ context?: VContext;
21
26
  }
22
27
  export interface ValtheraCompatibleInternal {
23
28
  c(config: VQuery): CollectionManager;
@@ -1,3 +1,4 @@
1
+ export declare function convertIdToUnix(id: string): number;
1
2
  export declare function sortByIds<T extends {
2
3
  _id: string;
3
4
  }>(objects: T[]): T[];
@@ -0,0 +1,8 @@
1
+ export function convertIdToUnix(id) {
2
+ return parseInt(id.split("-")[0], 36);
3
+ }
4
+ export function sortByIds(objects) {
5
+ return objects.slice().sort((a, b) => {
6
+ return convertIdToUnix(a._id) - convertIdToUnix(b._id) || a._id.localeCompare(b._id);
7
+ });
8
+ }
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "0.1.5";
1
+ export const version = "0.2.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/db-core",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "types": "dist/index.d.ts",
5
5
  "main": "dist/index.js",
6
6
  "author": "wxn0brP",
@@ -12,6 +12,9 @@
12
12
  "url": "https://github.com/wxn0brP/ValtheraDB-core.git"
13
13
  },
14
14
  "homepage": "https://github.com/wxn0brP/ValtheraDB",
15
+ "dependencies": {
16
+ "@wxn0brp/event-emitter": "^0.0.2"
17
+ },
15
18
  "devDependencies": {
16
19
  "@types/node": "^24.2.0",
17
20
  "tsc-alias": "^1.8.10",
@@ -31,8 +34,5 @@
31
34
  "import": "./dist/*.js",
32
35
  "default": "./dist/*.js"
33
36
  }
34
- },
35
- "dependencies": {
36
- "@wxn0brp/event-emitter": "^0.0.2"
37
37
  }
38
38
  }
@@ -1,7 +0,0 @@
1
- export function sortByIds(objects) {
2
- return objects.slice().sort((a, b) => {
3
- const [timestampA] = a._id.split("-");
4
- const [timestampB] = b._id.split("-");
5
- return timestampA.localeCompare(timestampB) || a._id.localeCompare(b._id);
6
- });
7
- }