@wxn0brp/vql 0.6.0-alpha.1 → 0.6.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.
@@ -1,3 +1,3 @@
1
1
  import { VQLProcessor } from "../processor.js";
2
- import { RelationQuery } from "../types/vql.js";
3
- export declare function executeRelation(cpu: VQLProcessor, query: RelationQuery, user: any): Promise<any>;
2
+ import { VQL_Query_Relation } from "../types/vql.js";
3
+ export declare function executeRelation(cpu: VQLProcessor, query: VQL_Query_Relation, user: any): Promise<any>;
@@ -21,7 +21,7 @@ export async function executeRelation(cpu, query, user) {
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.validFn, user, query)) {
24
+ if (!cpu.config.noCheckPermissions && !await checkRelationPermission(cpu.config, cpu.permValidFn, user, query)) {
25
25
  return { err: true, msg: "Permission denied", c: 403 };
26
26
  }
27
27
  const req = query.r;
@@ -1,3 +1,3 @@
1
1
  import { VQLProcessor } from "../processor.js";
2
- import { VQLRequest } from "../types/vql.js";
3
- export declare function executeQuery(cpu: VQLProcessor, query: VQLRequest, user: any): Promise<any>;
2
+ import { VQL_Query_CRUD } from "../types/vql.js";
3
+ export declare function executeQuery(cpu: VQLProcessor, query: VQL_Query_CRUD, user: any): Promise<any>;
@@ -5,7 +5,7 @@ export async function executeQuery(cpu, query, user) {
5
5
  return { err: true, msg: `Invalid query - db "${query.db || "undefined"}" not found`, c: 400 };
6
6
  const db = cpu.dbInstances[query.db];
7
7
  const operation = Object.keys(query.d)[0];
8
- if (!cpu.config.noCheckPermissions && !await checkRequestPermission(cpu.config, cpu.validFn, user, query)) {
8
+ if (!cpu.config.noCheckPermissions && !await checkRequestPermission(cpu.config, cpu.permValidFn, user, query)) {
9
9
  return { err: true, msg: "Permission denied", c: 403 };
10
10
  }
11
11
  if (operation === "find") {
@@ -1,2 +1,2 @@
1
- import { VQL } from "../../types/vql.js";
2
- export declare function parseVQLS(query: string): VQL;
1
+ import { VQL_Query } from "../../types/vql.js";
2
+ export declare function parseVQLS(query: string): VQL_Query;
package/dist/gw.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { GateWarden } from "@wxn0brp/gate-warden";
2
- import { ValidFn } from "./types/perm.js";
3
- export declare function createGwValidFn(gw: GateWarden): ValidFn;
2
+ import { PermValidFn } from "./types/perm.js";
3
+ export declare function createGwValidFn(gw: GateWarden): PermValidFn;
@@ -1,4 +1,4 @@
1
- import { ValidFn } from "../types/perm.js";
2
- import { RelationQuery } from "../types/vql.js";
1
+ import { PermValidFn } from "../types/perm.js";
2
+ import { VQL_Query_Relation } from "../types/vql.js";
3
3
  import { VQLConfig } from "../config.js";
4
- export declare function checkRelationPermission(config: VQLConfig, validFn: ValidFn, user: any, query: RelationQuery): Promise<boolean>;
4
+ export declare function checkRelationPermission(config: VQLConfig, permValidFn: PermValidFn, user: any, query: VQL_Query_Relation): Promise<boolean>;
@@ -1,12 +1,12 @@
1
1
  import { PermCRUD } from "../types/perm.js";
2
2
  import { extractPathsFromData, hashKey } from "./utils.js";
3
- export async function checkRelationPermission(config, validFn, user, query) {
3
+ export async function checkRelationPermission(config, permValidFn, user, query) {
4
4
  const { path, search, relations, select } = query.r;
5
5
  // Helper function to recursively check permissions with fallback mechanism
6
6
  const checkPermissionRecursively = async (entityId, fallbackLevels = []) => {
7
7
  // Check if the user has access to the current entity
8
8
  // const result = await gw.hasAccess(user.id, entityId, PermCRUD.READ);
9
- const result = await validFn(entityId, PermCRUD.READ, user);
9
+ const result = await permValidFn(entityId, PermCRUD.READ, user);
10
10
  if (result.granted) {
11
11
  return true;
12
12
  }
@@ -43,7 +43,7 @@ export async function checkRelationPermission(config, validFn, user, query) {
43
43
  if (relations) {
44
44
  for (const relationKey in relations) {
45
45
  const r = relations[relationKey];
46
- if (!await checkRelationPermission(config, validFn, user, { r })) {
46
+ if (!await checkRelationPermission(config, permValidFn, user, { r })) {
47
47
  return false;
48
48
  }
49
49
  }
@@ -1,7 +1,7 @@
1
- import { PermCRUD, ValidFn } from "../types/perm.js";
2
- import { VQLRequest } from "../types/vql.js";
3
1
  import { VQLConfig } from "../config.js";
4
- export declare function extractPaths(config: VQLConfig, query: VQLRequest): Promise<{
2
+ import { PermCRUD, PermValidFn } from "../types/perm.js";
3
+ import { VQL_Query_CRUD } from "../types/vql.js";
4
+ export declare function extractPaths(config: VQLConfig, query: VQL_Query_CRUD): Promise<{
5
5
  db: string;
6
6
  c: string;
7
7
  paths: {
@@ -15,4 +15,4 @@ export declare function processFieldPath(pathObj: {
15
15
  path: string[];
16
16
  key: string;
17
17
  }): string[];
18
- export declare function checkRequestPermission(config: VQLConfig, validFn: ValidFn, user: any, query: VQLRequest): Promise<boolean>;
18
+ export declare function checkRequestPermission(config: VQLConfig, permValidFn: PermValidFn, user: any, query: VQL_Query_CRUD): Promise<boolean>;
@@ -79,7 +79,7 @@ export function processFieldPath(pathObj) {
79
79
  }
80
80
  return processedPath;
81
81
  }
82
- export async function checkRequestPermission(config, validFn, user, query) {
82
+ export async function checkRequestPermission(config, permValidFn, user, query) {
83
83
  if (!query)
84
84
  return false;
85
85
  const permPaths = await extractPaths(config, query);
@@ -87,7 +87,7 @@ export async function checkRequestPermission(config, validFn, user, query) {
87
87
  const checkPermissionRecursively = async (entityId, requiredPerm, fallbackLevels = []) => {
88
88
  // Check if the user has access to the current entity
89
89
  // const result = await gw.hasAccess(user.id, entityId, requiredPerm);
90
- const result = await validFn(entityId, requiredPerm, user);
90
+ const result = await permValidFn(entityId, requiredPerm, user);
91
91
  if (result.granted) {
92
92
  return true;
93
93
  }
@@ -1,12 +1,12 @@
1
1
  import { Relation, ValtheraCompatible } from "@wxn0brp/db-core";
2
2
  import { VQLConfig, VQLConfigInterface } from "./config.js";
3
- import { VQLError, VqlQueryRaw } from "./types/vql.js";
4
- import { ValidFn } from "./types/perm.js";
3
+ import { VQLError, VQLUQ } from "./types/vql.js";
4
+ import { PermValidFn } from "./types/perm.js";
5
5
  export declare class VQLProcessor {
6
6
  dbInstances: Record<string, ValtheraCompatible>;
7
- validFn: ValidFn;
7
+ permValidFn: PermValidFn;
8
8
  relation: Relation;
9
9
  config: VQLConfig;
10
- constructor(dbInstances: Record<string, ValtheraCompatible>, config?: VQLConfig | Partial<VQLConfigInterface>, validFn?: ValidFn);
11
- execute<T = any>(queryRaw: VqlQueryRaw<T>, user?: any): Promise<T | VQLError>;
10
+ constructor(dbInstances: Record<string, ValtheraCompatible>, config?: VQLConfig | Partial<VQLConfigInterface>, permValidFn?: PermValidFn);
11
+ execute<T = any>(queryRaw: VQLUQ<T>, user?: any): Promise<T | VQLError>;
12
12
  }
package/dist/processor.js CHANGED
@@ -8,12 +8,12 @@ import { validateRaw, validateVql } from "./valid.js";
8
8
  import { parseVQLS } from "./cpu/string/index.js";
9
9
  export class VQLProcessor {
10
10
  dbInstances;
11
- validFn;
11
+ permValidFn;
12
12
  relation;
13
13
  config;
14
- constructor(dbInstances, config = new VQLConfig(), validFn = async () => ({ granted: true, via: "" })) {
14
+ constructor(dbInstances, config = new VQLConfig(), permValidFn = async () => ({ granted: true, via: "" })) {
15
15
  this.dbInstances = dbInstances;
16
- this.validFn = validFn;
16
+ this.permValidFn = permValidFn;
17
17
  this.relation = new Relation(dbInstances);
18
18
  this.config = config instanceof VQLConfig ? config : new VQLConfig(config);
19
19
  }
@@ -22,7 +22,6 @@ export class VQLProcessor {
22
22
  logger.info("Incoming string query");
23
23
  const q = typeof queryRaw === "string" ? queryRaw : queryRaw.query;
24
24
  const vars = typeof queryRaw === "string" ? null : queryRaw.var;
25
- const ref = typeof queryRaw === "string" ? null : queryRaw.ref;
26
25
  logger.debug(q);
27
26
  try {
28
27
  queryRaw = parseVQLS(q);
@@ -30,12 +29,10 @@ export class VQLProcessor {
30
29
  }
31
30
  catch (e) {
32
31
  logger.error("Error parsing string query: ", { error: e, msg: e.message });
33
- return { err: true, msg: "Invalid query", c: 400, why: `String query parsing error: ${e.message}` };
32
+ return { err: true, c: 400, msg: `String query parsing error: ${e.message}` };
34
33
  }
35
34
  if (vars)
36
35
  queryRaw = { ...queryRaw, var: vars };
37
- if (ref)
38
- queryRaw = { ...queryRaw, ref };
39
36
  logger.debug("Final string query: ", queryRaw);
40
37
  }
41
38
  else {
package/dist/sheet.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { VQL, VQLR } from "./types/vql.js";
2
- export declare function replaceVars(query: VQLR, user: any): VQL;
1
+ import { VQL_Query } from "./types/vql.js";
2
+ export declare function replaceVars(query: VQL_Query, user: any): VQL_Query;
@@ -9,4 +9,4 @@ export interface ValidFnResult {
9
9
  granted: boolean;
10
10
  via?: string;
11
11
  }
12
- export type ValidFn = (path: string, perm: number, user: any) => Promise<ValidFnResult>;
12
+ export type PermValidFn = (path: string, perm: number, user: any) => Promise<ValidFnResult>;
@@ -2,97 +2,79 @@ import { RelationTypes } from "@wxn0brp/db";
2
2
  import { Search, Arg } from "@wxn0brp/db-core/types/arg";
3
3
  import { DbFindOpts, FindOpts } from "@wxn0brp/db-core/types/options";
4
4
  import { UpdaterArg } from "@wxn0brp/db-core/types/updater";
5
- export interface VQLQuery<T = any> {
6
- find: VQLFind<T>;
7
- findOne: VQLFindOne<T>;
8
- f: VQLFindOne<T>;
9
- add: VQLAdd<T>;
10
- update: VQLUpdate<T>;
11
- updateOne: VQLUpdate<T>;
12
- remove: VQLRemove<T>;
13
- removeOne: VQLRemove<T>;
14
- updateOneOrAdd: VQLUpdateOneOrAdd<T>;
15
- removeCollection: VQLCollectionOperation;
16
- ensureCollection: VQLCollectionOperation;
17
- issetCollection: VQLCollectionOperation;
18
- getCollections: {};
19
- }
20
- export type VQLQueryData<T = any> = {
21
- find: VQLFind<T>;
22
- } | {
23
- findOne: VQLFindOne<T>;
24
- } | {
25
- f: VQLFindOne<T>;
26
- } | {
27
- add: VQLAdd<T>;
28
- } | {
29
- update: VQLUpdate<T>;
30
- } | {
31
- updateOne: VQLUpdate<T>;
32
- } | {
33
- remove: VQLRemove<T>;
34
- } | {
35
- removeOne: VQLRemove<T>;
36
- } | {
37
- updateOneOrAdd: VQLUpdateOneOrAdd<T>;
38
- } | {
39
- removeCollection: VQLCollectionOperation;
40
- } | {
41
- ensureCollection: VQLCollectionOperation;
42
- } | {
43
- issetCollection: VQLCollectionOperation;
44
- } | {
45
- getCollections: {};
46
- };
47
- export interface VQLRequest<T = any> {
48
- db: string;
49
- d: VQLQueryData<T>;
50
- }
51
- export interface VQLFind<T = any> {
5
+ export interface VQL_OP_Find<T = any> {
52
6
  collection: string;
53
7
  search?: Search<T>;
54
8
  limit?: number;
55
- fields?: VQLFields;
56
- select?: VQLFields;
57
- relations?: VQLRelations;
9
+ fields?: VQL_Fields;
10
+ select?: VQL_Fields;
58
11
  options?: DbFindOpts<T>;
59
12
  searchOpts?: FindOpts<T>;
60
13
  }
61
- export interface VQLFindOne<T = any> {
14
+ export interface VQL_OP_FindOne<T = any> {
62
15
  collection: string;
63
16
  search: Search<T>;
64
- fields?: VQLFields;
65
- select?: VQLFields;
66
- relations?: VQLRelations;
17
+ fields?: VQL_Fields;
18
+ select?: VQL_Fields;
67
19
  searchOpts?: FindOpts<T>;
68
20
  }
69
- export interface VQLAdd<T = any> {
21
+ export interface VQL_OP_Add<T = any> {
70
22
  collection: string;
71
23
  data: Arg<T>;
72
24
  id_gen?: boolean;
73
25
  }
74
- export interface VQLUpdate<T = any> {
26
+ export interface VQL_OP_Update<T = any> {
75
27
  collection: string;
76
28
  search: Search<T>;
77
29
  updater: UpdaterArg<T>;
78
30
  }
79
- export interface VQLRemove<T = any> {
31
+ export interface VQL_OP_Remove<T = any> {
80
32
  collection: string;
81
33
  search: Search<T>;
82
34
  }
83
- export interface VQLUpdateOneOrAdd<T = any> {
35
+ export interface VQL_OP_UpdateOneOrAdd<T = any> {
84
36
  collection: string;
85
37
  search: Search<T>;
86
38
  updater: UpdaterArg<T>;
87
39
  add_arg?: Arg<T>;
88
40
  id_gen?: boolean;
89
41
  }
90
- export interface VQLCollectionOperation {
42
+ export interface VQL_OP_CollectionOperation {
91
43
  collection: string;
92
44
  }
93
- export type VQLFields = Record<string, boolean | number> | string[];
94
- export type VQLRelations = Record<string, VQLFind | VQLFindOne>;
95
- export interface RelationQuery {
45
+ export type VQL_Fields = Record<string, boolean | number> | string[];
46
+ export type VQL_Query_CRUD_Data<T = any> = {
47
+ find: VQL_OP_Find<T>;
48
+ } | {
49
+ findOne: VQL_OP_FindOne<T>;
50
+ } | {
51
+ f: VQL_OP_FindOne<T>;
52
+ } | {
53
+ add: VQL_OP_Add<T>;
54
+ } | {
55
+ update: VQL_OP_Update<T>;
56
+ } | {
57
+ updateOne: VQL_OP_Update<T>;
58
+ } | {
59
+ remove: VQL_OP_Remove<T>;
60
+ } | {
61
+ removeOne: VQL_OP_Remove<T>;
62
+ } | {
63
+ updateOneOrAdd: VQL_OP_UpdateOneOrAdd<T>;
64
+ } | {
65
+ removeCollection: VQL_OP_CollectionOperation;
66
+ } | {
67
+ ensureCollection: VQL_OP_CollectionOperation;
68
+ } | {
69
+ issetCollection: VQL_OP_CollectionOperation;
70
+ } | {
71
+ getCollections: {};
72
+ };
73
+ export interface VQL_Query_CRUD<T = any> {
74
+ db: string;
75
+ d: VQL_Query_CRUD_Data<T>;
76
+ }
77
+ export interface VQL_Query_Relation {
96
78
  r: {
97
79
  path: RelationTypes.Path;
98
80
  search: Search;
@@ -102,25 +84,19 @@ export interface RelationQuery {
102
84
  select?: RelationTypes.FieldPath[];
103
85
  };
104
86
  }
105
- export interface VQLRef {
106
- ref?: string;
87
+ export interface VQL_Var {
107
88
  var?: {
108
89
  [k: string]: any;
109
90
  };
110
91
  }
111
- type VQLRefRequired = VQLRef & Required<Pick<VQLRef, "ref">>;
112
- type DeepPartial<T> = {
113
- [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
114
- };
115
- export type VQL<T = any> = (VQLRequest<T> | RelationQuery) & VQLRef;
116
- export type VQLR<T = any> = VQL<T> | (DeepPartial<VQL<T>> & VQLRefRequired) | VQLRefRequired;
92
+ /** VQL Query */
93
+ export type VQL_Query<T = any> = (VQL_Query_CRUD<T> | VQL_Query_Relation) & VQL_Var;
94
+ /** VQL Universal Query */
95
+ export type VQLUQ<T = any> = VQL_Query<T> | string | {
96
+ query: string;
97
+ } & VQL_Var;
117
98
  export interface VQLError {
118
99
  err: true;
119
100
  msg: string;
120
101
  c: number;
121
- why?: string;
122
102
  }
123
- export type VqlQueryRaw<T = any> = VQLR<T> | string | {
124
- query: string;
125
- } & VQLRef;
126
- export {};
package/dist/valid.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { VQL, VQLError, VQLR } from "./types/vql.js";
2
- export declare function validateRaw(query: VQLR): true | VQLError;
3
- export declare function validateVql(query: VQL): true | VQLError;
1
+ import { VQL_Query, VQLError } from "./types/vql.js";
2
+ export declare function validateRaw(query: VQL_Query): true | VQLError;
3
+ export declare function validateVql(query: VQL_Query): true | VQLError;
package/dist/valid.js CHANGED
@@ -1,7 +1,7 @@
1
- function emptyErr() {
1
+ function emptyErr(msg = "Bad query") {
2
2
  return {
3
3
  err: true,
4
- msg: "Bad query",
4
+ msg,
5
5
  c: 400
6
6
  };
7
7
  }
@@ -10,51 +10,133 @@ function isObj(obj, one = true) {
10
10
  }
11
11
  export function validateRaw(query) {
12
12
  if (("r" in query && isObj(query.r)) ||
13
- ("db" in query && typeof query.db === "string" && isObj(query.d)) ||
14
- ("ref" in query && isObj(query.ref)))
13
+ ("db" in query && typeof query.db === "string" && isObj(query.d)))
15
14
  return true;
16
- return emptyErr();
15
+ return emptyErr("Invalid VQL query structure. Must contain 'r' or 'db' and 'd'.");
16
+ }
17
+ function validateRelations(relations) {
18
+ if (!isObj(relations, false))
19
+ return emptyErr("The 'relations' property must be an object.");
20
+ for (const key in relations) {
21
+ const relation = relations[key];
22
+ if (!isObj(relation))
23
+ return emptyErr(`Relation '${key}' must be an object.`);
24
+ if (!("path" in relation) || !Array.isArray(relation.path) || relation.path.length !== 2)
25
+ return emptyErr(`Relation '${key}' must have a 'path' property with an array of two strings.`);
26
+ if ("search" in relation && !isObj(relation.search, false))
27
+ return emptyErr(`Relation '${key}' has an invalid 'search' property; it must be an object.`);
28
+ if ("many" in relation && typeof relation.many !== "boolean")
29
+ return emptyErr(`Relation '${key}' has an invalid 'many' property; it must be a boolean.`);
30
+ if ("options" in relation && !isObj(relation.options, false))
31
+ return emptyErr(`Relation '${key}' has an invalid 'options' property; it must be an object.`);
32
+ if ("select" in relation && !Array.isArray(relation.select))
33
+ return emptyErr(`Relation '${key}' has an invalid 'select' property; it must be an array.`);
34
+ if ("relations" in relation) {
35
+ const nestedResult = validateRelations(relation.relations);
36
+ if (nestedResult !== true)
37
+ return nestedResult;
38
+ }
39
+ }
40
+ return true;
17
41
  }
18
42
  function validR(query) {
19
43
  const { r } = query;
20
44
  if (!("path" in r) || !Array.isArray(r.path) || r.path.length !== 2)
21
- return emptyErr();
45
+ return emptyErr("Relation query 'r' must have a 'path' property with an array of two strings.");
22
46
  if (!isObj(r.search, false))
23
- return emptyErr();
47
+ return emptyErr("Relation query 'r.search' must be an object.");
48
+ if (!isObj(r.relations, false))
49
+ return emptyErr("Relation query 'r' must have a 'relations' object.");
50
+ const relationsValidation = validateRelations(r.relations);
51
+ if (relationsValidation !== true)
52
+ return relationsValidation;
53
+ if ("many" in r && typeof r.many !== "boolean")
54
+ return emptyErr("Relation query 'r.many' must be a boolean.");
55
+ if ("options" in r && !isObj(r.options, false))
56
+ return emptyErr("Relation query 'r.options' must be an object.");
57
+ if ("select" in r && !Array.isArray(r.select))
58
+ return emptyErr("Relation query 'r.select' must be an array.");
24
59
  return true;
25
60
  }
26
61
  function validD(query) {
27
62
  const { d } = query;
28
63
  const key = Object.keys(d)[0];
29
- if (key === "getCollection")
64
+ const value = d[key]; // Cast for common property
65
+ if (key === "getCollections")
30
66
  return true;
31
- const value = d[key];
32
67
  if (typeof value.collection !== "string" || value.collection.trim() === "")
33
- return emptyErr();
34
- if (key === "issetCollection" || key === "ensureCollection" || key === "removeCollection")
68
+ return emptyErr(`CRUD operation '${key}' must specify a non-empty 'collection' string.`);
69
+ if (key === "issetCollection" || key === "ensureCollection" || key === "removeCollection") {
35
70
  return true;
71
+ }
36
72
  if (key === "add") {
37
- if (!isObj(value.data))
38
- return emptyErr();
39
- else
40
- return true;
73
+ const op = d.add;
74
+ if (!isObj(op.data))
75
+ return emptyErr("'add' operation requires a 'data' object.");
76
+ if ("id_gen" in op && typeof op.id_gen !== "boolean")
77
+ return emptyErr("'add' operation 'id_gen' property must be a boolean.");
78
+ return true;
41
79
  }
42
- if ("search" in value && !isObj(value.search, false))
43
- return emptyErr();
44
- if (key === "find" || key === "findOne" || key === "f" || key === "remove" || key === "removeOne")
80
+ if (key === "find") {
81
+ const op = d.find;
82
+ if ("search" in op && !isObj(op.search, false))
83
+ return emptyErr("'find' operation 'search' property must be an object.");
84
+ if ("limit" in op && typeof op.limit !== "number")
85
+ return emptyErr("'find' operation 'limit' property must be a number.");
86
+ if ("fields" in op && !isObj(op.fields, false) && !Array.isArray(op.fields))
87
+ return emptyErr("'find' operation 'fields' property must be an object or an array.");
88
+ if ("select" in op && !isObj(op.select, false) && !Array.isArray(op.select))
89
+ return emptyErr("'find' operation 'select' property must be an object or an array.");
90
+ if ("options" in op && !isObj(op.options, false))
91
+ return emptyErr("'find' operation 'options' property must be an object.");
92
+ if ("searchOpts" in op && !isObj(op.searchOpts, false))
93
+ return emptyErr("'find' operation 'searchOpts' property must be an object.");
45
94
  return true;
46
- if (key === "update" || key === "updateOne" || key === "updateOneOrAdd") {
47
- if (!isObj(value.updater, false))
48
- return emptyErr();
49
- else
50
- return true;
51
95
  }
52
- return true;
96
+ if (key === "findOne" || key === "f") {
97
+ const op = d.findOne || d.f;
98
+ if (!isObj(op.search, false))
99
+ return emptyErr(`'${key}' operation requires a 'search' object.`);
100
+ if ("fields" in op && !isObj(op.fields, false) && !Array.isArray(op.fields))
101
+ return emptyErr(`'${key}' operation 'fields' property must be an object or an array.`);
102
+ if ("select" in op && !isObj(op.select, false) && !Array.isArray(op.select))
103
+ return emptyErr(`'${key}' operation 'select' property must be an object or an array.`);
104
+ if ("searchOpts" in op && !isObj(op.searchOpts, false))
105
+ return emptyErr(`'${key}' operation 'searchOpts' property must be an object.`);
106
+ return true;
107
+ }
108
+ if (key === "remove" || key === "removeOne") {
109
+ const op = d.remove || d.removeOne;
110
+ if (!isObj(op.search, false))
111
+ return emptyErr(`'${key}' operation requires a 'search' object.`);
112
+ return true;
113
+ }
114
+ if (key === "update" || key === "updateOne") {
115
+ const op = d.update || d.updateOne;
116
+ if (!isObj(op.search, false))
117
+ return emptyErr(`'${key}' operation requires a 'search' object.`);
118
+ if (!isObj(op.updater, false))
119
+ return emptyErr(`'${key}' operation requires an 'updater' object.`);
120
+ return true;
121
+ }
122
+ if (key === "updateOneOrAdd") {
123
+ const op = d.updateOneOrAdd;
124
+ if (!isObj(op.search, false))
125
+ return emptyErr("'updateOneOrAdd' operation requires a 'search' object.");
126
+ if (!isObj(op.updater, false))
127
+ return emptyErr("'updateOneOrAdd' operation requires an 'updater' object.");
128
+ if ("add_arg" in op && !isObj(op.add_arg, false))
129
+ return emptyErr("'updateOneOrAdd' operation 'add_arg' property must be an object.");
130
+ if ("id_gen" in op && typeof op.id_gen !== "boolean")
131
+ return emptyErr("'updateOneOrAdd' operation 'id_gen' property must be a boolean.");
132
+ return true;
133
+ }
134
+ return emptyErr(`Unknown or invalid CRUD operation: '${key}'`);
53
135
  }
54
136
  export function validateVql(query) {
55
137
  if ("r" in query && isObj(query.r))
56
138
  return validR(query);
57
139
  if ("d" in query && isObj(query.d))
58
140
  return validD(query);
59
- return emptyErr();
141
+ return emptyErr("Query must contain a valid 'r' (relation) or 'd' (database) property.");
60
142
  }
package/dist/vql.d.ts CHANGED
@@ -189,97 +189,79 @@ declare namespace RelationTypes {
189
189
  };
190
190
  }
191
191
  }
192
- export interface VQLQuery<T = any> {
193
- find: VQLFind<T>;
194
- findOne: VQLFindOne<T>;
195
- f: VQLFindOne<T>;
196
- add: VQLAdd<T>;
197
- update: VQLUpdate<T>;
198
- updateOne: VQLUpdate<T>;
199
- remove: VQLRemove<T>;
200
- removeOne: VQLRemove<T>;
201
- updateOneOrAdd: VQLUpdateOneOrAdd<T>;
202
- removeCollection: VQLCollectionOperation;
203
- ensureCollection: VQLCollectionOperation;
204
- issetCollection: VQLCollectionOperation;
205
- getCollections: {};
206
- }
207
- export type VQLQueryData<T = any> = {
208
- find: VQLFind<T>;
209
- } | {
210
- findOne: VQLFindOne<T>;
211
- } | {
212
- f: VQLFindOne<T>;
213
- } | {
214
- add: VQLAdd<T>;
215
- } | {
216
- update: VQLUpdate<T>;
217
- } | {
218
- updateOne: VQLUpdate<T>;
219
- } | {
220
- remove: VQLRemove<T>;
221
- } | {
222
- removeOne: VQLRemove<T>;
223
- } | {
224
- updateOneOrAdd: VQLUpdateOneOrAdd<T>;
225
- } | {
226
- removeCollection: VQLCollectionOperation;
227
- } | {
228
- ensureCollection: VQLCollectionOperation;
229
- } | {
230
- issetCollection: VQLCollectionOperation;
231
- } | {
232
- getCollections: {};
233
- };
234
- export interface VQLRequest<T = any> {
235
- db: string;
236
- d: VQLQueryData<T>;
237
- }
238
- export interface VQLFind<T = any> {
192
+ export interface VQL_OP_Find<T = any> {
239
193
  collection: string;
240
194
  search?: Search<T>;
241
195
  limit?: number;
242
- fields?: VQLFields;
243
- select?: VQLFields;
244
- relations?: VQLRelations;
196
+ fields?: VQL_Fields;
197
+ select?: VQL_Fields;
245
198
  options?: DbFindOpts<T>;
246
199
  searchOpts?: FindOpts<T>;
247
200
  }
248
- export interface VQLFindOne<T = any> {
201
+ export interface VQL_OP_FindOne<T = any> {
249
202
  collection: string;
250
203
  search: Search<T>;
251
- fields?: VQLFields;
252
- select?: VQLFields;
253
- relations?: VQLRelations;
204
+ fields?: VQL_Fields;
205
+ select?: VQL_Fields;
254
206
  searchOpts?: FindOpts<T>;
255
207
  }
256
- export interface VQLAdd<T = any> {
208
+ export interface VQL_OP_Add<T = any> {
257
209
  collection: string;
258
210
  data: Arg<T>;
259
211
  id_gen?: boolean;
260
212
  }
261
- export interface VQLUpdate<T = any> {
213
+ export interface VQL_OP_Update<T = any> {
262
214
  collection: string;
263
215
  search: Search<T>;
264
216
  updater: UpdaterArg<T>;
265
217
  }
266
- export interface VQLRemove<T = any> {
218
+ export interface VQL_OP_Remove<T = any> {
267
219
  collection: string;
268
220
  search: Search<T>;
269
221
  }
270
- export interface VQLUpdateOneOrAdd<T = any> {
222
+ export interface VQL_OP_UpdateOneOrAdd<T = any> {
271
223
  collection: string;
272
224
  search: Search<T>;
273
225
  updater: UpdaterArg<T>;
274
226
  add_arg?: Arg<T>;
275
227
  id_gen?: boolean;
276
228
  }
277
- export interface VQLCollectionOperation {
229
+ export interface VQL_OP_CollectionOperation {
278
230
  collection: string;
279
231
  }
280
- export type VQLFields = Record<string, boolean | number> | string[];
281
- export type VQLRelations = Record<string, VQLFind | VQLFindOne>;
282
- export interface RelationQuery {
232
+ export type VQL_Fields = Record<string, boolean | number> | string[];
233
+ export type VQL_Query_CRUD_Data<T = any> = {
234
+ find: VQL_OP_Find<T>;
235
+ } | {
236
+ findOne: VQL_OP_FindOne<T>;
237
+ } | {
238
+ f: VQL_OP_FindOne<T>;
239
+ } | {
240
+ add: VQL_OP_Add<T>;
241
+ } | {
242
+ update: VQL_OP_Update<T>;
243
+ } | {
244
+ updateOne: VQL_OP_Update<T>;
245
+ } | {
246
+ remove: VQL_OP_Remove<T>;
247
+ } | {
248
+ removeOne: VQL_OP_Remove<T>;
249
+ } | {
250
+ updateOneOrAdd: VQL_OP_UpdateOneOrAdd<T>;
251
+ } | {
252
+ removeCollection: VQL_OP_CollectionOperation;
253
+ } | {
254
+ ensureCollection: VQL_OP_CollectionOperation;
255
+ } | {
256
+ issetCollection: VQL_OP_CollectionOperation;
257
+ } | {
258
+ getCollections: {};
259
+ };
260
+ export interface VQL_Query_CRUD<T = any> {
261
+ db: string;
262
+ d: VQL_Query_CRUD_Data<T>;
263
+ }
264
+ export interface VQL_Query_Relation {
283
265
  r: {
284
266
  path: RelationTypes.Path;
285
267
  search: Search;
@@ -289,26 +271,21 @@ export interface RelationQuery {
289
271
  select?: RelationTypes.FieldPath[];
290
272
  };
291
273
  }
292
- export interface VQLRef {
293
- ref?: string;
274
+ export interface VQL_Var {
294
275
  var?: {
295
276
  [k: string]: any;
296
277
  };
297
278
  }
298
- export type VQLRefRequired = VQLRef & Required<Pick<VQLRef, "ref">>;
299
- export type DeepPartial<T> = {
300
- [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
301
- };
302
- export type VQL<T = any> = (VQLRequest<T> | RelationQuery) & VQLRef;
303
- export type VQLR<T = any> = VQL<T> | (DeepPartial<VQL<T>> & VQLRefRequired) | VQLRefRequired;
279
+ /** VQL Query */
280
+ export type VQL_Query<T = any> = (VQL_Query_CRUD<T> | VQL_Query_Relation) & VQL_Var;
281
+ /** VQL Universal Query */
282
+ export type VQLUQ<T = any> = VQL_Query<T> | string | {
283
+ query: string;
284
+ } & VQL_Var;
304
285
  export interface VQLError {
305
286
  err: true;
306
287
  msg: string;
307
288
  c: number;
308
- why?: string;
309
289
  }
310
- export type VqlQueryRaw<T = any> = VQLR<T> | string | {
311
- query: string;
312
- } & VQLRef;
313
290
 
314
291
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/vql",
3
- "version": "0.6.0-alpha.1",
3
+ "version": "0.6.0",
4
4
  "main": "dist/index.js",
5
5
  "author": "wxn0brP",
6
6
  "license": "MIT",
@@ -35,7 +35,6 @@
35
35
  "@wxn0brp/db": "^0.30.0",
36
36
  "@wxn0brp/falcon-frame": "0.0.20",
37
37
  "@wxn0brp/gate-warden": "^0.4.0",
38
- "dotenv": "^17.2.0",
39
38
  "esbuild": "^0.25.8",
40
39
  "tsc-alias": "^1.8.10",
41
40
  "typescript": "^5.7.3"