@wxn0brp/vql 0.8.4 → 0.10.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/cpu/relation.d.ts +2 -1
- package/dist/cpu/relation.js +3 -3
- package/dist/cpu/request.d.ts +2 -1
- package/dist/cpu/request.js +7 -4
- package/dist/helpers/apiAbstract.d.ts +31 -24
- package/dist/helpers/apiAbstract.js +8 -5
- package/dist/helpers/gw.js +2 -1
- package/dist/helpers/lowAdapter.d.ts +6 -0
- package/dist/helpers/lowAdapter.js +6 -0
- package/dist/helpers/sheet.js +1 -0
- package/dist/permissions/relation.js +1 -1
- package/dist/permissions/request.js +1 -1
- package/dist/permissions/resolver.d.ts +2 -2
- package/dist/permissions/resolver.js +26 -16
- package/dist/processor.d.ts +2 -2
- package/dist/processor.js +6 -6
- package/dist/types/perm.d.ts +3 -1
- package/dist/types/resolver.d.ts +4 -0
- package/dist/vql.d.ts +97 -50
- package/package.json +4 -4
package/dist/cpu/relation.d.ts
CHANGED
|
@@ -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>;
|
package/dist/cpu/relation.js
CHANGED
|
@@ -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 (!
|
|
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(
|
|
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);
|
package/dist/cpu/request.d.ts
CHANGED
|
@@ -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>;
|
package/dist/cpu/request.js
CHANGED
|
@@ -1,23 +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
|
-
export async function executeQuery(cpu, query, user) {
|
|
4
|
+
export async function executeQuery(cpu, query, user, cfg) {
|
|
4
5
|
if (!query.db || !cpu.dbInstances[query.db])
|
|
5
6
|
return { err: true, msg: `Invalid query - db "${query.db || "undefined"}" not found`, c: 400 };
|
|
6
7
|
const db = cpu.dbInstances[query.db];
|
|
8
|
+
if (db instanceof LowAdapter)
|
|
9
|
+
return await db.resolver(query, user);
|
|
7
10
|
const operation = Object.keys(query.d)[0];
|
|
8
|
-
if (!
|
|
11
|
+
if (!cfg.noCheckPermissions && !await checkRequestPermission(cfg, cpu.permValidFn, user, query)) {
|
|
9
12
|
return { err: true, msg: "Permission denied", c: 403 };
|
|
10
13
|
}
|
|
11
14
|
if (operation === "find") {
|
|
12
15
|
const params = query.d[operation];
|
|
13
|
-
const select = parseSelect(
|
|
16
|
+
const select = parseSelect(cfg, params.fields || params.select || {});
|
|
14
17
|
if (select && typeof select === "object" && Object.keys(select).length !== 0)
|
|
15
18
|
params.searchOpts = { ...params.searchOpts, select };
|
|
16
19
|
return db.find(params.collection, params.search, params.options || {}, params.searchOpts);
|
|
17
20
|
}
|
|
18
21
|
else if (operation === "findOne" || operation === "f") {
|
|
19
22
|
const params = query.d[operation];
|
|
20
|
-
const select = parseSelect(
|
|
23
|
+
const select = parseSelect(cfg, params.fields || params.select || {});
|
|
21
24
|
if (select && typeof select === "object" && Object.keys(select).length !== 0)
|
|
22
25
|
params.searchOpts = { ...params.searchOpts, select };
|
|
23
26
|
return db.findOne(params.collection, params.search, params.searchOpts);
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { VQL_Query_CRUD_Keys } from "../types/vql.js";
|
|
1
2
|
import { ValtheraCompatible } from "@wxn0brp/db-core";
|
|
2
|
-
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;
|
|
3
6
|
export interface ValtheraResolverMeta {
|
|
4
7
|
type: "valthera" | "api" | "wrapper" | (string & {});
|
|
5
8
|
version: string;
|
|
@@ -18,47 +21,51 @@ export interface ValtheraResolver {
|
|
|
18
21
|
find?: ResolverFn<[
|
|
19
22
|
collection: string,
|
|
20
23
|
search: any,
|
|
21
|
-
context?: any,
|
|
22
24
|
options?: any,
|
|
23
|
-
findOpts?: any
|
|
25
|
+
findOpts?: any,
|
|
26
|
+
context?: any
|
|
24
27
|
], any[]>;
|
|
25
28
|
findOne?: ResolverFn<[
|
|
26
29
|
collection: string,
|
|
27
30
|
search: any,
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
findOpts?: any,
|
|
32
|
+
context?: any
|
|
30
33
|
], any | null>;
|
|
31
34
|
update?: ResolverFn<[collection: string, search: any, updater: any, context?: any], boolean>;
|
|
32
35
|
updateOne?: ResolverFn<[collection: string, search: any, updater: any, context?: any], boolean>;
|
|
33
|
-
updateOneOrAdd?: ResolverFn<[
|
|
34
|
-
|
|
35
|
-
search: any,
|
|
36
|
-
updater: any,
|
|
37
|
-
add_arg?: any,
|
|
38
|
-
context?: any,
|
|
39
|
-
id_gen?: boolean
|
|
40
|
-
], boolean>;
|
|
36
|
+
updateOneOrAdd?: ResolverFn<[collection: string, search: any, updater: any, opts?: any], boolean>;
|
|
37
|
+
toggleOne?: ResolverFn<[collection: string, search: any, data?: any, context?: any], boolean>;
|
|
41
38
|
remove?: ResolverFn<[collection: string, search: any, context?: any], boolean>;
|
|
42
39
|
removeOne?: ResolverFn<[collection: string, search: any, context?: any], boolean>;
|
|
43
40
|
removeCollection?: ResolverFn<[collection: string], boolean>;
|
|
44
41
|
}
|
|
42
|
+
export type Operation = Exclude<VQL_Query_CRUD_Keys, "f">;
|
|
45
43
|
export declare function createValtheraAdapter(resolver: ValtheraResolver, extendedFind?: boolean): ValtheraCompatible;
|
|
46
|
-
export type Operation = "add" | "find" | "findOne" | "update" | "updateOne" | "updateOneOrAdd" | "remove" | "removeOne" | "removeCollection";
|
|
47
44
|
export declare class AdapterBuilder {
|
|
48
45
|
private catchCb;
|
|
49
46
|
private handlers;
|
|
50
47
|
private collections;
|
|
51
48
|
constructor(catchCb?: (e: any, op: string, args: any[]) => void);
|
|
52
49
|
register(op: Operation, collection: string, fn: Function): this;
|
|
53
|
-
add(collection: string, fn:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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;
|
|
62
70
|
getAdapter(extendedFind?: boolean): ValtheraCompatible;
|
|
63
71
|
}
|
|
64
|
-
export {};
|
|
@@ -4,7 +4,8 @@ const list = [
|
|
|
4
4
|
"ensureCollection", "issetCollection", "getCollections", "removeCollection",
|
|
5
5
|
"add",
|
|
6
6
|
"find", "findOne",
|
|
7
|
-
"update", "updateOne",
|
|
7
|
+
"update", "updateOne",
|
|
8
|
+
"updateOneOrAdd", "toggleOne",
|
|
8
9
|
"remove", "removeOne"
|
|
9
10
|
];
|
|
10
11
|
export function createValtheraAdapter(resolver, extendedFind = false) {
|
|
@@ -26,8 +27,8 @@ export function createValtheraAdapter(resolver, extendedFind = false) {
|
|
|
26
27
|
let data = await safe(resolver.find)(col, search, options, findOpts, context);
|
|
27
28
|
if (options?.reverse)
|
|
28
29
|
data.reverse();
|
|
29
|
-
if (options?.
|
|
30
|
-
data = data.slice(0, options?.
|
|
30
|
+
if (options?.limit !== -1 && data.length > options?.limit)
|
|
31
|
+
data = data.slice(0, options?.limit);
|
|
31
32
|
data = data.map(d => updateFindObject(d, findOpts || {}));
|
|
32
33
|
return data;
|
|
33
34
|
};
|
|
@@ -70,6 +71,9 @@ export class AdapterBuilder {
|
|
|
70
71
|
updateOneOrAdd(collection, fn) {
|
|
71
72
|
return this.register("updateOneOrAdd", collection, fn);
|
|
72
73
|
}
|
|
74
|
+
toggleOne(collection, fn) {
|
|
75
|
+
return this.register("toggleOne", collection, fn);
|
|
76
|
+
}
|
|
73
77
|
remove(collection, fn) {
|
|
74
78
|
return this.register("remove", collection, fn);
|
|
75
79
|
}
|
|
@@ -103,9 +107,8 @@ export class AdapterBuilder {
|
|
|
103
107
|
return true;
|
|
104
108
|
},
|
|
105
109
|
}, extendedFind);
|
|
106
|
-
for (const name of
|
|
110
|
+
for (const name of list.slice(4))
|
|
107
111
|
adapter[name] = (...args) => resolve(name, ...args);
|
|
108
|
-
}
|
|
109
112
|
return adapter;
|
|
110
113
|
}
|
|
111
114
|
}
|
package/dist/helpers/gw.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export function createGwValidFn(gw) {
|
|
2
2
|
return async (args) => {
|
|
3
|
-
|
|
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
|
}
|
package/dist/helpers/sheet.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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 (
|
|
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
|
}
|
package/dist/processor.d.ts
CHANGED
|
@@ -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 };
|
package/dist/types/perm.d.ts
CHANGED
|
@@ -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?:
|
|
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 */
|
package/dist/types/resolver.d.ts
CHANGED
|
@@ -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
|
@@ -9,8 +9,14 @@ export interface VContext {
|
|
|
9
9
|
export type KeysMatching<T, V, C = V> = {
|
|
10
10
|
[K in keyof T]-?: T[K] extends C ? K : never;
|
|
11
11
|
}[keyof T];
|
|
12
|
-
|
|
13
|
-
export type
|
|
12
|
+
/** Helper type for nested path values with type filtering */
|
|
13
|
+
export type NestedValue<T, V, C = V> = {
|
|
14
|
+
[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;
|
|
15
|
+
};
|
|
16
|
+
/** Helper type for nested path structure */
|
|
17
|
+
export type DeepPartial<T> = {
|
|
18
|
+
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
19
|
+
};
|
|
14
20
|
/** Logical Operators */
|
|
15
21
|
export type LogicalOperators<T = any> = {
|
|
16
22
|
/**
|
|
@@ -29,73 +35,110 @@ export type LogicalOperators<T = any> = {
|
|
|
29
35
|
*/
|
|
30
36
|
$not?: SearchOptions<T>;
|
|
31
37
|
};
|
|
32
|
-
/** Comparison Operators */
|
|
38
|
+
/** Comparison Operators with nested support */
|
|
33
39
|
export type ComparisonOperators<T = any> = {
|
|
34
|
-
|
|
35
|
-
$
|
|
36
|
-
|
|
37
|
-
$
|
|
38
|
-
|
|
40
|
+
/** 5 > 4 */
|
|
41
|
+
$gt?: NestedValue<T, number, number>;
|
|
42
|
+
/** 5 < 4 */
|
|
43
|
+
$lt?: NestedValue<T, number, number>;
|
|
44
|
+
/** 5 >= 4 */
|
|
45
|
+
$gte?: NestedValue<T, number, number>;
|
|
46
|
+
/** 5 <= 4 */
|
|
47
|
+
$lte?: NestedValue<T, number, number>;
|
|
48
|
+
/** 5 between [min, max] */
|
|
49
|
+
$between?: NestedValue<T, [
|
|
39
50
|
number,
|
|
40
51
|
number
|
|
41
52
|
], number>;
|
|
42
|
-
|
|
43
|
-
$
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
$
|
|
53
|
+
/** 2 in [1, 2, 3] */
|
|
54
|
+
$in?: DeepPartial<T> & {
|
|
55
|
+
[K in keyof T]?: T[K] extends any[] ? T[K] : T[K][];
|
|
56
|
+
};
|
|
57
|
+
/** 5 not in [1, 2, 3] */
|
|
58
|
+
$nin?: DeepPartial<T> & {
|
|
59
|
+
[K in keyof T]?: T[K] extends any[] ? T[K] : T[K][];
|
|
60
|
+
};
|
|
61
|
+
/** id > 4 */
|
|
62
|
+
$idGt?: NestedValue<T, string | number, string | number>;
|
|
63
|
+
/** id < 4 */
|
|
64
|
+
$idLt?: NestedValue<T, string | number, string | number>;
|
|
65
|
+
/** id >= 4 */
|
|
66
|
+
$idGte?: NestedValue<T, string | number, string | number>;
|
|
67
|
+
/** id <= 4 */
|
|
68
|
+
$idLte?: NestedValue<T, string | number, string | number>;
|
|
48
69
|
};
|
|
49
|
-
/** Type and Existence Operators */
|
|
70
|
+
/** Type and Existence Operators with nested support */
|
|
50
71
|
export type TypeAndExistenceOperators<T = any> = {
|
|
51
|
-
|
|
52
|
-
$
|
|
72
|
+
/** "name" in { name: "John" } */
|
|
73
|
+
$exists?: NestedValue<T, boolean>;
|
|
74
|
+
/** "name" == "string" in { name: "John" } */
|
|
75
|
+
$type?: NestedValue<T, string>;
|
|
53
76
|
};
|
|
54
|
-
/** Array Operators */
|
|
77
|
+
/** Array Operators with nested support */
|
|
55
78
|
export type ArrayOperators<T = any> = {
|
|
56
|
-
|
|
57
|
-
$
|
|
58
|
-
|
|
79
|
+
/** [1, 2, 3] includes 2 */
|
|
80
|
+
$arrinc?: DeepPartial<T>;
|
|
81
|
+
/** [1, 2, 3] array includes all elements e.g. [1, 2] */
|
|
82
|
+
$arrincall?: DeepPartial<T>;
|
|
83
|
+
/** [1, 2, 3] has size 3 */
|
|
84
|
+
$size?: NestedValue<T, number>;
|
|
59
85
|
};
|
|
60
|
-
/** String Operators */
|
|
86
|
+
/** String Operators with nested support */
|
|
61
87
|
export type StringOperators<T = any> = {
|
|
62
|
-
|
|
63
|
-
$
|
|
64
|
-
|
|
88
|
+
/** "John" matches /oh/ */
|
|
89
|
+
$regex?: NestedValue<T, RegExp | string, string>;
|
|
90
|
+
/** "John" starts with "Jo" */
|
|
91
|
+
$startsWith?: NestedValue<T, string, string>;
|
|
92
|
+
/** "John" ends with "hn" */
|
|
93
|
+
$endsWith?: NestedValue<T, string, string>;
|
|
65
94
|
};
|
|
66
|
-
/** Other Operators */
|
|
95
|
+
/** Other Operators with nested support */
|
|
67
96
|
export type OtherOperators<T = any> = {
|
|
68
|
-
$
|
|
97
|
+
/** { $type: "name" } matches { $type: "name" } literally - Ignore $ operators */
|
|
98
|
+
$subset?: DeepPartial<T>;
|
|
69
99
|
};
|
|
70
100
|
/** Predefined Search Operators */
|
|
71
101
|
export type PredefinedSearchOperators<T = any> = LogicalOperators<T> & ComparisonOperators<T> & TypeAndExistenceOperators<T> & ArrayOperators<T> & StringOperators<T> & OtherOperators<T>;
|
|
72
102
|
/**
|
|
73
103
|
* SearchOptions can be either a function or an object with predefined operators.
|
|
74
104
|
*/
|
|
75
|
-
export type SearchOptions<T = any> = PredefinedSearchOperators<T> &
|
|
105
|
+
export type SearchOptions<T = any> = PredefinedSearchOperators<T> & DeepPartial<T> & Record<string, any>;
|
|
76
106
|
/** Arrays */
|
|
77
107
|
export type ArrayUpdater<T = any> = {
|
|
78
|
-
$push
|
|
79
|
-
|
|
80
|
-
$pushset
|
|
81
|
-
$
|
|
82
|
-
$
|
|
108
|
+
/** [1,2] -> $push 3 -> [1,2,3] */
|
|
109
|
+
$push?: NestedValue<T, any>;
|
|
110
|
+
/** [1,2] -> $pushset 2,3 -> [1,2,3] */
|
|
111
|
+
$pushset?: NestedValue<T, any>;
|
|
112
|
+
/** [1,2,3] -> $pull 2 -> [1,3] */
|
|
113
|
+
$pull?: NestedValue<T, any>;
|
|
114
|
+
/** [1,2,2,3] -> $pullall [2] -> [1,3] */
|
|
115
|
+
$pullall?: NestedValue<T, any>;
|
|
83
116
|
};
|
|
84
117
|
/** Objects */
|
|
85
118
|
export type ObjectUpdater<T = any> = {
|
|
86
|
-
$merge
|
|
87
|
-
$
|
|
119
|
+
/** { a: 1 } -> $merge { b: 2 } -> { a: 1, b: 2 } */
|
|
120
|
+
$merge?: NestedValue<T, any>;
|
|
121
|
+
/** { a: { x: 1 } } -> $deepMerge { a: { y: 2 } } -> { a: { x: 1, y: 2 } } */
|
|
122
|
+
$deepMerge?: NestedValue<T, any>;
|
|
88
123
|
};
|
|
89
124
|
/** Values */
|
|
90
125
|
export type ValueUpdater<T = any> = {
|
|
91
|
-
$inc
|
|
92
|
-
$
|
|
93
|
-
$
|
|
94
|
-
$
|
|
95
|
-
/**
|
|
96
|
-
$
|
|
126
|
+
/** { count: 1 } -> $inc 2 -> { count: 3 } */
|
|
127
|
+
$inc?: NestedValue<T, number>;
|
|
128
|
+
/** { count: 5 } -> $dec 2 -> { count: 3 } */
|
|
129
|
+
$dec?: NestedValue<T, number>;
|
|
130
|
+
/** { name: "John" } -> $unset "name" -> {} */
|
|
131
|
+
$unset?: NestedValue<T, any>;
|
|
132
|
+
/** { oldName: "value" } -> $rename "oldName" to "newName" -> { newName: "value" } */
|
|
133
|
+
$rename?: NestedValue<T, any>;
|
|
134
|
+
/**
|
|
135
|
+
* {} -> $set { name: "John" } -> { name: "John" }
|
|
136
|
+
*
|
|
137
|
+
* Note: same as { name: value }
|
|
138
|
+
*/
|
|
139
|
+
$set?: NestedValue<T, any>;
|
|
97
140
|
};
|
|
98
|
-
export type UpdaterArg<T = any> = ArrayUpdater<T> & ObjectUpdater<T> & ValueUpdater<T> &
|
|
141
|
+
export type UpdaterArg<T = any> = ArrayUpdater<T> & ObjectUpdater<T> & ValueUpdater<T> & DeepPartial<T> & Record<string, any>;
|
|
99
142
|
export type Arg<T = any> = {
|
|
100
143
|
[K in keyof T]?: any;
|
|
101
144
|
} & Record<string, any>;
|
|
@@ -105,7 +148,7 @@ export type Search<T = any> = SearchOptions<T> | SearchFunc<T>;
|
|
|
105
148
|
export type Updater<T = any> = UpdaterArg<T> | UpdaterArg<T>[] | UpdaterFunc<T>;
|
|
106
149
|
export interface DbFindOpts<T = any> {
|
|
107
150
|
reverse?: boolean;
|
|
108
|
-
|
|
151
|
+
limit?: number;
|
|
109
152
|
offset?: number;
|
|
110
153
|
sortBy?: KeysMatching<T, any>;
|
|
111
154
|
sortAsc?: boolean;
|
|
@@ -126,31 +169,35 @@ declare class CollectionManager<D = Data> {
|
|
|
126
169
|
/**
|
|
127
170
|
* Find data in a database.
|
|
128
171
|
*/
|
|
129
|
-
find<T = Data>(search?: Search<T & D>, options?: DbFindOpts<T &
|
|
172
|
+
find<T = Data>(search?: Search<T & D>, options?: DbFindOpts<T & D>, findOpts?: FindOpts<T & D>, context?: VContext): Promise<T[]>;
|
|
130
173
|
/**
|
|
131
174
|
* Find one data entry in a database.
|
|
132
175
|
*/
|
|
133
|
-
findOne<T = Data>(search?: Search<T &
|
|
176
|
+
findOne<T = Data>(search?: Search<T & D>, findOpts?: FindOpts<T & D>, context?: VContext): Promise<T>;
|
|
134
177
|
/**
|
|
135
178
|
* Update data in a database.
|
|
136
179
|
*/
|
|
137
|
-
update<T = Data>(search: Search<T &
|
|
180
|
+
update<T = Data>(search: Search<T & D>, updater: Updater<T & D>, context?: VContext): Promise<boolean>;
|
|
138
181
|
/**
|
|
139
182
|
* Update one data entry in a database.
|
|
140
183
|
*/
|
|
141
|
-
updateOne<T = Data>(search: Search<T &
|
|
184
|
+
updateOne<T = Data>(search: Search<T & D>, updater: Updater<T & D>, context?: VContext): Promise<boolean>;
|
|
142
185
|
/**
|
|
143
186
|
* Remove data from a database.
|
|
144
187
|
*/
|
|
145
|
-
remove<T = Data>(search: Search<T &
|
|
188
|
+
remove<T = Data>(search: Search<T & D>, context?: VContext): Promise<boolean>;
|
|
146
189
|
/**
|
|
147
190
|
* Remove one data entry from a database.
|
|
148
191
|
*/
|
|
149
|
-
removeOne<T = Data>(search: Search<T &
|
|
192
|
+
removeOne<T = Data>(search: Search<T & D>, context?: VContext): Promise<boolean>;
|
|
150
193
|
/**
|
|
151
194
|
* Asynchronously updates one entry in a database or adds a new one if it doesn't exist.
|
|
152
195
|
*/
|
|
153
|
-
updateOneOrAdd<T = Data>(search: Search<T &
|
|
196
|
+
updateOneOrAdd<T = Data>(search: Search<T & D>, updater: Updater<T & D>, { add_arg, context, id_gen }: UpdateOneOrAdd<T & D>): Promise<boolean>;
|
|
197
|
+
/**
|
|
198
|
+
* 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
|
+
toggleOne<T = Data>(search: Search<T & D>, data?: Arg<T & D>, context?: VContext): Promise<boolean>;
|
|
154
201
|
}
|
|
155
202
|
export interface ValtheraCompatible {
|
|
156
203
|
c(collection: string): CollectionManager;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wxn0brp/vql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"author": "wxn0brP",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"query-language"
|
|
28
28
|
],
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@wxn0brp/db-core": ">=0.
|
|
30
|
+
"@wxn0brp/db-core": ">=0.3.0",
|
|
31
31
|
"@wxn0brp/falcon-frame": ">=0.5.3",
|
|
32
32
|
"@wxn0brp/gate-warden": ">=0.5.0"
|
|
33
33
|
},
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/bun": "*",
|
|
47
47
|
"@types/node": "*",
|
|
48
|
-
"@wxn0brp/db": "^0.
|
|
49
|
-
"@wxn0brp/db-core": "^0.
|
|
48
|
+
"@wxn0brp/db": "^0.41.0",
|
|
49
|
+
"@wxn0brp/db-core": "^0.3.0",
|
|
50
50
|
"@wxn0brp/falcon-frame": "^0.5.3",
|
|
51
51
|
"@wxn0brp/gate-warden": "^0.5.0",
|
|
52
52
|
"esbuild": "*",
|