From b085467bf432119d99d8221e420782b50ff22e3f Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 6 Nov 2023 19:01:11 +0200 Subject: [PATCH 1/7] chore: TS for math module --- package-lock.json | 27 +++++++++--- package.json | 1 + src/entity/in_memory.ts | 3 +- src/{math.js => math.ts} | 89 ++++++++++++++++++---------------------- src/utils/schemas.ts | 6 +-- 5 files changed, 66 insertions(+), 60 deletions(-) rename src/{math.js => math.ts} (72%) diff --git a/package-lock.json b/package-lock.json index 56090161..b8aa64dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1621,6 +1621,21 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==" }, + "@types/mathjs": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@types/mathjs/-/mathjs-3.21.1.tgz", + "integrity": "sha512-2q5o+7V6/aJqvaap6jmQPQddIwDh35KFx61SbKfoT8dkchL+AsqtQhrpxo99by0L4uXehZTl4gSyiJMjyA0kRg==", + "requires": { + "decimal.js": "^10.0.0" + }, + "dependencies": { + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + } + } + }, "@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -5656,7 +5671,7 @@ "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", "dev": true, "requires": { "es6-error": "^4.0.1" @@ -5665,7 +5680,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-from-string": { @@ -5834,7 +5849,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-function-length": { @@ -6108,7 +6123,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-final-newline": { @@ -6183,7 +6198,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "thenify": { @@ -6205,7 +6220,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "timers-ext": { diff --git a/package.json b/package.json index 3e925558..65d24208 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@types/crypto-js": "^4.1.1", "@types/js-yaml": "^4.0.5", "@types/json-schema": "^7.0.12", + "@types/mathjs": "^3.21.1", "@types/mocha": "^10.0.1", "@types/node": "^20.4.2", "@types/react-jsonschema-form": "^1.7.8", diff --git a/src/entity/in_memory.ts b/src/entity/in_memory.ts index 93d27e13..b032fa7c 100644 --- a/src/entity/in_memory.ts +++ b/src/entity/in_memory.ts @@ -1,3 +1,4 @@ +import { JSONSchema6 } from "json-schema"; import getValue from "lodash/get"; import omit from "lodash/omit"; @@ -216,7 +217,7 @@ export class InMemoryEntity { /** * Returns class JSON schema */ - static get jsonSchema() { + static get jsonSchema(): JSONSchema6 | undefined { try { return getSchemaByClassName(this.name); } catch (e) { diff --git a/src/math.js b/src/math.ts similarity index 72% rename from src/math.js rename to src/math.ts index 322ab21f..4c156248 100644 --- a/src/math.js +++ b/src/math.ts @@ -11,39 +11,36 @@ import { tolerance as TOLERANCE } from "./constants"; const EPSILON = 1e-8; /** * @summary Returns scalar product of vectors - * @param v1 {Number[]} Vector 1 - * @param v2 {Number[]} Vector 2 - * @return {Number} + * @param v1 Vector 1 + * @param v2 Vector 2 */ - -const product = (v1, v2) => { +const product = (v1: number[], v2: number[]) => { return math.multiply(v1, math.transpose(v2)); }; /** * @summary Returns length of a vector. - * @param v {Number[]} Vector - * @return {Number} + * @param v Vector */ -const vlen = (v) => { +const vlen = (v: number[]) => { return math.sqrt(product(v, v)); }; /** * @summary Returns angle between `a` and `b` vectors. - * @param a {Number[]} Vector a - * @param b {Number[]} Vector b - * @param [unit] {String} `rad`, `deg` - * @return {Number} + * @param a Vector a + * @param b Vector b + * @param unit `rad`, `deg` */ -const angle = (a, b, unit) => { +const angle = (a:number[], b:number[], unit: string) => { const lenA = vlen(a); const lenB = vlen(b); + // @ts-ignore return math.unit(math.acos(product(a, b) / (lenA * lenB)), "rad").toNumber(unit || "deg"); }; -const angleUpTo90 = (...args) => { - const angleUpTo180 = angle(...args); +const angleUpTo90 = (a:number[], b:number[], unit: string) => { + const angleUpTo180 = angle(a,b, unit); return angleUpTo180 < 90 ? angleUpTo180 : 180 - angleUpTo180; }; @@ -53,7 +50,7 @@ const angleUpTo90 = (...args) => { * @param v2 {Number[]} Vector * @return {Number} */ -const vDist = (v1, v2) => { +const vDist = (v1:number[], v2:number[]) => { if (v1.length !== v2.length) { console.error( "Attempting to calculate distance between vectors of different dimensionality", @@ -70,35 +67,36 @@ const vDist = (v1, v2) => { * @param tolerance {Number} Tolerance * @return {Number} */ -const vEqualWithTolerance = (vec1, vec2, tolerance = TOLERANCE.pointsDistance) => - vDist(vec1, vec2) <= tolerance; +const vEqualWithTolerance = (vec1:number[], vec2:number[], tolerance = TOLERANCE.pointsDistance): boolean => { + const val = vDist(vec1, vec2); + if (typeof val === "undefined") { + return false; + } + // @ts-ignore + return val <= tolerance; +} + /** * @summary Returns 0 if passed number is less than Made.math.EPSILON. * @param n {Number} * @return {Number} */ -const roundToZero = (n) => { +const roundToZero = (n: number) => { return Math.abs(n) < EPSILON ? 0 : n; }; /** * @summary Returns number with specified precision. - * @param x {Number} - * @param n {Number} - * @return {Number} */ -const precise = (x, n = 7) => { +const precise = (x: number, n = 7) => { return Number(x.toPrecision(n)); }; /** * @summary Returns mod of the passed value with the specified tolerance. - * @param num {Number} - * @param tolerance {Number} - * @return {Number} */ -const mod = (num, tolerance = 0.001) => { +const mod = (num: number, tolerance = 0.001): number => { const m = num % 1; const x = num >= 0 ? m : 1 + m; @@ -112,11 +110,11 @@ const mod = (num, tolerance = 0.001) => { * @summary Returns cartesian of passed arrays. * @example combinations([1,2], [4,5], [6]) = [[1,4,6], [1,5,6], [2,4,6], [2,5,6]]; */ -const cartesianProduct = (...arg) => { - const r = []; +const cartesianProduct = (...arg: number[][]):number[][] => { + const r: number[][] = []; const max = arg.length - 1; - const helper = (arr, i) => { + const helper = (arr: number[], i: number) => { for (let j = 0, l = arg[i].length; j < l; j++) { const a = arr.slice(0); // clone arr a.push(arg[i][j]); @@ -134,20 +132,16 @@ const cartesianProduct = (...arg) => { /** * @summary Returns all possible positive integer combinations where each value changes from 0 to a, b, c. - * @param a {Number} - * @param b {Number} - * @param tolerance {Number} */ -const almostEqual = (a, b, tolerance = TOLERANCE.pointsDistance) => { +const almostEqual = (a: number, b: number, tolerance = TOLERANCE.pointsDistance): boolean => { return Math.abs(a - b) < tolerance; }; /** * @summary Returns true if number is 0 <= x < 1, inclusive, otherwise false. * Helper to deal with JS arithmetic artifacts. - * @number number {Number} */ -const isBetweenZeroInclusiveAndOne = (number, tolerance = TOLERANCE.length) => { +const isBetweenZeroInclusiveAndOne = (number: number, tolerance = TOLERANCE.length): boolean => { return roundToZero(number) >= 0 && !almostEqual(number, 1, tolerance) && number < 1; }; @@ -160,7 +154,7 @@ const isBetweenZeroInclusiveAndOne = (number, tolerance = TOLERANCE.length) => { * @param b * @param c */ -const combinations = (a, b, c) => { +const combinations = (a: number, b: number, c: number) => { const combs = []; for (let i = 0; i <= a; i++) { for (let j = 0; j <= b; j++) { @@ -175,7 +169,7 @@ const combinations = (a, b, c) => { /* * @summary Same as `combinations` but accepting intervals (tuples) of integers: eg. [-3, 4] */ -const combinationsFromIntervals = (arrA, arrB, arrC) => { +const combinationsFromIntervals = (arrA: number[], arrB:number[], arrC: number[]) => { const combs = []; for (let i = arrA[0]; i <= arrA[1]; i++) { for (let j = arrB[0]; j <= arrB[1]; j++) { @@ -187,21 +181,18 @@ const combinationsFromIntervals = (arrA, arrB, arrC) => { return combs; }; -const roundValueToNDecimals = (value, decimals = 3) => { +const roundValueToNDecimals = (value: number, decimals = 3) => { return parseFloat(value.toFixed(decimals)); }; /** * @summary Returns n splits of the passed segment. - * @param point1 {Number[]} - * @param point2 {Number[]} - * @param n {Number} */ -const calculateSegmentsBetweenPoints3D = (point1, point2, n) => { +const calculateSegmentsBetweenPoints3D = (point1: (string | number)[], point2:(string | number)[], n: number | string) => { // safely parse if passed strings - const point1_ = point1.map((x) => parseFloat(x)); - const point2_ = point2.map((x) => parseFloat(x)); - const n_ = parseInt(n); + const point1_ = point1.map((x) => typeof x === "string" ? parseFloat(x) : x); + const point2_ = point2.map((x) => typeof x === "string" ? parseFloat(x) : x); + const n_ = typeof n === "string" ? parseInt(n) : n; const result = []; for (let i = 1; i < n_; i++) { @@ -223,10 +214,10 @@ const calculateSegmentsBetweenPoints3D = (point1, point2, n) => { * @locus Client * @method * @name toPrecision - * @param {Number} number - * @param {Number} precision Optional. An integer specifying the number of significant digits. + * @param number + * @param precision Optional. An integer specifying the number of significant digits. */ -export function numberToPrecision(number, precision) { +export function numberToPrecision(number: number | string, precision?: number): string { if (_.isNumber(number)) { return number.toPrecision(precision); } diff --git a/src/utils/schemas.ts b/src/utils/schemas.ts index 0b0f096b..6d9b2001 100644 --- a/src/utils/schemas.ts +++ b/src/utils/schemas.ts @@ -1,10 +1,9 @@ import { JSONSchema } from "@exabyte-io/esse.js/schema"; +import { JSONSchema7Definition } from "json-schema"; import forEach from "lodash/forEach"; import hasProperty from "lodash/has"; import isEmpty from "lodash/isEmpty"; -import { JSONSchema7Definition } from "json-schema"; - import { JSONSchemasInterface } from "../JSONSchemasInterface"; export * from "@exabyte-io/esse.js/lib/js/esse/schemaUtils"; @@ -37,7 +36,7 @@ interface Node { * @returns */ export function getSchemaByClassName(className: string) { - return schemas[className] ? JSONSchemasInterface.schemaById(schemas[className]) : null; + return schemas[className] ? JSONSchemasInterface.schemaById(schemas[className]) : undefined; } /** @@ -245,7 +244,6 @@ const buildNamedEntitiesDependencies = (entities: NamedEntity[]) => { schemaByNamedEntityName(entity.name) || defaultNamedEntitySchema(entity.name); return { - ...filterForGenerativeProperties(schema), }; }), From abc8b63bea1e2df20a760cb20485c5ac33d79f56 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 7 Nov 2023 00:19:59 +0200 Subject: [PATCH 2/7] update: improve entity clone method --- src/entity/in_memory.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/entity/in_memory.ts b/src/entity/in_memory.ts index b032fa7c..f1b7102a 100644 --- a/src/entity/in_memory.ts +++ b/src/entity/in_memory.ts @@ -71,7 +71,6 @@ export class InMemoryEntity { /** * @summary Array of fields to exclude from resulted JSON - * @param {String[]} exclude */ toJSON(exclude: string[] = []) { return (this.constructor as typeof InMemoryEntity)._isDeepCloneRequired @@ -89,13 +88,17 @@ export class InMemoryEntity { /** * @summary Clone this entity - * @param extraContext {Object} - * @returns {*} */ - clone(extraContext: object = {}): InMemoryEntity { + clone(extraContext: object = {}): this { const Entity = this.constructor as typeof InMemoryEntity; - return new Entity({ ...this.toJSON(), ...extraContext }); + // @ts-ignore + const object: typeof this = new Entity({ + ...this.toJSON(), + ...extraContext, + }); + + return object; } // override upon inheritance From 71996b93305219b3138f72bde277c6fa478107d0 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 7 Nov 2023 00:45:48 +0200 Subject: [PATCH 3/7] update: improve entity clone method --- src/entity/in_memory.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/entity/in_memory.ts b/src/entity/in_memory.ts index f1b7102a..ff98b5a8 100644 --- a/src/entity/in_memory.ts +++ b/src/entity/in_memory.ts @@ -89,11 +89,9 @@ export class InMemoryEntity { /** * @summary Clone this entity */ - clone(extraContext: object = {}): this { - const Entity = this.constructor as typeof InMemoryEntity; - + clone(extraContext?: object): T { // @ts-ignore - const object: typeof this = new Entity({ + const object: T = new this.constructor({ ...this.toJSON(), ...extraContext, }); From e90d9b067bbf97b6e5520b5adb057188bbcf945b Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Thu, 9 Nov 2023 16:37:09 +0200 Subject: [PATCH 4/7] chore: export nameValue interface --- src/utils/object.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/object.ts b/src/utils/object.ts index adc356ee..50c48c5d 100644 --- a/src/utils/object.ts +++ b/src/utils/object.ts @@ -92,7 +92,7 @@ export function renameKeysForObject( return result; } -interface NameValueObject { +export interface NameValueObject { name: string; value: unknown; [key: string]: unknown; From 801ad1d1ecec73375e51cc58b57506d62611d8f3 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 10 Nov 2023 14:36:32 +0200 Subject: [PATCH 5/7] chore: improve TS clone logic --- src/entity/in_memory.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/entity/in_memory.ts b/src/entity/in_memory.ts index ff98b5a8..e4146c75 100644 --- a/src/entity/in_memory.ts +++ b/src/entity/in_memory.ts @@ -89,9 +89,11 @@ export class InMemoryEntity { /** * @summary Clone this entity */ - clone(extraContext?: object): T { - // @ts-ignore - const object: T = new this.constructor({ + clone(extraContext?: object): this { + type ThisType = typeof this; + type TConstructor = { new (o: object): ThisType }; + + const object = new (this.constructor as TConstructor)({ ...this.toJSON(), ...extraContext, }); From 73f88573ef5180f5745393fa2b68b3eee70841ab Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 10 Nov 2023 15:06:15 +0200 Subject: [PATCH 6/7] chore: rename types --- src/entity/in_memory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entity/in_memory.ts b/src/entity/in_memory.ts index e4146c75..d2045537 100644 --- a/src/entity/in_memory.ts +++ b/src/entity/in_memory.ts @@ -91,9 +91,9 @@ export class InMemoryEntity { */ clone(extraContext?: object): this { type ThisType = typeof this; - type TConstructor = { new (o: object): ThisType }; + type ThisConstructor = { new (o: object): ThisType }; - const object = new (this.constructor as TConstructor)({ + const object = new (this.constructor as ThisConstructor)({ ...this.toJSON(), ...extraContext, }); From 832b39cf21730552aee07af0ab9aba4a403c1ea1 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 10 Nov 2023 16:10:41 +0200 Subject: [PATCH 7/7] chore: new esse schemas --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65d24208..d242595e 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@babel/preset-react": "7.16.7", "@babel/register": "^7.16.0", "@babel/runtime-corejs3": "7.16.8", - "@exabyte-io/esse.js": "2023.11.1-0", + "@exabyte-io/esse.js": "git+https://github.com/Exabyte-io/esse.git#update/SOF-7096", "@types/chai": "^4.3.5", "@types/crypto-js": "^4.1.1", "@types/js-yaml": "^4.0.5",