@wxn0brp/db-core 0.12.14 → 0.12.16

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.
@@ -1,5 +1,6 @@
1
1
  import { Collection } from "../helpers/collection.js";
2
2
  import { Data } from "../types/data.js";
3
+ import { IndexOpts } from "../types/idx.js";
3
4
  import { VQueryT } from "../types/query.js";
4
5
  import { TransactionHandle } from "../types/transaction.js";
5
6
  import { ValtheraClass } from "./valthera.js";
@@ -27,6 +28,9 @@ export declare class Transaction {
27
28
  issetCollection(collection: string | VQueryT.Collection): Promise<boolean>;
28
29
  getCollections(): Promise<string[]>;
29
30
  removeCollection(target: string | VQueryT.Collection): Promise<boolean>;
31
+ createIndex(collection: string, fields: string[], opts?: IndexOpts): Promise<unknown>;
32
+ removeIndex(collection: string, fields: string[]): Promise<unknown>;
33
+ capabilities(): Promise<import("../index.js").AdapterCapabilities>;
30
34
  commit(): Promise<void>;
31
35
  rollback(): Promise<void>;
32
36
  }
@@ -69,7 +69,33 @@ export class Transaction {
69
69
  return this._parent.execute("getCollections", {}, this.handle);
70
70
  }
71
71
  removeCollection(target) {
72
- return this._parent.execute("removeCollection", resolveCollection(target), this.handle);
72
+ const collection = resolveCollection(target);
73
+ this._parent._collections.delete(collection);
74
+ return this._parent.execute("removeCollection", collection, this.handle);
75
+ }
76
+ createIndex(collection, fields, opts) {
77
+ const index = {
78
+ collection,
79
+ fields,
80
+ opts,
81
+ };
82
+ return this._parent.execute("createIndex", {
83
+ collection,
84
+ index,
85
+ }, this.handle);
86
+ }
87
+ removeIndex(collection, fields) {
88
+ const index = {
89
+ collection,
90
+ fields,
91
+ };
92
+ return this._parent.execute("removeIndex", {
93
+ collection,
94
+ index,
95
+ }, this.handle);
96
+ }
97
+ capabilities() {
98
+ return this._parent.capabilities();
73
99
  }
74
100
  async commit() {
75
101
  try {
@@ -10,6 +10,7 @@ import { ValtheraPlugin } from "../types/plugin.js";
10
10
  import { VQuery, VQueryT } from "../types/query.js";
11
11
  import { TransactionHandle } from "../types/transaction.js";
12
12
  import { ValtheraCompatible } from "../types/valthera.js";
13
+ import { type DbOp } from "../utils/opKind.js";
13
14
  import { Transaction } from "./transaction.js";
14
15
  /**
15
16
  * Represents a database management class for performing CRUD operations.
@@ -20,9 +21,9 @@ export declare class ValtheraClass implements ValtheraCompatible {
20
21
  adapter: ActionsBase;
21
22
  executor: ExecutorInterface;
22
23
  emitter: VEE<{
23
- [K in keyof Omit<ValtheraCompatible, "c">]: (query: VQuery, result: Awaited<ReturnType<ValtheraCompatible[K]>>, collection?: string) => void;
24
+ [K in DbOp]: (query: VQuery, result: Awaited<ReturnType<ValtheraClass[K]>>, collection?: string) => void;
24
25
  } & {
25
- "*": (name: keyof Omit<ValtheraCompatible, "c">, query: VQuery, result: any, collection?: string) => void;
26
+ "*": (name: DbOp, query: VQuery, result: any, collection?: string) => void;
26
27
  }>;
27
28
  version: string;
28
29
  _plugins: ValtheraPlugin[];
@@ -31,7 +32,7 @@ export declare class ValtheraClass implements ValtheraCompatible {
31
32
  constructor(options: DbOpts);
32
33
  init(...args: any[]): Promise<any>;
33
34
  close(...args: any[]): Promise<any>;
34
- execute<T>(name: keyof ValtheraCompatible, query: VQuery<any> | string, txHandle?: TransactionHandle): Promise<T>;
35
+ execute<T>(name: DbOp, query: VQuery<any> | string, txHandle?: TransactionHandle): Promise<T>;
35
36
  /**
36
37
  * Create a new instance of a Collection class.
37
38
  */
@@ -321,17 +321,23 @@ export class ValtheraClass {
321
321
  async transaction(collections, fn) {
322
322
  await this.init();
323
323
  const releases = [];
324
- const promises = collections.map(collection => {
325
- let started;
326
- const startedPromise = new Promise(r => (started = r));
327
- this.executor.addOp(async () => {
328
- started();
329
- await new Promise(resolve => releases.push(resolve));
330
- }, undefined, collection);
331
- return startedPromise;
332
- });
333
- await Promise.all(promises);
324
+ const keys = this.executor instanceof SmartExecutor && this.executor.aware
325
+ ? [
326
+ ...new Set(collections),
327
+ ]
328
+ : [
329
+ undefined,
330
+ ];
331
+ if (!keys.length)
332
+ keys.push(undefined);
333
+ const acquire = (collection) => new Promise((resolve, reject) => this.executor
334
+ .addOp(async () => {
335
+ resolve();
336
+ await new Promise(release => releases.push(release));
337
+ }, undefined, collection)
338
+ .catch(reject));
334
339
  try {
340
+ await Promise.all(keys.map(acquire));
335
341
  let handle;
336
342
  try {
337
343
  handle = await this.adapter.beginTransaction(genId(), collections);
@@ -51,7 +51,7 @@ export class Collection {
51
51
  count(search = {}) {
52
52
  return this.db.count({
53
53
  collection: this.collection,
54
- search,
54
+ search: search,
55
55
  });
56
56
  }
57
57
  /**
@@ -1,10 +1,17 @@
1
1
  import { Data } from "./data.js";
2
+ import { IsStrict } from "./config.js";
2
3
  import { SearchOptions } from "./searchOpts.js";
3
4
  import { VContext } from "./types.js";
4
5
  import { UpdaterArg } from "./updater.js";
5
- export type Arg<T = any> = {
6
+ import { FieldsOf, WithId } from "./utils.js";
7
+ type LooseArg<T = any> = {
6
8
  [K in keyof T]?: any;
7
9
  } & Record<string, any>;
10
+ /**
11
+ * Data payload (e.g. for `add`).
12
+ * In strict mode fields and nested objects of `T` are allowed; otherwise any key is accepted.
13
+ */
14
+ export type Arg<T = any> = IsStrict extends true ? FieldsOf<WithId<T>> : LooseArg<T>;
8
15
  /**
9
16
  * Function-based search.
10
17
  * @deprecated Use operator objects or a plugin instead.
@@ -17,3 +24,4 @@ export type SearchFunc<T = any> = (data: T, context: VContext) => boolean;
17
24
  export type UpdaterFunc<T = any> = (data: T, context: VContext) => Data | void;
18
25
  export type Search<T = any, AllowFn extends boolean = true> = AllowFn extends true ? SearchOptions<T> | SearchFunc<T> : SearchOptions<T>;
19
26
  export type Updater<T = any, AllowFn extends boolean = true> = AllowFn extends true ? UpdaterArg<T> | UpdaterFunc<T> : UpdaterArg<T>;
27
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Enable strict mode.
3
+ * Currently opt-in, but will be enabled by default later.
4
+ *
5
+ * ```
6
+ * declare module "@wxn0brp/db-core/types/config" {
7
+ * interface TypeConfig {
8
+ * strict: true;
9
+ * }
10
+ * }
11
+ * ```
12
+ */
13
+ export interface TypeConfig {
14
+ }
15
+ export type IsStrict = TypeConfig extends {
16
+ strict: false;
17
+ } ? false : TypeConfig extends {
18
+ strict: true;
19
+ } ? true : false;
@@ -0,0 +1 @@
1
+ export {};
@@ -47,40 +47,40 @@ export declare namespace VQueryT {
47
47
  id_gen?: boolean;
48
48
  };
49
49
  type Find<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
50
- search?: Search<T, AllowFn>;
50
+ search?: NoInfer<Search<T, AllowFn>>;
51
51
  findOpts?: FindOpts<T>;
52
52
  dbFindOpts?: DbFindOpts<T>;
53
53
  /** @deprecated */
54
54
  context?: VContext;
55
55
  };
56
56
  type FindOne<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
57
- search: Search<T, AllowFn>;
57
+ search: NoInfer<Search<T, AllowFn>>;
58
58
  findOpts?: FindOpts<T>;
59
59
  /** @deprecated */
60
60
  context?: VContext;
61
61
  };
62
62
  type Update<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
63
- search: Search<T, AllowFn>;
64
- updater: Updater<T, AllowFn>;
63
+ search: NoInfer<Search<T, AllowFn>>;
64
+ updater: NoInfer<Updater<T, AllowFn>>;
65
65
  /** @deprecated */
66
66
  context?: VContext;
67
67
  };
68
68
  type Remove<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
69
- search: Search<T, AllowFn>;
69
+ search: NoInfer<Search<T, AllowFn>>;
70
70
  /** @deprecated */
71
71
  context?: VContext;
72
72
  };
73
73
  type UpdateOneOrAdd<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
74
- search: Search<T, AllowFn>;
75
- updater: Updater<T, AllowFn>;
76
- add_arg?: Arg<T>;
74
+ search: NoInfer<Search<T, AllowFn>>;
75
+ updater: NoInfer<Updater<T, AllowFn>>;
76
+ add_arg?: NoInfer<Arg<T>>;
77
77
  id_gen?: boolean;
78
78
  /** @deprecated */
79
79
  context?: VContext;
80
80
  };
81
81
  type ToggleOne<T = Data, AllowFn extends boolean = true> = QueryBase<T> & {
82
- search: Search<T, AllowFn>;
83
- data: Arg<T>;
82
+ search: NoInfer<Search<T, AllowFn>>;
83
+ data: NoInfer<Arg<T>>;
84
84
  /** @deprecated */
85
85
  context?: VContext;
86
86
  };
@@ -99,7 +99,7 @@ export declare namespace VQueryT {
99
99
  index: IndexDefinition;
100
100
  };
101
101
  type Count<T = Data> = QueryBase<T> & {
102
- search: Search<T, false>;
102
+ search: NoInfer<Search<T, false>>;
103
103
  };
104
104
  interface Collection {
105
105
  collection: string;
@@ -1,4 +1,5 @@
1
- import { DeepPartial, NestedValue } from "./utils.js";
1
+ import { IsStrict } from "./config.js";
2
+ import { DeepPartial, FieldsOf, NestedValue, WithId } from "./utils.js";
2
3
  export type JSPrimitiveType = "string" | "number" | "boolean" | "bigint" | "symbol" | "undefined" | "function" | "object";
3
4
  /** Logical Operators */
4
5
  export type LogicalOperators<T = any> = {
@@ -102,7 +103,4 @@ export type OtherOperators<T = any> = {
102
103
  };
103
104
  /** Predefined Search Operators */
104
105
  export type PredefinedSearchOperators<T = any> = LogicalOperators<T> & ComparisonOperators<T> & TypeAndExistenceOperators<T> & ArrayOperators<T> & StringOperators<T> & OtherOperators<T>;
105
- /**
106
- * SearchOptions can be either a function or an object with predefined operators.
107
- */
108
- export type SearchOptions<T = any> = PredefinedSearchOperators<T> & DeepPartial<T> & Record<string, any>;
106
+ export type SearchOptions<T = any> = IsStrict extends true ? FieldsOf<WithId<T>> & PredefinedSearchOperators<WithId<T>> : PredefinedSearchOperators<T> & DeepPartial<T> & Record<string, any>;
@@ -1,4 +1,5 @@
1
- import { DeepPartial, NestedValue } from "./utils.js";
1
+ import { IsStrict } from "./config.js";
2
+ import { DeepPartial, FieldsOf, NestedValue, WithId } from "./utils.js";
2
3
  /** Arrays */
3
4
  export type ArrayUpdater<T = any> = {
4
5
  /** [1,2] -> $push 3 -> [1,2,3] */
@@ -34,6 +35,6 @@ export type ValueUpdater<T = any> = {
34
35
  *
35
36
  * Note: same as { name: value }
36
37
  */
37
- $set?: NestedValue<T, any>;
38
+ $set?: IsStrict extends true ? FieldsOf<T> : NestedValue<T, any>;
38
39
  };
39
- export type UpdaterArg<T = any> = ArrayUpdater<T> & ObjectUpdater<T> & ValueUpdater<T> & DeepPartial<T> & Record<string, any>;
40
+ export type UpdaterArg<T = any> = IsStrict extends true ? ArrayUpdater<WithId<T>> & ObjectUpdater<WithId<T>> & ValueUpdater<WithId<T>> & FieldsOf<WithId<T>> : ArrayUpdater<T> & ObjectUpdater<T> & ValueUpdater<T> & DeepPartial<T> & Record<string, any>;
@@ -7,6 +7,17 @@ export type PartialPickMatching<T, V, C = V> = Partial<Pick<T, KeysMatching<T, V
7
7
  export type NestedValue<T, V, C = V> = {
8
8
  [K in keyof T as T[K] extends C ? K : T[K] extends object ? K : never]?: T[K] extends C ? V : T[K] extends object ? NestedValue<T[K], V, C> : never;
9
9
  };
10
+ export type Leaf = Date | RegExp | Function | readonly unknown[];
11
+ export type WithId<T> = T & {
12
+ _id?: string;
13
+ };
14
+ /**
15
+ * Plain fields of `T`: keys and nested partials.
16
+ * `$` operators are added on top of it by the query types.
17
+ */
18
+ export type FieldsOf<T> = {
19
+ [K in keyof T]?: T[K] extends Leaf ? T[K] : T[K] extends object ? FieldsOf<T[K]> | T[K] : T[K];
20
+ };
10
21
  /** Helper type for nested path structure */
11
22
  export type DeepPartial<T> = {
12
23
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
@@ -1,9 +1,36 @@
1
- export type PluginOpKind = "read" | "write" | "delete" | "collection" | "index" | "meta" | "control";
1
+ export type PluginOpKind = "read" | "write" | "delete" | "collection" | "index" | "meta" | "unknown" | "control";
2
+ export declare const OP_KINDS: {
3
+ readonly find: "read";
4
+ readonly findOne: "read";
5
+ readonly count: "read";
6
+ readonly add: "write";
7
+ readonly bulkAdd: "write";
8
+ readonly update: "write";
9
+ readonly updateOne: "write";
10
+ readonly updateOneOrAdd: "write";
11
+ readonly toggleOne: "write";
12
+ readonly remove: "delete";
13
+ readonly removeOne: "delete";
14
+ readonly ensureCollection: "collection";
15
+ readonly issetCollection: "collection";
16
+ readonly removeCollection: "collection";
17
+ readonly createIndex: "index";
18
+ readonly removeIndex: "index";
19
+ readonly getCollections: "meta";
20
+ readonly capabilities: "meta";
21
+ readonly beginTransaction: "control";
22
+ readonly commitTransaction: "control";
23
+ readonly rollbackTransaction: "control";
24
+ };
25
+ /** Every operation name known to the adapter contract. */
26
+ export type OpName = keyof typeof OP_KINDS;
27
+ /**
28
+ * Operations routed through {@link ValtheraClass.execute}.
29
+ */
30
+ export type DbOp = Exclude<OpName, "beginTransaction" | "commitTransaction" | "rollbackTransaction" | "capabilities">;
2
31
  export declare function getOpKind(op: string): PluginOpKind;
3
32
  export declare function isKnownOp(op: string): boolean;
4
- export declare function isMutation(kind: PluginOpKind): kind is "delete" | "write";
33
+ /** db[collection][op] */
5
34
  export declare function isCollectionOp(op: string): boolean;
6
- export declare function isIndexOp(op: string): boolean;
7
- export declare function isMetaOp(op: string): boolean;
8
- export declare function isControlOp(op: string): boolean;
9
- export declare function isNoQueryOp(op: string): boolean;
35
+ /** db[op] */
36
+ export declare function isDbOp(op: string): boolean;
@@ -1,4 +1,4 @@
1
- const OP_KINDS = {
1
+ export const OP_KINDS = {
2
2
  find: "read",
3
3
  findOne: "read",
4
4
  count: "read",
@@ -22,27 +22,22 @@ const OP_KINDS = {
22
22
  rollbackTransaction: "control",
23
23
  };
24
24
  export function getOpKind(op) {
25
- return Object.hasOwn(OP_KINDS, op) ? OP_KINDS[op] : "write";
25
+ return Object.hasOwn(OP_KINDS, op) ? OP_KINDS[op] : "unknown";
26
26
  }
27
27
  export function isKnownOp(op) {
28
28
  return Object.hasOwn(OP_KINDS, op);
29
29
  }
30
- export function isMutation(kind) {
31
- return kind === "write" || kind === "delete";
32
- }
30
+ const COLLECTION_OP_KINDS = new Set([
31
+ "read",
32
+ "write",
33
+ "delete",
34
+ "index",
35
+ ]);
36
+ /** db[collection][op] */
33
37
  export function isCollectionOp(op) {
34
- return getOpKind(op) === "collection";
35
- }
36
- export function isIndexOp(op) {
37
- return getOpKind(op) === "index";
38
- }
39
- export function isMetaOp(op) {
40
- return getOpKind(op) === "meta";
41
- }
42
- export function isControlOp(op) {
43
- return getOpKind(op) === "control";
38
+ return isKnownOp(op) && COLLECTION_OP_KINDS.has(getOpKind(op));
44
39
  }
45
- export function isNoQueryOp(op) {
46
- const kind = getOpKind(op);
47
- return kind === "collection" || kind === "meta";
40
+ /** db[op] */
41
+ export function isDbOp(op) {
42
+ return isKnownOp(op) && getOpKind(op) !== "control";
48
43
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.12.14";
1
+ export declare const version = "0.12.16";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "0.12.14";
1
+ export const version = "0.12.16";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/db-core",
3
- "version": "0.12.14",
3
+ "version": "0.12.16",
4
4
  "types": "dist/index.d.ts",
5
5
  "main": "dist/index.js",
6
6
  "author": "wxn0brP",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "homepage": "https://github.com/wxn0brP/ValtheraDB",
15
15
  "dependencies": {
16
- "@wxn0brp/event-emitter": "0.0.7"
16
+ "@wxn0brp/event-emitter": "0.0.9"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/bun": "*",