denis 2024-01-07 21:01:58 +03:00
parent f6f9af986b
commit f6cec3232d
8 changed files with 129 additions and 22 deletions

5
domain.d.ts vendored
View File

@ -47,6 +47,7 @@ type FilterWithSet = {
type: ExpressionType["Filter"], type: ExpressionType["Filter"],
set: string, set: string,
filter: Filter, filter: Filter,
field: string,
}; };
type Expression = type Expression =
@ -65,9 +66,9 @@ type StringNode = BaseNode & {
value: string; value: string;
}; };
type MapString = BaseNode & { type MapNode = BaseNode & {
valueType: NodeValueType["Map"]; valueType: NodeValueType["Map"];
value: { [key: string]: Node["uuid"]; }; value: { [key: string]: BaseNode["uuid"]; };
}; };
type ExpressionNode = BaseNode & { type ExpressionNode = BaseNode & {

57
package-lock.json generated
View File

@ -8,9 +8,12 @@
"name": "refdb", "name": "refdb",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": {
"dot-prop": "^8.0.2"
},
"devDependencies": { "devDependencies": {
"@types/node": "^20.10.6", "@types/node": "^20.10.6",
"typescript": "4.9.3" "typescript": "5.3.3"
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
@ -22,17 +25,42 @@
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"node_modules/dot-prop": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz",
"integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==",
"dependencies": {
"type-fest": "^3.8.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/type-fest": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
"integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.9.3", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
}, },
"engines": { "engines": {
"node": ">=4.2.0" "node": ">=14.17"
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
@ -52,10 +80,23 @@
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"dot-prop": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz",
"integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==",
"requires": {
"type-fest": "^3.8.0"
}
},
"type-fest": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
"integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="
},
"typescript": { "typescript": {
"version": "4.9.3", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true "dev": true
}, },
"undici-types": { "undici-types": {

View File

@ -16,6 +16,9 @@
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/node": "^20.10.6", "@types/node": "^20.10.6",
"typescript": "4.9.3" "typescript": "5.3.3"
},
"dependencies": {
"dot-prop": "^8.0.2"
} }
} }

View File

@ -1,4 +1,6 @@
import { getProperty } from 'dot-prop';
import * as crypto from 'node:crypto'; import * as crypto from 'node:crypto';
import { filter } from './filter/filter';
const NOT_DEFINED_SET = "NOT_DEFINED"; const NOT_DEFINED_SET = "NOT_DEFINED";
@ -73,9 +75,12 @@ export class DataBase {
if (cache != null) { if (cache != null) {
return cache; return cache;
} }
const result = this.calculateExpression(node);
this.expressionCacheMap.set(node.uuid, result);
return result;
} }
private calculateExpression(node: ExpressionNode) { private calculateExpression(node: ExpressionNode): ExpressionResult {
switch (node.value.type) { switch (node.value.type) {
case "count": { case "count": {
if (node.value.hasOwnProperty("set")) { if (node.value.hasOwnProperty("set")) {
@ -92,9 +97,33 @@ export class DataBase {
break; break;
} }
case "filter": { case "filter": {
switch (typeof node.value.filter.value) {
case "number": {
if (node.value.hasOwnProperty("set")) {
const { set, field, filter: filterObj } = node.value as FilterWithSet;
const setValues = this.getSet(set);
return setValues.filter((it) => {
const candidate = getProperty(it, field) as PrimitiveValue;
return filter(
filterObj.predicate,
candidate,
filterObj.value
);
}) as ExpressionResult;
}
if (node.value.hasOwnProperty("expression")) {
const exprNode: ExpressionNode = this.nodeMap.get((node.value as FilterWithExpression).expression);
const expressionValue = this.getExpression(exprNode.id);
if (expressionValue instanceof Array) {
return expressionValue.length;
}
}
}
}
break;
} }
} }
return null as ExpressionResult;
} }
} }

28
src/filter/filter.ts Normal file
View File

@ -0,0 +1,28 @@
export function filter(
filterType: Filter["predicate"],
candidate: Filter["value"],
expect: Filter["value"],
): boolean {
switch (filterType) {
case "equal": {
return candidate === expect;
}
case "greatThat": {
return candidate > expect;
}
case "greatThatEqual": {
return candidate >= expect;
}
case "lessThat": {
return candidate < expect;
}
case "lessThatEqual": {
return candidate <= expect;
}
case "include": {
return (candidate as string).toUpperCase().includes((expect as string).toUpperCase());
}
}
}

View File

@ -32,14 +32,17 @@ for (const user of users) {
const ageExp = db.addNode({ const ageExp = db.addNode({
set: "users_exp", set: "users_exp",
valueType: "expression", valueType: "expression",
id: "userExp_gt_13",
value: { value: {
type: "filter", type: "filter",
set: "user", set: "user",
field: "age",
filter: { filter: {
predicate: "greatThat", predicate: "greatThat",
value: 13 value: 13
} }
} }
}); } as ExpressionNode);
console.log(db.getSet("user")); console.log(db.getSet("user"));
console.log(db.getExpression("userExp_gt_13"));

View File

@ -1,22 +1,24 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ "target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": [ "lib": [
"es6" "es6",
"es7",
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ ], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"module": "commonjs", /* Specify what module code is generated. */ "module": "ES6", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */ "rootDir": "./src", /* Specify the root folder within your source files. */
"resolveJsonModule": true, /* Enable importing .json files. */ "resolveJsonModule": true, /* Enable importing .json files. */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */ "outDir": "./dist", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": false, /* Enable all strict type-checking options. */ "strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */ "skipLibCheck": false, /* Skip type checking all .d.ts files. */
"moduleResolution": "Node",
}, },
"include": [ "include": [
"./src/**.ts", "./src/**/*.ts",
"./domain.d.ts" "./domain.d.ts"
], ],
"exclude": [ "exclude": [