@wxn0brp/vql 0.9.0 → 0.10.2

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 wxn0brP
3
+ Copyright (c) 2026 wxn0brP
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,3 +1,4 @@
1
+ import { VQLConfig } from "../helpers/config.js";
1
2
  import { VQLProcessor } from "../processor.js";
2
3
  import { VQL_Query_Relation } from "../types/vql.js";
3
- export declare function executeRelation(cpu: VQLProcessor, query: VQL_Query_Relation, user: any): Promise<any>;
4
+ export declare function executeRelation(cpu: VQLProcessor, query: VQL_Query_Relation, user: any, cfg: VQLConfig): Promise<any>;
@@ -17,15 +17,15 @@ function checkDBsExist(cpu, req) {
17
17
  }
18
18
  return { err: false };
19
19
  }
20
- export async function executeRelation(cpu, query, user) {
20
+ export async function executeRelation(cpu, query, user, cfg) {
21
21
  const checkDb = checkDBsExist(cpu, query.r);
22
22
  if (checkDb.err)
23
23
  return checkDb;
24
- if (!cpu.config.noCheckPermissions && !await checkRelationPermission(cpu.config, cpu.permValidFn, user, query)) {
24
+ if (!cfg.noCheckPermissions && !await checkRelationPermission(cfg, cpu.permValidFn, user, query)) {
25
25
  return { err: true, msg: "Permission denied", c: 403 };
26
26
  }
27
27
  const req = query.r;
28
- standardizeRelationRequest(cpu.config, req);
28
+ standardizeRelationRequest(cfg, req);
29
29
  const { path, search, relations, select } = req;
30
30
  if (req.many) {
31
31
  return await cpu.relation.find(path, search, relations, select, req.options);
@@ -1,3 +1,4 @@
1
+ import { VQLConfig } from "../helpers/config.js";
1
2
  import { VQLProcessor } from "../processor.js";
2
3
  import { VQL_Query_CRUD } from "../types/vql.js";
3
- export declare function executeQuery(cpu: VQLProcessor, query: VQL_Query_CRUD, user: any): Promise<any>;
4
+ export declare function executeQuery(cpu: VQLProcessor, query: VQL_Query_CRUD, user: any, cfg: VQLConfig): Promise<any>;
@@ -1,26 +1,26 @@
1
+ import { LowAdapter } from "../helpers/lowAdapter.js";
1
2
  import { checkRequestPermission } from "../permissions/index.js";
2
3
  import { parseSelect } from "./utils.js";
3
- import { LowAdapter } from "../helpers/lowAdapter.js";
4
- export async function executeQuery(cpu, query, user) {
4
+ export async function executeQuery(cpu, query, user, cfg) {
5
5
  if (!query.db || !cpu.dbInstances[query.db])
6
6
  return { err: true, msg: `Invalid query - db "${query.db || "undefined"}" not found`, c: 400 };
7
7
  const db = cpu.dbInstances[query.db];
8
8
  if (db instanceof LowAdapter)
9
9
  return await db.resolver(query, user);
10
10
  const operation = Object.keys(query.d)[0];
11
- if (!cpu.config.noCheckPermissions && !await checkRequestPermission(cpu.config, cpu.permValidFn, user, query)) {
11
+ if (!cfg.noCheckPermissions && !await checkRequestPermission(cfg, cpu.permValidFn, user, query)) {
12
12
  return { err: true, msg: "Permission denied", c: 403 };
13
13
  }
14
14
  if (operation === "find") {
15
15
  const params = query.d[operation];
16
- const select = parseSelect(cpu.config, params.fields || params.select || {});
16
+ const select = parseSelect(cfg, params.fields || params.select || {});
17
17
  if (select && typeof select === "object" && Object.keys(select).length !== 0)
18
18
  params.searchOpts = { ...params.searchOpts, select };
19
19
  return db.find(params.collection, params.search, params.options || {}, params.searchOpts);
20
20
  }
21
21
  else if (operation === "findOne" || operation === "f") {
22
22
  const params = query.d[operation];
23
- const select = parseSelect(cpu.config, params.fields || params.select || {});
23
+ const select = parseSelect(cfg, params.fields || params.select || {});
24
24
  if (select && typeof select === "object" && Object.keys(select).length !== 0)
25
25
  params.searchOpts = { ...params.searchOpts, select };
26
26
  return db.findOne(params.collection, params.search, params.searchOpts);
@@ -1,6 +1,8 @@
1
1
  import { VQL_Query_CRUD_Keys } from "../types/vql.js";
2
2
  import { ValtheraCompatible } from "@wxn0brp/db-core";
3
- type ResolverFn<TArgs extends any[] = any[], TReturn = any> = (...args: TArgs) => Promise<TReturn>;
3
+ export type ResolverFn<TArgs extends any[] = any[], TReturn = any> = (...args: TArgs) => Promise<TReturn>;
4
+ export type DropFirstFromTuple<T extends any[]> = T extends [any, ...infer Rest] ? Rest : never;
5
+ export type DropFirst<T> = T extends (...args: infer Args) => infer R ? (...args: DropFirstFromTuple<Args>) => R : never;
4
6
  export interface ValtheraResolverMeta {
5
7
  type: "valthera" | "api" | "wrapper" | (string & {});
6
8
  version: string;
@@ -45,16 +47,25 @@ export declare class AdapterBuilder {
45
47
  private collections;
46
48
  constructor(catchCb?: (e: any, op: string, args: any[]) => void);
47
49
  register(op: Operation, collection: string, fn: Function): this;
48
- add(collection: string, fn: ValtheraResolver["add"]): this;
49
- find(collection: string, fn: ValtheraResolver["find"]): this;
50
- findOne(collection: string, fn: ValtheraResolver["findOne"]): this;
51
- update(collection: string, fn: ValtheraResolver["update"]): this;
52
- updateOne(collection: string, fn: ValtheraResolver["updateOne"]): this;
53
- updateOneOrAdd(collection: string, fn: ValtheraResolver["updateOneOrAdd"]): this;
54
- toggleOne(collection: string, fn: ValtheraResolver["toggleOne"]): this;
55
- remove(collection: string, fn: ValtheraResolver["remove"]): this;
56
- removeOne(collection: string, fn: ValtheraResolver["removeOne"]): this;
57
- removeCollection(collection: string, fn: ValtheraResolver["removeCollection"]): this;
50
+ add(collection: (string & {}), fn: DropFirst<ValtheraResolver["add"]>): this;
51
+ add(collection: "*", fn: ValtheraResolver["add"]): this;
52
+ find(collection: (string & {}), fn: DropFirst<ValtheraResolver["find"]>): this;
53
+ find(collection: "*", fn: ValtheraResolver["find"]): this;
54
+ findOne(collection: (string & {}), fn: DropFirst<ValtheraResolver["findOne"]>): this;
55
+ findOne(collection: "*", fn: ValtheraResolver["findOne"]): this;
56
+ update(collection: (string & {}), fn: DropFirst<ValtheraResolver["update"]>): this;
57
+ update(collection: "*", fn: ValtheraResolver["update"]): this;
58
+ updateOne(collection: (string & {}), fn: DropFirst<ValtheraResolver["updateOne"]>): this;
59
+ updateOne(collection: "*", fn: ValtheraResolver["updateOne"]): this;
60
+ updateOneOrAdd(collection: (string & {}), fn: DropFirst<ValtheraResolver["updateOneOrAdd"]>): this;
61
+ updateOneOrAdd(collection: "*", fn: ValtheraResolver["updateOneOrAdd"]): this;
62
+ toggleOne(collection: (string & {}), fn: DropFirst<ValtheraResolver["toggleOne"]>): this;
63
+ toggleOne(collection: "*", fn: ValtheraResolver["toggleOne"]): this;
64
+ remove(collection: (string & {}), fn: DropFirst<ValtheraResolver["remove"]>): this;
65
+ remove(collection: "*", fn: ValtheraResolver["remove"]): this;
66
+ removeOne(collection: (string & {}), fn: DropFirst<ValtheraResolver["removeOne"]>): this;
67
+ removeOne(collection: "*", fn: ValtheraResolver["removeOne"]): this;
68
+ removeCollection(collection: (string & {}), fn: DropFirst<ValtheraResolver["removeCollection"]>): this;
69
+ removeCollection(collection: "*", fn: ValtheraResolver["removeCollection"]): this;
58
70
  getAdapter(extendedFind?: boolean): ValtheraCompatible;
59
71
  }
60
- export {};
@@ -1,4 +1,4 @@
1
- import CollectionManager from "@wxn0brp/db-core/helpers/CollectionManager";
1
+ import { CollectionManager } from "@wxn0brp/db-core/helpers/collectionManager";
2
2
  import updateFindObject from "@wxn0brp/db-core/utils/updateFindObject";
3
3
  const list = [
4
4
  "ensureCollection", "issetCollection", "getCollections", "removeCollection",
@@ -1,5 +1,6 @@
1
1
  export function createGwValidFn(gw) {
2
2
  return async (args) => {
3
- return gw.hasAccess(args.user.id, args.field, args.p);
3
+ const res = await gw.hasAccess(args.user._id, args.field, args.p);
4
+ return { granted: res.granted, via: `gate-warden`, reason: res.via };
4
5
  };
5
6
  }
@@ -18,7 +18,7 @@ export async function checkRelationPermission(config, permValidFn, user, query)
18
18
  return true;
19
19
  }
20
20
  // If the result is "entity-404", check the next fallback level
21
- if (!config.strictACL && result.via === "entity-404" && fallbackLevels.length > 0) {
21
+ if (!config.strictACL && result.reason === "entity-404" && fallbackLevels.length > 0) {
22
22
  const nextFallbackEntityId = await hashKey(config, fallbackLevels.slice(0, -1));
23
23
  return checkPermissionRecursively(nextFallbackEntityId, fallbackLevels.slice(0, -2), fallbackLevels.slice(0, -2));
24
24
  }
@@ -106,7 +106,7 @@ export async function checkRequestPermission(config, permValidFn, user, query) {
106
106
  return true;
107
107
  }
108
108
  // If the result is "entity-404", check the next fallback level
109
- if (!config.strictACL && result.via === "entity-404" && fallbackLevels.length > 0) {
109
+ if (!config.strictACL && result.reason === "entity-404" && fallbackLevels.length > 0) {
110
110
  const nextFallbackEntityId = await hashKey(config, fallbackLevels.slice(0, -1));
111
111
  return checkPermissionRecursively(nextFallbackEntityId, fallbackLevels.slice(0, -2), requiredPerm, fallbackLevels.slice(0, -2));
112
112
  }
@@ -1,9 +1,9 @@
1
- import { PathMatcher, PermissionResolver } from "../types/resolver.js";
1
+ import { PathMatcher, PermissionResolver, ValidEngineOpts } from "../types/resolver.js";
2
2
  import { PermValidFn } from "../types/perm.js";
3
3
  import { GateWarden } from "@wxn0brp/gate-warden";
4
4
  export declare class PermissionResolverEngine {
5
5
  private resolvers;
6
- addResolver(matcher: PathMatcher, resolver: PermissionResolver): void;
6
+ addResolver(matcher: PathMatcher, resolver: PermissionResolver, opts?: ValidEngineOpts | ValidEngineOpts["stringMode"]): void;
7
7
  create(): PermValidFn;
8
8
  createWithGw(gw: GateWarden): PermValidFn;
9
9
  }
@@ -1,15 +1,25 @@
1
1
  export class PermissionResolverEngine {
2
2
  resolvers = [];
3
- addResolver(matcher, resolver) {
4
- this.resolvers.push({ matcher, resolver });
3
+ addResolver(matcher, resolver, opts = {}) {
4
+ if (typeof opts === "string")
5
+ opts = { stringMode: opts };
6
+ this.resolvers.push({ matcher, resolver, opts });
5
7
  }
6
8
  create() {
7
9
  return async (args) => {
8
10
  const originalPath = args.path.join("/");
9
- for (const { matcher, resolver } of this.resolvers) {
11
+ for (const { matcher, resolver, opts } of this.resolvers) {
10
12
  let isMatch = false;
11
13
  if (typeof matcher === "string") {
12
- isMatch = originalPath === matcher;
14
+ const { stringMode } = opts;
15
+ if (stringMode === "endsWith")
16
+ isMatch = originalPath.endsWith(matcher);
17
+ else if (stringMode === "startsWith")
18
+ isMatch = originalPath.startsWith(matcher);
19
+ else if (stringMode === "includes")
20
+ isMatch = originalPath.includes(matcher);
21
+ else
22
+ isMatch = originalPath === matcher;
13
23
  }
14
24
  else if (matcher instanceof RegExp) {
15
25
  isMatch = matcher.test(originalPath);
@@ -17,18 +27,18 @@ export class PermissionResolverEngine {
17
27
  else if (typeof matcher === "function") {
18
28
  isMatch = await matcher(originalPath, args.path);
19
29
  }
20
- if (isMatch) {
21
- try {
22
- const resolverGranted = await resolver(args);
23
- return { granted: resolverGranted, via: `resolver` };
24
- }
25
- catch (error) {
26
- console.error(`[Resolver Engine] Error in custom resolver for path ${originalPath}:`, error);
27
- return { granted: false, via: `resolver-error` };
28
- }
30
+ if (!isMatch)
31
+ continue;
32
+ try {
33
+ const resolverGranted = await resolver(args);
34
+ return { granted: resolverGranted, via: `resolver`, reason: "resolver" };
35
+ }
36
+ catch (error) {
37
+ console.error(`[Resolver Engine] Error in custom resolver for path ${originalPath}:`, error);
38
+ return { granted: false, via: `resolver`, reason: "resolver-error" };
29
39
  }
30
40
  }
31
- return { granted: false, via: `no-resolver-match` };
41
+ return { granted: false, via: `resolver`, reason: "no-resolver-match" };
32
42
  };
33
43
  }
34
44
  createWithGw(gw) {
@@ -37,10 +47,10 @@ export class PermissionResolverEngine {
37
47
  const resolverResult = await resolver(args);
38
48
  if (resolverResult.granted)
39
49
  return resolverResult;
40
- if (!resolverResult.granted && resolverResult.via !== `no-resolver-match`)
50
+ if (resolverResult.reason !== `no-resolver-match`)
41
51
  return resolverResult;
42
52
  const gwResult = await gw.hasAccess(args.user.id, args.field, args.p);
43
- return { granted: gwResult.granted, via: `gate-warden` };
53
+ return { granted: gwResult.granted, via: `gate-warden`, reason: gwResult.via };
44
54
  };
45
55
  }
46
56
  }
@@ -8,7 +8,7 @@ export declare class VQLProcessor {
8
8
  relation: Relation;
9
9
  config: VQLConfig;
10
10
  constructor(dbInstances: Record<string, ValtheraCompatible>, config?: VQLConfig | Partial<VQLConfigInterface>, permValidFn?: PermValidFn);
11
- execute<T = any>(queryRaw: VQLUQ<T>, user?: any): Promise<T | VQLError>;
11
+ execute<T = any>(queryRaw: VQLUQ<T>, user?: any, cfg?: VQLConfig): Promise<T | VQLError>;
12
12
  _preProcessQuery(queryRaw: VQLUQ, user: any): {
13
13
  err: VQLError;
14
14
  query?: undefined;
@@ -20,5 +20,5 @@ export declare class VQLProcessor {
20
20
  query?: VQL_Query;
21
21
  err?: VQLError;
22
22
  };
23
- _runQuery(query: VQL_Query, user: any): Promise<any>;
23
+ _runQuery(query: VQL_Query, user: any, cfg?: VQLConfig): Promise<any>;
24
24
  }
package/dist/processor.js CHANGED
@@ -11,17 +11,17 @@ export class VQLProcessor {
11
11
  permValidFn;
12
12
  relation;
13
13
  config;
14
- constructor(dbInstances, config = new VQLConfig(), permValidFn = async () => ({ granted: true, via: "" })) {
14
+ constructor(dbInstances, config = new VQLConfig(), permValidFn = async () => ({ granted: true, via: "resolver", reason: "no-resolver-match" })) {
15
15
  this.dbInstances = dbInstances;
16
16
  this.permValidFn = permValidFn;
17
17
  this.relation = new Relation(dbInstances);
18
18
  this.config = config instanceof VQLConfig ? config : new VQLConfig(config);
19
19
  }
20
- async execute(queryRaw, user = { _id: "null-null-null" }) {
20
+ async execute(queryRaw, user = { _id: "null-null-null" }, cfg = this.config) {
21
21
  const result = this._preProcessQuery(queryRaw, user);
22
22
  if ("err" in result)
23
23
  return result.err;
24
- return await this._runQuery(result.query, user);
24
+ return await this._runQuery(result.query, user, cfg);
25
25
  }
26
26
  _preProcessQuery(queryRaw, user) {
27
27
  const { query: parsedQuery, err: parseErr } = this._parseQuery(queryRaw);
@@ -68,12 +68,12 @@ export class VQLProcessor {
68
68
  }
69
69
  return { query: queryRaw };
70
70
  }
71
- async _runQuery(query, user) {
71
+ async _runQuery(query, user, cfg = this.config) {
72
72
  if ("r" in query) {
73
- return await executeRelation(this, query, user);
73
+ return await executeRelation(this, query, user, cfg);
74
74
  }
75
75
  else if ("d" in query) {
76
- return await executeQuery(this, query, user);
76
+ return await executeQuery(this, query, user, cfg);
77
77
  }
78
78
  else {
79
79
  return { err: true, msg: "Invalid query", c: 400 };
@@ -1,3 +1,4 @@
1
+ import { AccessResult } from "@wxn0brp/gate-warden";
1
2
  export declare enum PermCRUD {
2
3
  CREATE = 1,
3
4
  READ = 2,
@@ -7,7 +8,8 @@ export declare enum PermCRUD {
7
8
  }
8
9
  export interface ValidFnResult {
9
10
  granted: boolean;
10
- via?: string;
11
+ via?: "resolver" | "gate-warden";
12
+ reason?: AccessResult["via"] | "resolver" | "no-resolver-match" | "resolver-error";
11
13
  }
12
14
  export interface PermValidFnArgs {
13
15
  /** sha256/json */
@@ -7,8 +7,12 @@ export type PermissionResolver = (args: PermValidFnArgs) => Promise<boolean>;
7
7
  export interface ResolverEntry {
8
8
  matcher: PathMatcher;
9
9
  resolver: PermissionResolver;
10
+ opts: ValidEngineOpts;
10
11
  }
11
12
  export interface ResolverValidFnResult {
12
13
  granted: boolean;
13
14
  via: string;
14
15
  }
16
+ export interface ValidEngineOpts {
17
+ stringMode?: "equal" | "startsWith" | "endsWith" | "includes";
18
+ }
package/dist/vql.d.ts CHANGED
@@ -17,6 +17,7 @@ export type NestedValue<T, V, C = V> = {
17
17
  export type DeepPartial<T> = {
18
18
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
19
19
  };
20
+ export type JSPrimitiveType = "string" | "number" | "boolean" | "bigint" | "symbol" | "undefined" | "function" | "object";
20
21
  /** Logical Operators */
21
22
  export type LogicalOperators<T = any> = {
22
23
  /**
@@ -70,9 +71,9 @@ export type ComparisonOperators<T = any> = {
70
71
  /** Type and Existence Operators with nested support */
71
72
  export type TypeAndExistenceOperators<T = any> = {
72
73
  /** "name" in { name: "John" } */
73
- $exists?: NestedValue<T, boolean>;
74
+ $exists?: NestedValue<T, boolean, any>;
74
75
  /** "name" == "string" in { name: "John" } */
75
- $type?: NestedValue<T, string>;
76
+ $type?: NestedValue<T, JSPrimitiveType, any>;
76
77
  };
77
78
  /** Array Operators with nested support */
78
79
  export type ArrayOperators<T = any> = {
@@ -165,39 +166,39 @@ declare class CollectionManager<D = Data> {
165
166
  /**
166
167
  * Add data to a database.
167
168
  */
168
- add<T = Data>(data: Arg<T & D>, id_gen?: boolean): Promise<T>;
169
+ add(data: Arg<D>, id_gen?: boolean): Promise<D>;
169
170
  /**
170
171
  * Find data in a database.
171
172
  */
172
- find<T = Data>(search?: Search<T & D>, options?: DbFindOpts<T & D>, findOpts?: FindOpts<T & D>, context?: VContext): Promise<T[]>;
173
+ find(search?: Search<D>, options?: DbFindOpts<D>, findOpts?: FindOpts<D>, context?: VContext): Promise<D[]>;
173
174
  /**
174
175
  * Find one data entry in a database.
175
176
  */
176
- findOne<T = Data>(search?: Search<T & D>, findOpts?: FindOpts<T & D>, context?: VContext): Promise<T>;
177
+ findOne(search?: Search<D>, findOpts?: FindOpts<D>, context?: VContext): Promise<D>;
177
178
  /**
178
179
  * Update data in a database.
179
180
  */
180
- update<T = Data>(search: Search<T & D>, updater: Updater<T & D>, context?: VContext): Promise<boolean>;
181
+ update(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<boolean>;
181
182
  /**
182
183
  * Update one data entry in a database.
183
184
  */
184
- updateOne<T = Data>(search: Search<T & D>, updater: Updater<T & D>, context?: VContext): Promise<boolean>;
185
+ updateOne(search: Search<D>, updater: Updater<D>, context?: VContext): Promise<boolean>;
185
186
  /**
186
187
  * Remove data from a database.
187
188
  */
188
- remove<T = Data>(search: Search<T & D>, context?: VContext): Promise<boolean>;
189
+ remove(search: Search<D>, context?: VContext): Promise<boolean>;
189
190
  /**
190
191
  * Remove one data entry from a database.
191
192
  */
192
- removeOne<T = Data>(search: Search<T & D>, context?: VContext): Promise<boolean>;
193
+ removeOne(search: Search<D>, context?: VContext): Promise<boolean>;
193
194
  /**
194
195
  * Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
195
196
  */
196
- updateOneOrAdd<T = Data>(search: Search<T & D>, updater: Updater<T & D>, { add_arg, context, id_gen }: UpdateOneOrAdd<T & D>): Promise<boolean>;
197
+ updateOneOrAdd(search: Search<D>, updater: Updater<D>, { add_arg, context, id_gen }?: UpdateOneOrAdd<D>): Promise<boolean>;
197
198
  /**
198
199
  * Asynchronously removes one entry in a database or adds a new one if it doesn't exist. Usage e.g. for toggling a flag.
199
200
  */
200
- toggleOne<T = Data>(search: Search<T & D>, data?: Arg<T & D>, context?: VContext): Promise<boolean>;
201
+ toggleOne(search: Search<D>, data?: Arg<D>, context?: VContext): Promise<boolean>;
201
202
  }
202
203
  export interface ValtheraCompatible {
203
204
  c(collection: string): CollectionManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/vql",
3
- "version": "0.9.0",
3
+ "version": "0.10.2",
4
4
  "main": "dist/index.js",
5
5
  "author": "wxn0brP",
6
6
  "license": "MIT",
@@ -27,9 +27,9 @@
27
27
  "query-language"
28
28
  ],
29
29
  "peerDependencies": {
30
- "@wxn0brp/db-core": ">=0.3.0",
31
- "@wxn0brp/falcon-frame": ">=0.5.3",
32
- "@wxn0brp/gate-warden": ">=0.5.0"
30
+ "@wxn0brp/db-core": ">=0.4.0",
31
+ "@wxn0brp/falcon-frame": ">=0.5.9",
32
+ "@wxn0brp/gate-warden": ">=0.5.3"
33
33
  },
34
34
  "peerDependenciesMeta": {
35
35
  "@wxn0brp/falcon-frame": {
@@ -45,10 +45,10 @@
45
45
  "devDependencies": {
46
46
  "@types/bun": "*",
47
47
  "@types/node": "*",
48
- "@wxn0brp/db": "^0.41.0",
49
- "@wxn0brp/db-core": "^0.3.0",
50
- "@wxn0brp/falcon-frame": "^0.5.3",
51
- "@wxn0brp/gate-warden": "^0.5.0",
48
+ "@wxn0brp/db": "^0.41.1",
49
+ "@wxn0brp/db-core": "^0.4.0",
50
+ "@wxn0brp/falcon-frame": "^0.5.9",
51
+ "@wxn0brp/gate-warden": "^0.5.3",
52
52
  "esbuild": "*",
53
53
  "tsc-alias": "*",
54
54
  "typescript": "*"