@wxn0brp/vql 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/dist/apiAbstract.d.ts +17 -0
- package/dist/apiAbstract.js +25 -0
- package/dist/apiAbstract.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -0
- package/dist/cpu/relation.d.ts +3 -0
- package/dist/cpu/relation.js +38 -0
- package/dist/cpu/relation.js.map +1 -0
- package/dist/cpu/request.d.ts +3 -0
- package/dist/cpu/request.js +66 -0
- package/dist/cpu/request.js.map +1 -0
- package/dist/cpu/string/index.d.ts +8 -0
- package/dist/cpu/string/index.js +55 -0
- package/dist/cpu/string/index.js.map +1 -0
- package/dist/cpu/string/json5.d.ts +2 -0
- package/dist/cpu/string/json5.js +9 -0
- package/dist/cpu/string/json5.js.map +1 -0
- package/dist/cpu/string/middle.d.ts +3 -0
- package/dist/cpu/string/middle.js +42 -0
- package/dist/cpu/string/middle.js.map +1 -0
- package/dist/cpu/string/simple.d.ts +2 -0
- package/dist/cpu/string/simple.js +152 -0
- package/dist/cpu/string/simple.js.map +1 -0
- package/dist/cpu/string/utils.d.ts +17 -0
- package/dist/cpu/string/utils.js +70 -0
- package/dist/cpu/string/utils.js.map +1 -0
- package/dist/cpu/string/yaml.d.ts +2 -0
- package/dist/cpu/string/yaml.js +20 -0
- package/dist/cpu/string/yaml.js.map +1 -0
- package/dist/cpu/utils.d.ts +1 -0
- package/dist/cpu/utils.js +15 -0
- package/dist/cpu/utils.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.js +14 -0
- package/dist/logger.js.map +1 -0
- package/dist/permissions/index.d.ts +2 -0
- package/dist/permissions/index.js +3 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/relation.d.ts +3 -0
- package/dist/permissions/relation.js +53 -0
- package/dist/permissions/relation.js.map +1 -0
- package/dist/permissions/request.d.ts +18 -0
- package/dist/permissions/request.js +130 -0
- package/dist/permissions/request.js.map +1 -0
- package/dist/permissions/utils.d.ts +5 -0
- package/dist/permissions/utils.js +23 -0
- package/dist/permissions/utils.js.map +1 -0
- package/dist/processor.d.ts +11 -0
- package/dist/processor.js +44 -0
- package/dist/processor.js.map +1 -0
- package/dist/sheet/index.d.ts +2 -0
- package/dist/sheet/index.js +65 -0
- package/dist/sheet/index.js.map +1 -0
- package/dist/sheet/load.d.ts +3 -0
- package/dist/sheet/load.js +23 -0
- package/dist/sheet/load.js.map +1 -0
- package/dist/tests/customExe.d.ts +6 -0
- package/dist/tests/customExe.js +27 -0
- package/dist/tests/customExe.js.map +1 -0
- package/dist/tests/db.d.ts +1 -0
- package/dist/tests/db.js +33 -0
- package/dist/tests/db.js.map +1 -0
- package/dist/tests/index.d.ts +1 -0
- package/dist/tests/index.js +104 -0
- package/dist/tests/index.js.map +1 -0
- package/dist/types/perm.d.ts +7 -0
- package/dist/types/perm.js +9 -0
- package/dist/types/perm.js.map +1 -0
- package/dist/types/vql.d.ts +118 -0
- package/dist/types/vql.js +2 -0
- package/dist/types/vql.js.map +1 -0
- package/dist/valid.d.ts +17 -0
- package/dist/valid.js +51 -0
- package/dist/valid.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const opPrefix = {
|
|
2
|
+
"-": "remove",
|
|
3
|
+
"+": "add",
|
|
4
|
+
"~": "update",
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Extracts metadata from a query string, including database name, operation,
|
|
8
|
+
* collection name, and the query body.
|
|
9
|
+
*
|
|
10
|
+
* @param input The input string to extract the information from.
|
|
11
|
+
* @returns An object with the following properties:
|
|
12
|
+
* - `db`: The database name.
|
|
13
|
+
* - `op`: The operation to perform, such as "find", "findOne", "add", "update", or "remove".
|
|
14
|
+
* - `collection`: The collection name.
|
|
15
|
+
* - `body`: The query body.
|
|
16
|
+
*/
|
|
17
|
+
export function extractMeta(input) {
|
|
18
|
+
// Split the input into non-empty, trimmed lines and remove comments
|
|
19
|
+
const split = input
|
|
20
|
+
.split("\n")
|
|
21
|
+
.map(line => line.trim())
|
|
22
|
+
.filter(line => line.length > 0 && !line.startsWith("#") && !line.startsWith("//"))
|
|
23
|
+
.join(" ")
|
|
24
|
+
.split(/\s+/)
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
// Ensure the query has at least database and collection
|
|
27
|
+
if (split.length < 2)
|
|
28
|
+
throw new Error("Invalid query");
|
|
29
|
+
// Handle cases like "db users" or "db users!"
|
|
30
|
+
if (split.length === 2 && /^[A-Za-z]/.test(split[0])) {
|
|
31
|
+
let op = split[0].endsWith("!") ? "findOne" : "find";
|
|
32
|
+
return { db: split[0], op, collection: split[1].replace("!", ""), body: "" };
|
|
33
|
+
}
|
|
34
|
+
// Handle cases like "db find users"
|
|
35
|
+
if (split.length === 3 && /^[A-Za-z0-9_-]+$/.test(split[2])) {
|
|
36
|
+
return { db: split[0], op: split[1], collection: split[2], body: "" };
|
|
37
|
+
}
|
|
38
|
+
// Default operation and initialization
|
|
39
|
+
const db = split.shift();
|
|
40
|
+
let op = "find";
|
|
41
|
+
let collection = "";
|
|
42
|
+
let body = "";
|
|
43
|
+
// Determine operation and collection based on special characters
|
|
44
|
+
if (["!", "-", "+", "~"].some(c => split[0].includes(c)) || // Check if operation is indicated by special character
|
|
45
|
+
[".", ":", "{"].some(c => split[1].includes(c)) // Check if query body is indicated by special character
|
|
46
|
+
) {
|
|
47
|
+
let temp = split.shift();
|
|
48
|
+
const firstChar = temp[0];
|
|
49
|
+
const lastChar = temp[temp.length - 1];
|
|
50
|
+
op = opPrefix[firstChar] || "find";
|
|
51
|
+
if (op !== "find")
|
|
52
|
+
temp = temp.slice(1); // Remove operation prefix if not "find"
|
|
53
|
+
if (lastChar === "!") {
|
|
54
|
+
if (op !== "add")
|
|
55
|
+
op += "One"; // Adjust operation for singular cases
|
|
56
|
+
collection = temp.slice(0, -1);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
collection = temp;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
op = split.shift(); // Assume second word is operation
|
|
64
|
+
collection = split.shift(); // Assume third word is collection
|
|
65
|
+
}
|
|
66
|
+
// Remaining words form the query body
|
|
67
|
+
body = split.join(" ");
|
|
68
|
+
return { db, op, collection, body };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/cpu/string/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { processVQL_MB } from "./middle.js";
|
|
2
|
+
import { extractMeta } from "./utils.js";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
export function parseVQLM(query) {
|
|
5
|
+
const { db, op, collection } = extractMeta(query);
|
|
6
|
+
let lineEndIndex = 0;
|
|
7
|
+
let foundNonWhitespace = false;
|
|
8
|
+
for (let i = 0; i < query.length; i++) {
|
|
9
|
+
if (!foundNonWhitespace && query[i] !== " " && query[i] !== "\t" && query[i] !== "\r" && query[i] !== "\n")
|
|
10
|
+
foundNonWhitespace = true;
|
|
11
|
+
if (foundNonWhitespace && query[i] === "\n") {
|
|
12
|
+
lineEndIndex = i;
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const body = query.slice(lineEndIndex + 1);
|
|
17
|
+
const parsed = yaml.load(body);
|
|
18
|
+
return processVQL_MB(db, op, collection, parsed);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=yaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.js","sourceRoot":"","sources":["../../../src/cpu/string/yaml.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,MAAM,UAAU,SAAS,CAAC,KAAa;IACnC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAElD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,kBAAkB,GAAG,IAAI,CAAC;QACtI,IAAI,kBAAkB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1C,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;QACV,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseSelect(select: object | object[]): any[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VQLConfig } from "../config.js";
|
|
2
|
+
export function parseSelect(select) {
|
|
3
|
+
if (Array.isArray(select)) {
|
|
4
|
+
if (!VQLConfig.strictSelect && select.length === 0)
|
|
5
|
+
return undefined;
|
|
6
|
+
return select;
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
const keys = Object.keys(select);
|
|
10
|
+
if (!VQLConfig.strictSelect && keys.length === 0)
|
|
11
|
+
return undefined;
|
|
12
|
+
return keys.filter(k => !!select[k]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cpu/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,UAAU,WAAW,CAAC,MAAyB;IACjD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACrE,OAAO,MAAM,CAAC;IAClB,CAAC;SAAM,CAAC;QACJ,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACnE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { VQLProcessor } from "./processor.js";
|
|
2
|
+
import { VQLConfig } from "./config.js";
|
|
3
|
+
import { createValtheraAdapter } from "./apiAbstract.js";
|
|
4
|
+
export default VQLProcessor;
|
|
5
|
+
export { createValtheraAdapter, VQLConfig };
|
|
6
|
+
export * as VQLSheet from "./sheet/load.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { VQLProcessor } from "./processor.js";
|
|
2
|
+
import { VQLConfig } from "./config.js";
|
|
3
|
+
import { createValtheraAdapter } from "./apiAbstract.js";
|
|
4
|
+
export default VQLProcessor;
|
|
5
|
+
export { createValtheraAdapter, VQLConfig };
|
|
6
|
+
export * as VQLSheet from "./sheet/load.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,eAAe,YAAY,CAAC;AAC5B,OAAO,EACH,qBAAqB,EACrB,SAAS,EACZ,CAAA;AACD,OAAO,KAAK,QAAQ,MAAM,cAAc,CAAC"}
|
package/dist/logger.d.ts
ADDED
package/dist/logger.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ConsoleTransport, FileTransport, Logger } from "@wxn0brp/wts-logger";
|
|
2
|
+
const logger = new Logger({
|
|
3
|
+
transports: [
|
|
4
|
+
new ConsoleTransport(),
|
|
5
|
+
new FileTransport("data/execution.log")
|
|
6
|
+
],
|
|
7
|
+
loggerName: "VQL"
|
|
8
|
+
});
|
|
9
|
+
export function logLog(instanceName, message) {
|
|
10
|
+
const logMessage = `[${instanceName}] ${message}`;
|
|
11
|
+
logger.info(logMessage);
|
|
12
|
+
}
|
|
13
|
+
export default logger;
|
|
14
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE9E,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;IACtB,UAAU,EAAE;QACR,IAAI,gBAAgB,EAAE;QACtB,IAAI,aAAa,CAAC,oBAAoB,CAAC;KAC1C;IACD,UAAU,EAAE,KAAK;CACpB,CAAC,CAAC;AAEH,MAAM,UAAU,MAAM,CAAC,YAAoB,EAAE,OAAY;IACrD,MAAM,UAAU,GAAG,IAAI,YAAY,KAAK,OAAO,EAAE,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC5B,CAAC;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PermCRUD } from "../types/perm.js";
|
|
2
|
+
import { extractPathsFromData, hashKey } from "./utils.js";
|
|
3
|
+
import { VQLConfig } from "../config.js";
|
|
4
|
+
export async function checkRelationPermission(gw, user, query) {
|
|
5
|
+
const { path, search, relations, select } = query.r;
|
|
6
|
+
// Helper function to recursively check permissions with fallback mechanism
|
|
7
|
+
const checkPermissionRecursively = async (entityId, fallbackLevels = []) => {
|
|
8
|
+
// Check if the user has access to the current entity
|
|
9
|
+
const result = await gw.hasAccess(user.id, entityId, PermCRUD.READ);
|
|
10
|
+
if (result.granted) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
// If the result is "entity-404", check the next fallback level
|
|
14
|
+
if (!VQLConfig.strictACL && result.via === "entity-404" && fallbackLevels.length > 0) {
|
|
15
|
+
const nextFallbackEntityId = hashKey(fallbackLevels.slice(0, -1));
|
|
16
|
+
return checkPermissionRecursively(nextFallbackEntityId, fallbackLevels.slice(0, -2));
|
|
17
|
+
}
|
|
18
|
+
// If no fallback levels are left or the result is not "entity-404", deny access
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
21
|
+
// Check permission for the relation field in the parent collection
|
|
22
|
+
if (!await checkPermissionRecursively(hashKey(path), path)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Check permissions for search fields
|
|
26
|
+
const searchPaths = extractPathsFromData(search || {});
|
|
27
|
+
for (const searchPath of searchPaths) {
|
|
28
|
+
const key = [...path, ...searchPath.path, searchPath.key];
|
|
29
|
+
if (!await checkPermissionRecursively(hashKey(key), key)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Check permissions for select fields
|
|
34
|
+
if (select) {
|
|
35
|
+
for (const fieldPath of select) {
|
|
36
|
+
const key = [...path, fieldPath];
|
|
37
|
+
if (!await checkPermissionRecursively(hashKey(key), key)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Recursively check nested relations
|
|
43
|
+
if (relations) {
|
|
44
|
+
for (const relationKey in relations) {
|
|
45
|
+
const r = relations[relationKey];
|
|
46
|
+
if (!await checkRelationPermission(gw, user, { r })) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=relation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation.js","sourceRoot":"","sources":["../../src/permissions/relation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,EAAmB,EACnB,IAAS,EACT,KAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IAEpD,2EAA2E;IAC3E,MAAM,0BAA0B,GAAG,KAAK,EACpC,QAAgB,EAChB,iBAA2B,EAAE,EACb,EAAE;QAClB,qDAAqD;QACrD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEpE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,+DAA+D;QAC/D,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,YAAY,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnF,MAAM,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,0BAA0B,CAAC,oBAAoB,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzF,CAAC;QAED,gFAAgF;QAChF,OAAO,KAAK,CAAC;IACjB,CAAC,CAAC;IAEF,mEAAmE;IACnE,IAAI,CAAC,MAAM,0BAA0B,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,sCAAsC;IACtC,MAAM,WAAW,GAAG,oBAAoB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACvD,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,0BAA0B,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YACvD,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,IAAI,MAAM,EAAE,CAAC;QACT,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,SAAS,CAAa,CAAC;YAC7C,IAAI,CAAC,MAAM,0BAA0B,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBACvD,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,IAAI,SAAS,EAAE,CAAC;QACZ,KAAK,MAAM,WAAW,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;YACjC,IAAI,CAAC,MAAM,uBAAuB,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAS,CAAC,EAAE,CAAC;gBACzD,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GateWarden } from "@wxn0brp/gate-warden";
|
|
2
|
+
import { PermCRUD } from "../types/perm.js";
|
|
3
|
+
import { VQLRequest } from "../types/vql.js";
|
|
4
|
+
export declare function extractPaths(query: VQLRequest): {
|
|
5
|
+
db: string;
|
|
6
|
+
c: string;
|
|
7
|
+
paths: {
|
|
8
|
+
filed?: string;
|
|
9
|
+
p?: PermCRUD;
|
|
10
|
+
c?: PermCRUD;
|
|
11
|
+
path?: string[];
|
|
12
|
+
}[];
|
|
13
|
+
};
|
|
14
|
+
export declare function processFieldPath(pathObj: {
|
|
15
|
+
path: string[];
|
|
16
|
+
key: string;
|
|
17
|
+
}): string[];
|
|
18
|
+
export declare function checkRequestPermission(gw: GateWarden<any>, user: any, query: VQLRequest): Promise<boolean>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { PermCRUD } from "../types/perm.js";
|
|
2
|
+
import { extractPathsFromData, hashKey } from "./utils.js";
|
|
3
|
+
import { VQLConfig } from "../config.js";
|
|
4
|
+
export function extractPaths(query) {
|
|
5
|
+
const operation = Object.keys(query.d)[0];
|
|
6
|
+
const collection = query.d[operation].collection;
|
|
7
|
+
const permPaths = {
|
|
8
|
+
db: hashKey(query.db),
|
|
9
|
+
c: collection,
|
|
10
|
+
paths: []
|
|
11
|
+
};
|
|
12
|
+
switch (operation) {
|
|
13
|
+
case "f":
|
|
14
|
+
case "find":
|
|
15
|
+
case "findOne":
|
|
16
|
+
const qf = query.d[operation];
|
|
17
|
+
permPaths.paths.push({ filed: extractPathsFromData(qf.search), p: PermCRUD.READ });
|
|
18
|
+
break;
|
|
19
|
+
case "add":
|
|
20
|
+
permPaths.paths.push({ c: PermCRUD.CREATE });
|
|
21
|
+
break;
|
|
22
|
+
case "update":
|
|
23
|
+
case "updateOne":
|
|
24
|
+
const qu = query.d[operation];
|
|
25
|
+
permPaths.paths.push({ filed: extractPathsFromData(qu.search), p: PermCRUD.READ });
|
|
26
|
+
permPaths.paths.push({ filed: extractPathsFromData(qu.updater), p: PermCRUD.UPDATE });
|
|
27
|
+
break;
|
|
28
|
+
case "remove":
|
|
29
|
+
case "removeOne":
|
|
30
|
+
permPaths.paths.push({ c: PermCRUD.DELETE });
|
|
31
|
+
break;
|
|
32
|
+
case "updateOneOrAdd":
|
|
33
|
+
const qo = query.d[operation];
|
|
34
|
+
permPaths.paths.push({ c: PermCRUD.CREATE });
|
|
35
|
+
permPaths.paths.push({ filed: extractPathsFromData(qo.search), p: PermCRUD.READ });
|
|
36
|
+
permPaths.paths.push({ filed: extractPathsFromData(qo.updater), p: PermCRUD.UPDATE });
|
|
37
|
+
break;
|
|
38
|
+
case "checkCollection":
|
|
39
|
+
case "getCollections":
|
|
40
|
+
case "issetCollection":
|
|
41
|
+
case "removeCollection":
|
|
42
|
+
permPaths.paths.push({ c: PermCRUD.COLLECTION });
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
permPaths.paths = permPaths.paths.map(path => {
|
|
46
|
+
if (!path.filed)
|
|
47
|
+
return path;
|
|
48
|
+
return path.filed.map(filed => {
|
|
49
|
+
const processedPath = [query.db, collection, ...processFieldPath(filed)];
|
|
50
|
+
return { filed: hashKey(processedPath), path: processedPath, p: path.p };
|
|
51
|
+
});
|
|
52
|
+
}).flat();
|
|
53
|
+
return permPaths;
|
|
54
|
+
}
|
|
55
|
+
export function processFieldPath(pathObj) {
|
|
56
|
+
let subsetMode = false;
|
|
57
|
+
const processedPath = [];
|
|
58
|
+
for (const part of pathObj.path) {
|
|
59
|
+
if (subsetMode) {
|
|
60
|
+
processedPath.push(part);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
if (part.startsWith("$")) {
|
|
64
|
+
if (part === "$subset") {
|
|
65
|
+
subsetMode = true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
processedPath.push(part);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (subsetMode) {
|
|
74
|
+
processedPath.push(pathObj.key);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (!pathObj.key.startsWith("$")) {
|
|
78
|
+
processedPath.push(pathObj.key);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return processedPath;
|
|
82
|
+
}
|
|
83
|
+
export async function checkRequestPermission(gw, user, query) {
|
|
84
|
+
if (!query)
|
|
85
|
+
return false;
|
|
86
|
+
const permPaths = extractPaths(query);
|
|
87
|
+
// Helper function to recursively check permissions
|
|
88
|
+
const checkPermissionRecursively = async (entityId, requiredPerm, fallbackLevels = []) => {
|
|
89
|
+
// Check if the user has access to the current entity
|
|
90
|
+
const result = await gw.hasAccess(user.id, entityId, requiredPerm);
|
|
91
|
+
if (result.granted) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
// If the result is "entity-404", check the next fallback level
|
|
95
|
+
if (!VQLConfig.strictACL && result.via === "entity-404" && fallbackLevels.length > 0) {
|
|
96
|
+
const nextFallbackEntityId = hashKey(fallbackLevels.slice(0, -1));
|
|
97
|
+
return checkPermissionRecursively(nextFallbackEntityId, requiredPerm, fallbackLevels.slice(0, -2));
|
|
98
|
+
}
|
|
99
|
+
// If no fallback levels are left or the result is not "entity-404", deny access
|
|
100
|
+
return false;
|
|
101
|
+
};
|
|
102
|
+
debugger;
|
|
103
|
+
// Check each required permission
|
|
104
|
+
const results = [];
|
|
105
|
+
for (const path of permPaths.paths) {
|
|
106
|
+
let entityId;
|
|
107
|
+
let requiredPerm;
|
|
108
|
+
let fallbackLevels = [];
|
|
109
|
+
if ("c" in path) {
|
|
110
|
+
// Collection-level permission: hash the combination of db and collection
|
|
111
|
+
entityId = hashKey([query.db, permPaths.c]);
|
|
112
|
+
requiredPerm = path.c;
|
|
113
|
+
// Fallback to database level if needed
|
|
114
|
+
fallbackLevels = [query.db];
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Field-level permission: use the hashed field path
|
|
118
|
+
entityId = path.filed;
|
|
119
|
+
requiredPerm = path.p;
|
|
120
|
+
// Fallback to collection and then database level if needed
|
|
121
|
+
fallbackLevels = path.path;
|
|
122
|
+
}
|
|
123
|
+
// Check permissions recursively
|
|
124
|
+
const result = await checkPermissionRecursively(entityId, requiredPerm, fallbackLevels);
|
|
125
|
+
results.push(result);
|
|
126
|
+
}
|
|
127
|
+
// All permissions must be granted
|
|
128
|
+
return results.every(result => result);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/permissions/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import { VQLConfig } from "../config.js";
|
|
3
|
+
export function hashKey(path) {
|
|
4
|
+
const json = JSON.stringify(path);
|
|
5
|
+
if (VQLConfig.hidePath)
|
|
6
|
+
return crypto.createHash("sha256").update(json).digest("hex");
|
|
7
|
+
else
|
|
8
|
+
return json;
|
|
9
|
+
}
|
|
10
|
+
export function extractPathsFromData(data, stack = []) {
|
|
11
|
+
const paths = [];
|
|
12
|
+
for (const key in data) {
|
|
13
|
+
const value = data[key];
|
|
14
|
+
if (typeof value === "object") {
|
|
15
|
+
paths.push(...extractPathsFromData(value, [...stack, key]));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
paths.push({ path: stack, key });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return paths;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/permissions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,UAAU,OAAO,CAAC,IAAS;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,SAAS,CAAC,QAAQ;QAClB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;;QAE9D,OAAO,IAAI,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAS,EAAE,QAAkB,EAAE;IAChE,MAAM,KAAK,GAAsC,EAAE,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACrC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Relation, ValtheraCompatible } from "@wxn0brp/db";
|
|
2
|
+
import { GateWarden } from "@wxn0brp/gate-warden";
|
|
3
|
+
import { VQL, VQLR } from "./types/vql.js";
|
|
4
|
+
export declare class VQLProcessor<GW = any> {
|
|
5
|
+
dbInstances: Record<string, ValtheraCompatible>;
|
|
6
|
+
gw: GateWarden<GW>;
|
|
7
|
+
relation: Relation;
|
|
8
|
+
preDefinedSheets: Map<string, VQL>;
|
|
9
|
+
constructor(dbInstances: Record<string, ValtheraCompatible>, gw?: GateWarden<GW>);
|
|
10
|
+
execute(queryRaw: VQLR | string, user: any): Promise<any>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Relation } from "@wxn0brp/db";
|
|
2
|
+
import { validateRaw, validateVql } from "./valid.js";
|
|
3
|
+
import { executeSheet } from "./sheet/index.js";
|
|
4
|
+
import { executeQuery } from "./cpu/request.js";
|
|
5
|
+
import { executeRelation } from "./cpu/relation.js";
|
|
6
|
+
import { parseStringQuery } from "./cpu/string/index.js";
|
|
7
|
+
export class VQLProcessor {
|
|
8
|
+
dbInstances;
|
|
9
|
+
gw;
|
|
10
|
+
relation;
|
|
11
|
+
preDefinedSheets = new Map();
|
|
12
|
+
constructor(dbInstances, gw = null) {
|
|
13
|
+
this.dbInstances = dbInstances;
|
|
14
|
+
this.gw = gw;
|
|
15
|
+
this.relation = new Relation(dbInstances);
|
|
16
|
+
}
|
|
17
|
+
async execute(queryRaw, user) {
|
|
18
|
+
if (typeof queryRaw === "string") {
|
|
19
|
+
try {
|
|
20
|
+
queryRaw = parseStringQuery(queryRaw);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
return { err: true, msg: "Invalid query", c: 400, why: `String query parsing error: ${e.message}` };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const validateRawResult = validateRaw(queryRaw);
|
|
27
|
+
if (validateRawResult !== true)
|
|
28
|
+
return validateRawResult;
|
|
29
|
+
const query = executeSheet(queryRaw, this.preDefinedSheets);
|
|
30
|
+
const validateVqlResult = validateVql(query);
|
|
31
|
+
if (validateVqlResult !== true)
|
|
32
|
+
return validateVqlResult;
|
|
33
|
+
if ("r" in query) {
|
|
34
|
+
return await executeRelation(this, query, user);
|
|
35
|
+
}
|
|
36
|
+
else if ("d" in query) {
|
|
37
|
+
return await executeQuery(this, query, user);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return { err: true, msg: "Invalid query", c: 400 };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processor.js","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,OAAO,YAAY;IAKV;IACA;IALJ,QAAQ,CAAW;IACnB,gBAAgB,GAAqB,IAAI,GAAG,EAAE,CAAC;IAEtD,YACW,WAA+C,EAC/C,KAAqB,IAAI;QADzB,gBAAW,GAAX,WAAW,CAAoC;QAC/C,OAAE,GAAF,EAAE,CAAuB;QAEhC,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAuB,EAAE,IAAS;QAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACD,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,+BAA+B,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YACxG,CAAC;QACL,CAAC;QAED,MAAM,iBAAiB,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,iBAAiB,KAAK,IAAI;YAAE,OAAO,iBAAiB,CAAC;QAEzD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAE5D,MAAM,iBAAiB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,iBAAiB,KAAK,IAAI;YAAE,OAAO,iBAAiB,CAAC;QAEzD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACf,OAAO,MAAM,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,MAAM,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACJ,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;QACvD,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { deepMerge } from "@wxn0brp/wts-deep-merge";
|
|
2
|
+
function trimPath(path) {
|
|
3
|
+
return path && path.length > 2 ? path.slice(0, 2) : path;
|
|
4
|
+
}
|
|
5
|
+
function relationFix(relations) {
|
|
6
|
+
for (const key in relations) {
|
|
7
|
+
const value = relations[key];
|
|
8
|
+
value.path = trimPath(value.path);
|
|
9
|
+
if (value.relations) {
|
|
10
|
+
relationFix(value.relations);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function pathFix(vql) {
|
|
15
|
+
if ("d" in vql) {
|
|
16
|
+
const key = Object.keys(vql.d)[0];
|
|
17
|
+
const value = vql.d[key];
|
|
18
|
+
value.path = trimPath(value.path);
|
|
19
|
+
}
|
|
20
|
+
else if ("r" in vql) {
|
|
21
|
+
const value = vql.r;
|
|
22
|
+
value.path = trimPath(value.path);
|
|
23
|
+
if (value.relations) {
|
|
24
|
+
relationFix(value.relations);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function replaceVariables(obj, variables) {
|
|
29
|
+
if (typeof obj === "string") {
|
|
30
|
+
if (obj.startsWith("$")) {
|
|
31
|
+
return variables[obj.slice(1)] || variables[obj];
|
|
32
|
+
}
|
|
33
|
+
return obj;
|
|
34
|
+
}
|
|
35
|
+
else if (Array.isArray(obj)) {
|
|
36
|
+
return obj.map((item) => replaceVariables(item, variables));
|
|
37
|
+
}
|
|
38
|
+
else if (typeof obj === "object") {
|
|
39
|
+
const newObj = {};
|
|
40
|
+
for (const key in obj) {
|
|
41
|
+
newObj[key] = replaceVariables(obj[key], variables);
|
|
42
|
+
}
|
|
43
|
+
return newObj;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return obj;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function executeSheet(query, preDefinedSheets) {
|
|
50
|
+
if ("ref" in query) {
|
|
51
|
+
if (preDefinedSheets.has(query.ref)) {
|
|
52
|
+
const ref = preDefinedSheets.get(query.ref);
|
|
53
|
+
const merge = deepMerge(query, ref);
|
|
54
|
+
pathFix(merge);
|
|
55
|
+
query = merge;
|
|
56
|
+
}
|
|
57
|
+
delete query.ref;
|
|
58
|
+
}
|
|
59
|
+
if ("var" in query) {
|
|
60
|
+
query = replaceVariables(query, query.var);
|
|
61
|
+
delete query.var;
|
|
62
|
+
}
|
|
63
|
+
return query;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sheet/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
2
|
+
function loadSheet(map, file) {
|
|
3
|
+
if (!existsSync(file)) {
|
|
4
|
+
throw new Error(`Sheet ${file} not found`);
|
|
5
|
+
}
|
|
6
|
+
const sheet = JSON.parse(readFileSync(file, "utf-8"));
|
|
7
|
+
for (const key in sheet) {
|
|
8
|
+
map.set(key, sheet[key]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function loadSheetsFromDir(dir) {
|
|
12
|
+
const map = new Map();
|
|
13
|
+
for (const file of readdirSync(dir)) {
|
|
14
|
+
loadSheet(map, `${dir}/${file}`);
|
|
15
|
+
}
|
|
16
|
+
return map;
|
|
17
|
+
}
|
|
18
|
+
export function loadSheetFromFile(file) {
|
|
19
|
+
const map = new Map();
|
|
20
|
+
loadSheet(map, file);
|
|
21
|
+
return map;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/sheet/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAG3D,SAAS,SAAS,CAAC,GAAqB,EAAE,IAAY;IAClD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAwB,CAAC;IAE7E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAe,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAe,CAAC;IACnC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,OAAO,GAAG,CAAC;AACf,CAAC"}
|