From 1eb69c2ba83b2fe7991261862996ee983c624447 Mon Sep 17 00:00:00 2001 From: tjduigna Date: Mon, 25 Jul 2022 09:03:47 -0400 Subject: [PATCH 1/5] feat: pre-commit hook --- .gitignore | 1 - .husky/pre-commit | 4 ++++ package.json | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100755 .husky/pre-commit diff --git a/.gitignore b/.gitignore index bc94ae96..1cdadc57 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ dist/ build/ node_modules/ .eslintcache -.husky/ .nyc_output/ .idea/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..36af2198 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged diff --git a/package.json b/package.json index cfbe7d96..43e8c3de 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "lint": "eslint src tests && prettier --write src tests", "lint:fix": "eslint --fix --cache src tests && prettier --write src tests", "transpile": "babel --out-dir dist src", - "postinstall": "npm run transpile" + "postinstall": "npm run transpile", + "prettier": "prettier --check src tests", + "prepare": "husky install" }, "repository": { "type": "git", From ddb0f30ba3e2a25cdde355168e0ce6afff50ce45 Mon Sep 17 00:00:00 2001 From: tjduigna Date: Mon, 25 Jul 2022 09:06:50 -0400 Subject: [PATCH 2/5] test: lint-staged --- src/entity/index.js | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/entity/index.js b/src/entity/index.js index 12f089af..b60dffd9 100644 --- a/src/entity/index.js +++ b/src/entity/index.js @@ -1,42 +1,34 @@ +import { InMemoryEntity } from "./in_memory"; +import { RuntimeContextFieldMixin } from "./mixins/context_runtime"; +import { HashedInputArrayMixin } from "./mixins/hash"; import { - InMemoryEntity, -} from "./in_memory"; - + DefaultableMixin, + HasDescriptionMixin, + HasMetadataMixin, + NamedEntityMixin, + TaggableMixin, +} from "./mixins/props"; +import { RuntimeItemsMixin } from "./mixins/runtime_items"; import { - NamedInMemoryEntity, DefaultableInMemoryEntity, - NamedDefaultableInMemoryEntity, HasMetadataNamedDefaultableInMemoryEntity, + NamedDefaultableInMemoryEntity, NamedDefaultableRepetitionContextAndRenderInMemoryEntity, NamedDefaultableRepetitionImportantSettingsInMemoryEntity, NamedDefaultableRepetitionRuntimeItemsImportantSettingsContextAndRenderHashedInMemoryEntity, + NamedInMemoryEntity, } from "./other"; - -import { - DefaultableMixin, - HasDescriptionMixin, - HasMetadataMixin, - TaggableMixin, - NamedEntityMixin, -} from "./mixins/props"; - -import { HashedInputArrayMixin } from "./mixins/hash"; -import { RuntimeItemsMixin } from "./mixins/runtime_items"; -import { RuntimeContextFieldMixin } from "./mixins/context_runtime"; - import { InMemoryEntitySet } from "./set"; import { ENTITY_SET_TYPES } from "./set/enums"; - import { constructEntitySetFactoryByConfig } from "./set/factory"; -import { InMemoryEntitySetMixin, InMemoryEntityInSetMixin } from "./set/mixins"; -import * as selectorsForEntitySet from "./set/selectors"; +import { InMemoryEntityInSetMixin, InMemoryEntitySetMixin } from "./set/mixins"; import { OrderedInMemoryEntityInSetMixin, OrderedInMemoryEntitySetMixin, } from "./set/ordered/mixins"; +import * as selectorsForEntitySet from "./set/selectors"; export { - InMemoryEntity, NamedInMemoryEntity, DefaultableInMemoryEntity, @@ -45,7 +37,6 @@ export { NamedDefaultableRepetitionContextAndRenderInMemoryEntity, NamedDefaultableRepetitionImportantSettingsInMemoryEntity, NamedDefaultableRepetitionRuntimeItemsImportantSettingsContextAndRenderHashedInMemoryEntity, - DefaultableMixin, HasDescriptionMixin, HasMetadataMixin, @@ -54,7 +45,6 @@ export { RuntimeItemsMixin, RuntimeContextFieldMixin, HashedInputArrayMixin, - InMemoryEntitySet, ENTITY_SET_TYPES, constructEntitySetFactoryByConfig, @@ -63,5 +53,4 @@ export { InMemoryEntityInSetMixin, OrderedInMemoryEntitySetMixin, OrderedInMemoryEntityInSetMixin, - }; From 0ea8c0ceb02e0ea9e62b835866e8df987da8cd90 Mon Sep 17 00:00:00 2001 From: tjduigna Date: Mon, 25 Jul 2022 09:14:44 -0400 Subject: [PATCH 3/5] feat: add plugin-prettier --- package-lock.json | 24 ++++++++++++++++++++++++ package.json | 3 ++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index d99434bf..5eea3111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2418,6 +2418,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-react": { "version": "7.30.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz", @@ -2601,6 +2610,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4384,6 +4399,15 @@ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", diff --git a/package.json b/package.json index 43e8c3de..6803ffcf 100644 --- a/package.json +++ b/package.json @@ -60,10 +60,11 @@ "eslint": "7.32.0", "eslint-config-airbnb": "19.0.2", "eslint-config-prettier": "8.3.0", - "eslint-plugin-react": "^7.30.0", "eslint-plugin-import": "2.25.3", "eslint-plugin-jsdoc": "37.1.0", "eslint-plugin-jsx-a11y": "6.5.1", + "eslint-plugin-prettier": "4.2.1", + "eslint-plugin-react": "7.30.0", "eslint-plugin-simple-import-sort": "7.0.0", "husky": "^7.0.4", "lint-staged": "^12.1.2", From 4c901dc42b0dce98b9467b5e06731736c991a513 Mon Sep 17 00:00:00 2001 From: tjduigna Date: Mon, 25 Jul 2022 10:46:04 -0400 Subject: [PATCH 4/5] feat: lints codejs --- package-lock.json | 13 +- package.json | 3 +- src/context/index.js | 13 +- src/context/mixins.js | 259 ++++++++++++++------------- src/context/pickers.js | 8 +- src/context/provider.js | 51 +++--- src/context/registry.js | 16 +- src/entity/in_memory.js | 40 +++-- src/entity/mixins/context.js | 16 +- src/entity/mixins/context_runtime.js | 2 +- src/entity/mixins/hash.js | 8 +- src/entity/mixins/props.js | 41 +++-- src/entity/mixins/repetition.js | 12 +- src/entity/mixins/runtime_items.js | 50 ++++-- src/entity/other.js | 20 +-- src/entity/set.js | 26 +-- src/entity/set/factory.js | 24 ++- src/entity/set/mixins.js | 47 +++-- src/entity/set/ordered.js | 9 +- src/entity/set/ordered/mixins.js | 27 +-- src/entity/set/ordered/utils.js | 16 +- src/entity/set/selectors.js | 34 ++-- src/index.js | 4 +- src/math.js | 18 +- src/utils/array.js | 9 +- src/utils/class.js | 68 ++++--- src/utils/codemirror.js | 8 +- src/utils/file.js | 30 ++-- src/utils/hash.js | 3 +- src/utils/index.js | 35 ++-- src/utils/object.js | 118 ++++++------ src/utils/object.tests.js | 50 ------ src/utils/selector.js | 10 +- src/utils/str.js | 15 +- src/utils/uuid.js | 2 +- tests/in_memory.tests.js | 12 +- tests/object.tests.js | 48 +++++ tests/provider.tests.js | 7 +- tests/setup.js | 2 +- tests/utils.class.js | 48 ++--- tests/utils.tests.js | 29 +-- 41 files changed, 659 insertions(+), 592 deletions(-) delete mode 100644 src/utils/object.tests.js create mode 100644 tests/object.tests.js diff --git a/package-lock.json b/package-lock.json index 5eea3111..fd2ccb9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3231,6 +3231,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true } } }, @@ -5119,10 +5125,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { "version": "2.3.0", diff --git a/package.json b/package.json index 6803ffcf..9ad9788d 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "mathjs": "^3.9.0", "mixwith": "^0.1.1", "underscore": "^1.13.3", - "underscore.string": "^3.3.4" + "underscore.string": "^3.3.4", + "uuid": "8.3.2" }, "devDependencies": { "chai": "^4.3.4", diff --git a/src/context/index.js b/src/context/index.js index 92792e4b..37a96f46 100644 --- a/src/context/index.js +++ b/src/context/index.js @@ -1,25 +1,21 @@ -import { ContextProvider } from "./provider"; -import { ContextProviderRegistryContainer } from "./registry"; - -import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; - import { ApplicationContextMixinBuilder, + JobContextMixin, MaterialContextMixinBuilder, MaterialsContextMixinBuilder, MaterialsSetContextMixin, MethodDataContextMixin, - JobContextMixin, WorkflowContextMixin, } from "./mixins"; +import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; +import { ContextProvider } from "./provider"; +import { ContextProviderRegistryContainer } from "./registry"; export { ContextProvider, ContextProviderRegistryContainer, - JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin, - ApplicationContextMixinBuilder, MaterialContextMixinBuilder, MaterialsContextMixinBuilder, @@ -27,5 +23,4 @@ export { MethodDataContextMixin, JobContextMixin, WorkflowContextMixin, - }; diff --git a/src/context/mixins.js b/src/context/mixins.js index 7a48d47f..6ae1ad8e 100644 --- a/src/context/mixins.js +++ b/src/context/mixins.js @@ -1,138 +1,153 @@ +/* eslint-disable max-classes-per-file */ import CryptoJS from "crypto-js"; import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; -export const ApplicationContextMixinBuilder = (applicationCls) => (superclass) => class extends superclass { - constructor(config) { - super(config); - if (!applicationCls) throw Error("ApplicationContextMixinBuilder: applicationCls is undefined"); - this._application = config.context && config.context.application || applicationCls.createDefault(); - } - - get application() { - return this._application; - } -}; - -export const MaterialContextMixinBuilder = (materialCls) => (superclass) => class extends superclass { - - constructor(config) { - super(config); - if (!materialCls) throw Error("MaterialContextMixinBuilder: materialCls is undefined"); - this._material = config.context && config.context.material; - if (!this._material) this._material = materialCls.createDefault(); - this.updateMaterialHash(); - } - - get isEditedIsSetToFalseOnMaterialUpdate() { - return false; - } - - updateMaterialHash() { - if (this.isEditedIsSetToFalseOnMaterialUpdate) this.isEdited = false; - this.extraData = {materialHash: this.material.hash}; - } - - // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too - // does not have an id. Here we catch when such material is used and avoid resetting isEdited - get isMaterialCreatedDefault() { - return !Boolean(this.material.id); - } - - get isMaterialUpdated() { - return Boolean(this.extraData && (this.extraData.materialHash !== this.material.hash)); - } - - get material() { - return this._material; - } -}; - -export const MaterialsSetContextMixin = (superclass) => class extends superclass { - - constructor(config) { - super(config); - this._materialsSet = this.config.context && this.config.context.materialsSet; - } - - get materialsSet() {return this._materialsSet} - - sortMaterialsByIndexInSet(materials = []) { - // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). - return materials.concat().sort((a, b) => compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false)); - } - -}; - -export const MaterialsContextMixinBuilder = (materialCls) => (superclass) => class extends superclass { - - constructor(config) { - super(config); - const materials = this.config.context && this.config.context.materials; - if (!materialCls) throw Error("MaterialsContextMixinBuilder: materialCls is undefined"); - this._materials = (materials && materials.length) ? materials : [materialCls.createDefault()]; - } - - get materials() {return this._materials} -}; - -export const MethodDataContextMixin = (superclass) => class extends superclass { - - constructor(config) { - super(config); - this._methodData = config.context && config.context.methodData || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } - - /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between - * subsequent initializations of the derived class. Not used at present and kept for the record. - */ - _initMethodDataHash() { - this.methodDataHash = CryptoJS.MD5(JSON.stringify(this.methodData)).toString(); - this.extraData = {methodDataHash: this.methodDataHash}; - if (!this._methodData) { - this._methodData = {}; - this.isEdited = false; - // Commented out to reduce effect on performance. Uncomment for debugging purposes. - // TODO: remove on next refactoring or convert to log - // console.warn("MethodDataContextMixin: methodData is undefined or null"); - } else { - if (this.isMethodDataUpdated) { - this.isEdited = false; - } else { - this.isEdited = config.isEdited; - } +export const ApplicationContextMixinBuilder = (applicationCls) => (superclass) => + class extends superclass { + constructor(config) { + super(config); + if (!applicationCls) + throw Error("ApplicationContextMixinBuilder: applicationCls is undefined"); + this._application = + (config.context && config.context.application) || applicationCls.createDefault(); } - } - get methodData() {return this._methodData} + get application() { + return this._application; + } + }; + +export const MaterialContextMixinBuilder = (materialCls) => (superclass) => + class extends superclass { + constructor(config) { + super(config); + if (!materialCls) throw Error("MaterialContextMixinBuilder: materialCls is undefined"); + this._material = config.context && config.context.material; + if (!this._material) this._material = materialCls.createDefault(); + this.updateMaterialHash(); + } - get isMethodDataUpdated() { - return Boolean(this.extraData && (this.extraData.methodDataHash !== this.methodDataHash)); - } + // eslint-disable-next-line class-methods-use-this + get isEditedIsSetToFalseOnMaterialUpdate() { + return false; + } -}; + updateMaterialHash() { + if (this.isEditedIsSetToFalseOnMaterialUpdate) this.isEdited = false; + this.extraData = { materialHash: this.material.hash }; + } -export const WorkflowContextMixin = (superclass) => class extends superclass { + // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too + // does not have an id. Here we catch when such material is used and avoid resetting isEdited + get isMaterialCreatedDefault() { + return !this.material.id; + } - constructor(config) { - super(config); - this._workflow = config.context && config.context.workflow || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } + get isMaterialUpdated() { + return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); + } - get workflow() {return this._workflow} + get material() { + return this._material; + } + }; -}; +export const MaterialsSetContextMixin = (superclass) => + class extends superclass { + constructor(config) { + super(config); + this._materialsSet = this.config.context && this.config.context.materialsSet; + } -export const JobContextMixin = (superclass) => class extends superclass { + get materialsSet() { + return this._materialsSet; + } - constructor(config) { - super(config); - this._job = config.context && config.context.job || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } + sortMaterialsByIndexInSet(materials = []) { + // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). + return materials + .concat() + .sort((a, b) => + compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false), + ); + } + }; + +export const MaterialsContextMixinBuilder = (materialCls) => (superclass) => + class extends superclass { + constructor(config) { + super(config); + const materials = this.config.context && this.config.context.materials; + if (!materialCls) throw Error("MaterialsContextMixinBuilder: materialCls is undefined"); + this._materials = + materials && materials.length ? materials : [materialCls.createDefault()]; + } - get job() {return this._job} + get materials() { + return this._materials; + } + }; + +export const MethodDataContextMixin = (superclass) => + class extends superclass { + constructor(config) { + super(config); + this._methodData = (config.context && config.context.methodData) || {}; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + } -}; + /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between + * subsequent initializations of the derived class. Not used at present and kept for the record. + */ + _initMethodDataHash() { + this.methodDataHash = CryptoJS.MD5(JSON.stringify(this.methodData)).toString(); + this.extraData = { methodDataHash: this.methodDataHash }; + if (!this._methodData) { + this._methodData = {}; + this.isEdited = false; + // Commented out to reduce effect on performance. Uncomment for debugging purposes. + // TODO: remove on next refactoring or convert to log + // console.warn("MethodDataContextMixin: methodData is undefined or null"); + } else if (this.isMethodDataUpdated) { + this.isEdited = false; + } else { + // eslint-disable-next-line no-undef + this.isEdited = config.isEdited; + } + } + + get methodData() { + return this._methodData; + } + + get isMethodDataUpdated() { + return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); + } + }; + +export const WorkflowContextMixin = (superclass) => + class extends superclass { + constructor(config) { + super(config); + this._workflow = (config.context && config.context.workflow) || {}; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + } + + get workflow() { + return this._workflow; + } + }; + +export const JobContextMixin = (superclass) => + class extends superclass { + constructor(config) { + super(config); + this._job = (config.context && config.context.job) || {}; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + } + + get job() { + return this._job; + } + }; diff --git a/src/context/pickers.js b/src/context/pickers.js index 5bdf081a..b5645abc 100644 --- a/src/context/pickers.js +++ b/src/context/pickers.js @@ -2,16 +2,12 @@ import _ from "underscore"; export const WorkflowContextPickKeysForMixin = (workflow) => { return { - workflow: _.pick(workflow, [ - "hasRelaxation" - ]) + workflow: _.pick(workflow, ["hasRelaxation"]), }; }; export const JobContextPickKeysForMixin = (job) => { return { - job: _.pick(job, [ - "parentJob" - ]) + job: _.pick(job, ["parentJob"]), }; }; diff --git a/src/context/provider.js b/src/context/provider.js index c63ba329..1170dd3e 100644 --- a/src/context/provider.js +++ b/src/context/provider.js @@ -10,22 +10,23 @@ * @notes Should hold static data only (see `setData` method), no classes or functions */ import lodash from "lodash"; + import { deepClone } from "../utils/clone"; export class ContextProvider { - constructor(config) { this.config = config; - this.name = config.name; // property name, ie. "kpath" + this.name = config.name; // property name, ie. "kpath" this.domain = config.domain || "default"; // if context is passed inside config, treat it as additional config + // eslint-disable-next-line no-param-reassign if (config.context) config = ContextProvider.createConfigFromContext(config); this.entityName = config.entityName || "unit"; // entity this provider yields data to, eg. "unit", "subworkflow" - this.data = config.data; // property data container - this.extraData = config.extraData; // property extraData container, used track changes to data, for example - this.isEdited = config.isEdited; // whether property was edited by user, available under `isEdited` key + this.data = config.data; // property data container + this.extraData = config.extraData; // property extraData container, used track changes to data, for example + this.isEdited = config.isEdited; // whether property was edited by user, available under `isEdited` key this.setIsEdited = this.setIsEdited.bind(this); this.getData = this.getData.bind(this); @@ -37,7 +38,7 @@ export class ContextProvider { static getConstructorConfig(config) { return { constructor: this.prototype.constructor, - config: config + config, }; } @@ -45,11 +46,16 @@ export class ContextProvider { const data = lodash.get(config.context, config.name); const isEdited = lodash.get(config.context, this.getIsEditedKeyByName(config.name)); const extraData = lodash.get(config.context, this.getExtraDataKeyByName(config.name)); - return Object.assign(config, data ? { - data, - extraData, - isEdited, - } : {}); + return Object.assign( + config, + data + ? { + data, + extraData, + isEdited, + } + : {}, + ); } setIsEdited(bool) { @@ -65,52 +71,53 @@ export class ContextProvider { } // override in children + // eslint-disable-next-line class-methods-use-this get defaultData() { - throw new Error('Not implemented.'); + throw new Error("Not implemented."); } // override in children + // eslint-disable-next-line class-methods-use-this transformData(data) { return data; } yieldData(...transformDataArgs) { - const extraDataObject = this.extraData ? {[this.extraDataKey]: this.extraData} : {}; + const extraDataObject = this.extraData ? { [this.extraDataKey]: this.extraData } : {}; return { ...extraDataObject, [this.name]: this.transformData(this.getData(), ...transformDataArgs), [this.isEditedKey]: this.isEdited, - } + }; } // override when this.data needs additional processing before making it available to rendering context // used to calculate explicit points path, for example yieldDataForRendering() { - return this.yieldData() + return this.yieldData(); } get extraDataKey() { - return `${this.name}ExtraData` + return `${this.name}ExtraData`; } static getExtraDataKeyByName(name) { - return `${name}ExtraData` + return `${name}ExtraData`; } get isEditedKey() { - return `is${lodash.capitalize(this.name)}Edited` + return `is${lodash.capitalize(this.name)}Edited`; } static getIsEditedKeyByName(name) { - return `is${lodash.capitalize(name)}Edited` + return `is${lodash.capitalize(name)}Edited`; } get isUnitContextProvider() { - return this.entityName === "unit" + return this.entityName === "unit"; } get isSubworkflowContextProvider() { - return this.entityName === "subworkflow" + return this.entityName === "subworkflow"; } - } diff --git a/src/context/registry.js b/src/context/registry.js index 433b95e8..5fa45a5a 100644 --- a/src/context/registry.js +++ b/src/context/registry.js @@ -1,6 +1,5 @@ export class ContextProviderRegistryContainer { - - constructor(config = {}) { + constructor() { this._providers = []; } @@ -12,24 +11,23 @@ export class ContextProviderRegistryContainer { this._providers = p; } - addProvider({name, instance}) { + addProvider({ name, instance }) { this._providers.push({ name, - instance + instance, }); } findProviderInstanceByName(name) { - const p = this.providers.find(p => p.name === name); - return p && p.instance; + const provider = this.providers.find((p) => p.name === name); + return provider && provider.instance; } removeProvider(providerCls) { - this.providers = this.providers.filter(p => p.name === providerCls.name); + this.providers = this.providers.filter((p) => p.name === providerCls.name); } removeProviderByName(name) { - this.providers = this.providers.filter(p => p.name === name); + this.providers = this.providers.filter((p) => p.name === name); } - } diff --git a/src/entity/in_memory.js b/src/entity/in_memory.js index 22293113..fa5366f8 100644 --- a/src/entity/in_memory.js +++ b/src/entity/in_memory.js @@ -1,15 +1,12 @@ import lodash from "lodash"; // import { ESSE } from "@exabyte-io/esse.js"; - import { deepClone } from "../utils/clone"; // TODO: https://exabyte.atlassian.net/browse/SOF-5946 // const schemas = new ESSE().schemas; - export class InMemoryEntity { - static create(config) { return new this.prototype.constructor(config); } @@ -61,12 +58,13 @@ export class InMemoryEntity { * @returns {*} */ clone(extraContext = {}) { - return new this.constructor(Object.assign({}, this.toJSON(), extraContext)); + return new this.constructor({ ...this.toJSON(), ...extraContext }); } // override upon inheritance get schema() { if (this._schema) return this._schema; + return null; } set schema(schema) { @@ -106,18 +104,30 @@ export class InMemoryEntity { return ctx.isValid(); } - get id() {return this.prop('_id', '')} + get id() { + return this.prop("_id", ""); + } - set id(id) {this.setProp('_id', id)} + set id(id) { + this.setProp("_id", id); + } - static get cls() {return this.prototype.constructor.name} + static get cls() { + return this.prototype.constructor.name; + } - get cls() {return this.constructor.name} + get cls() { + return this.constructor.name; + } // TODO: figure out why the above getter for `cls` returns `null` and use only one - getClsName() {return this.constructor.name} + getClsName() { + return this.constructor.name; + } - get slug() {return this.prop('slug')} + get slug() { + return this.prop("slug"); + } get isSystemEntity() { return this.prop("systemName", false); @@ -130,13 +140,13 @@ export class InMemoryEntity { */ getAsEntityReference(byIdOnly = false) { if (byIdOnly) { - return { _id: this.id } + return { _id: this.id }; } return { _id: this.id, slug: this.slug, cls: this.getClsName(), - } + }; } /** @@ -147,18 +157,18 @@ export class InMemoryEntity { * @param name {string} the name of the entity to choose * @returns {*} */ + // eslint-disable-next-line class-methods-use-this getEntityByName(entities, entity, name) { let filtered; if (!name) { - filtered = entities.filter(entity => entity.prop("isDefault") === true); + filtered = entities.filter((ent) => ent.prop("isDefault") === true); if (!filtered.length) filtered = [entities[0]]; } else { - filtered = entities.filter(entity => entity.prop("name") === name); + filtered = entities.filter((ent) => ent.prop("name") === name); } if (filtered.length !== 1) { console.log(`found ${filtered.length} entity ${entity} with name ${name} expected 1`); } return filtered[0]; } - } diff --git a/src/entity/mixins/context.js b/src/entity/mixins/context.js index fac0eeaa..87208fc4 100644 --- a/src/entity/mixins/context.js +++ b/src/entity/mixins/context.js @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { deepClone } from "../../utils/clone"; export const ContextAndRenderFieldsMixin = (superclass) => { @@ -17,8 +18,8 @@ export const ContextAndRenderFieldsMixin = (superclass) => { } updateContext(ctx = {}, executeRender = false) { - this._context = Object.assign({}, this.context, ctx); - executeRender && this.render(); + this._context = { ...this.context, ...ctx }; + if (executeRender) this.render(); } // to get "persistent" context, that is stored in database and further should be provided to constructor @@ -29,15 +30,16 @@ export const ContextAndRenderFieldsMixin = (superclass) => { // to make context persistent in `_json` updatePersistentContext(ctx = {}) { - this.setProp("context", Object.assign({}, ctx)); + this.setProp("context", { ...ctx }); } // to get persistent and volatile context combined getCombinedContext() { - return Object.assign({}, this.getPersistentContext(), this.context); + return { ...this.getPersistentContext(), ...this.context }; } // override in subclasses + // eslint-disable-next-line no-unused-vars render(context = this.context) { throw new Error("RenderInitMixin: render not implemented in derived class"); } @@ -69,14 +71,14 @@ export const ImportantSettingsProviderMixin = (superclass) => { } setImportant(key, value) { - this.setProp("important", {[key]: value}) + this.setProp("important", { [key]: value }); } /** * @return {JSONSchemaFormDataProvider[]} */ get importantSettingsProviders() { - return this.contextProviders.filter(p => p.domain === "important"); + return this.contextProviders.filter((p) => p.domain === "important"); } get isImportantEdited() { @@ -84,7 +86,7 @@ export const ImportantSettingsProviderMixin = (superclass) => { } set isImportantEdited(bool) { - this.setProp("important", Object.assign(this.important, {isEdited: bool})); + this.setProp("important", Object.assign(this.important, { isEdited: bool })); } }; }; diff --git a/src/entity/mixins/context_runtime.js b/src/entity/mixins/context_runtime.js index b83fce18..fb59580a 100644 --- a/src/entity/mixins/context_runtime.js +++ b/src/entity/mixins/context_runtime.js @@ -19,7 +19,7 @@ export const RuntimeContextFieldMixin = (superclass) => { } toJSON() { - return Object.assign({}, super.toJSON(), {runtimeContext: this._runtimeContext}); + return { ...super.toJSON(), runtimeContext: this._runtimeContext }; } }; }; diff --git a/src/entity/mixins/hash.js b/src/entity/mixins/hash.js index 4d83c50b..61104a8c 100644 --- a/src/entity/mixins/hash.js +++ b/src/entity/mixins/hash.js @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { calculateHashFromObject } from "../../utils/hash"; import { removeCommentsFromSourceCode, removeEmptyLinesFromString } from "../../utils/str"; @@ -7,6 +8,7 @@ export const HashedEntityMixin = (superclass) => { * @summary Returns an object based on meaningful fields for this unit, that will be used to calculate the hash * Must be overridden. */ + // eslint-disable-next-line class-methods-use-this getHashObject() { return {}; } @@ -28,10 +30,10 @@ export const HashedInputArrayMixin = (superclass) => { * @summary expects an array with elements containing field [{content: "..."}] */ get hashFromArrayInputContent() { - const objectForHashing = this.input.map(i => - removeEmptyLinesFromString(removeCommentsFromSourceCode(i.content)) + const objectForHashing = this.input.map((i) => + removeEmptyLinesFromString(removeCommentsFromSourceCode(i.content)), ); - return calculateHashFromObject(objectForHashing) + return calculateHashFromObject(objectForHashing); } }; }; diff --git a/src/entity/mixins/props.js b/src/entity/mixins/props.js index 72da5b98..61e492c5 100644 --- a/src/entity/mixins/props.js +++ b/src/entity/mixins/props.js @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ export const DefaultableMixin = (superclass) => { return class extends superclass { get isDefault() { @@ -16,34 +17,54 @@ export const DefaultableMixin = (superclass) => { export const TaggableMixin = (superclass) => { return class extends superclass { - get tags() {return this.prop("tags", [])} + get tags() { + return this.prop("tags", []); + } - set tags(array) {this.setProp("tags", array)} + set tags(array) { + this.setProp("tags", array); + } // only keep unique elements in tags - setTags(array) {this.tags = array.filter((value, index, self) => self.indexOf(value) === index)} + setTags(array) { + this.tags = array.filter((value, index, self) => self.indexOf(value) === index); + } }; }; export const HasMetadataMixin = (superclass) => { return class extends superclass { - get metadata() {return this.prop("metadata", {})} + get metadata() { + return this.prop("metadata", {}); + } - set metadata(object) {this.setProp("metadata", object)} + set metadata(object) { + this.setProp("metadata", object); + } - updateMetadata(object) {this.metadata = Object.assign({}, this.metadata, object)} + updateMetadata(object) { + this.metadata = { ...this.metadata, ...object }; + } }; }; export const HasDescriptionMixin = (superclass) => { return class extends superclass { - get description() {return this.prop("description", "")} + get description() { + return this.prop("description", ""); + } - set description(string) {this.setProp("description", string)} + set description(string) { + this.setProp("description", string); + } - get descriptionObject() {return this.prop("descriptionObject")} + get descriptionObject() { + return this.prop("descriptionObject"); + } - set descriptionObject(obj) {this.setProp("descriptionObject", obj)} + set descriptionObject(obj) { + this.setProp("descriptionObject", obj); + } }; }; diff --git a/src/entity/mixins/repetition.js b/src/entity/mixins/repetition.js index 759063ae..18aab453 100644 --- a/src/entity/mixins/repetition.js +++ b/src/entity/mixins/repetition.js @@ -1,24 +1,24 @@ export const HasRepetitionMixin = (superclass) => { return class extends superclass { get repetition() { - return this._repetition || 0 + return this._repetition || 0; } setRepetition(repetition) { this._repetition = repetition; - if (["Subworkflow", "Workflow"].find(n => this.constructor.name === n)) { - this.units.forEach(u => u.setRepetition(repetition)); + if (["Subworkflow", "Workflow"].find((n) => this.constructor.name === n)) { + this.units.forEach((u) => u.setRepetition(repetition)); } if (this.constructor.name === "Workflow") { - this.subworkflows.forEach(sw => sw.setRepetition(repetition)); - this.workflows.forEach(wf => wf.setRepetition(repetition)); + this.subworkflows.forEach((sw) => sw.setRepetition(repetition)); + this.workflows.forEach((wf) => wf.setRepetition(repetition)); } } get totalRepetitions() { - return this._totalRepetitions || 1 + return this._totalRepetitions || 1; } setTotalRepetitions(totalRepetition) { diff --git a/src/entity/mixins/runtime_items.js b/src/entity/mixins/runtime_items.js index d90d8bb4..53f14712 100644 --- a/src/entity/mixins/runtime_items.js +++ b/src/entity/mixins/runtime_items.js @@ -1,4 +1,4 @@ -import _ from "underscore"; +/* eslint-disable max-classes-per-file, class-methods-use-this */ import s from "underscore.string"; import { safeMakeObject } from "../../utils/object"; @@ -10,7 +10,6 @@ import { safeMakeObject } from "../../utils/object"; export const RuntimeItemsMixin = (superclass) => { return class extends superclass { - get results() { return this.prop("results", this.defaultResults).map(safeMakeObject); } @@ -27,13 +26,21 @@ export const RuntimeItemsMixin = (superclass) => { return this.prop("postProcessors", this.defaultPostProcessors).map(safeMakeObject); } - get defaultResults() {return []} + get defaultResults() { + return []; + } - get defaultMonitors() {return []} + get defaultMonitors() { + return []; + } - get defaultPreProcessors() {return []} + get defaultPreProcessors() { + return []; + } - get defaultPostProcessors() {return []} + get defaultPostProcessors() { + return []; + } get hashObjectFromRuntimeItems() { return { @@ -67,29 +74,38 @@ export const RuntimeItemsUILogicMixin = (superclass) => { * @param config * @private */ + // eslint-disable-next-line no-unused-vars _initRuntimeItems(keys, config) { // keeping this separate from constructor so that it can be overridden in mixing (eg. in `ExecutionUnit`) const me = this; keys.map((key) => { if (!me._json[key]) me._json[key] = me[`default${s.capitalize(key)}`]; + return null; }); } + // eslint-disable-next-line default-param-last _addRuntimeItem(key = "results", config) { this._json[key].push(safeMakeObject(config)); } + // eslint-disable-next-line default-param-last _removeRuntimeItem(key = "results", config) { - config = safeMakeObject(config); - this._removeRuntimeItemByName(key, config.name); + const newConfig = safeMakeObject(config); + this._removeRuntimeItemByName(key, newConfig.name); } _removeRuntimeItemByName(key, name) { - this._json[key] = this._json[key].filter(x => x.name !== name); + this._json[key] = this._json[key].filter((x) => x.name !== name); } + // eslint-disable-next-line default-param-last _toggleRuntimeItem(key = "results", data, isAdding) { - isAdding ? this._addRuntimeItem(key, data) : this._removeRuntimeItem(key, data); + if (isAdding) { + this._addRuntimeItem(key, data); + } else { + this._removeRuntimeItem(key, data); + } } toggleResult(data, isAdding) { @@ -109,25 +125,25 @@ export const RuntimeItemsUILogicMixin = (superclass) => { } get resultNames() { - return this.results.map(r => { - return r && r.name - }) + return this.results.map((r) => { + return r && r.name; + }); } get monitorNames() { - return this.monitors.map(r => r.name) + return this.monitors.map((r) => r.name); } get postProcessorNames() { - return this.postProcessors.map(r => r.name) + return this.postProcessors.map((r) => r.name); } get preProcessorNames() { - return this.preProcessors.map(r => r.name) + return this.preProcessors.map((r) => r.name); } getResultByName(name) { - return this.results.find(r => r.name === name); + return this.results.find((r) => r.name === name); } }; }; diff --git a/src/entity/other.js b/src/entity/other.js index c516205b..c0646e76 100644 --- a/src/entity/other.js +++ b/src/entity/other.js @@ -1,10 +1,12 @@ +/* eslint-disable max-classes-per-file */ import { mix } from "mixwith"; + import { InMemoryEntity } from "./in_memory"; -import { DefaultableMixin, HasMetadataMixin, NamedEntityMixin } from "./mixins/props"; import { ContextAndRenderFieldsMixin, ImportantSettingsProviderMixin } from "./mixins/context"; import { HashedEntityMixin } from "./mixins/hash"; +import { DefaultableMixin, HasMetadataMixin, NamedEntityMixin } from "./mixins/props"; import { HasRepetitionMixin } from "./mixins/repetition"; -import { RuntimeItemsUILogicMixin, RuntimeItemsUIAllowedMixin } from "./mixins/runtime_items"; +import { RuntimeItemsUIAllowedMixin, RuntimeItemsUILogicMixin } from "./mixins/runtime_items"; export class DefaultableInMemoryEntity extends mix(InMemoryEntity).with(DefaultableMixin) {} @@ -23,21 +25,11 @@ export class HasMetadataNamedDefaultableInMemoryEntity extends mix(InMemoryEntit export class NamedDefaultableRepetitionImportantSettingsInMemoryEntity extends mix( InMemoryEntity, -).with( - DefaultableMixin, - NamedEntityMixin, - HasRepetitionMixin, - ImportantSettingsProviderMixin, -) {} +).with(DefaultableMixin, NamedEntityMixin, HasRepetitionMixin, ImportantSettingsProviderMixin) {} export class NamedDefaultableRepetitionContextAndRenderInMemoryEntity extends mix( InMemoryEntity, -).with( - DefaultableMixin, - NamedEntityMixin, - HasRepetitionMixin, - ContextAndRenderFieldsMixin, -) {} +).with(DefaultableMixin, NamedEntityMixin, HasRepetitionMixin, ContextAndRenderFieldsMixin) {} export class NamedDefaultableRepetitionRuntimeItemsImportantSettingsContextAndRenderHashedInMemoryEntity extends mix( InMemoryEntity, diff --git a/src/entity/set.js b/src/entity/set.js index 3ddb98b7..da5219a6 100644 --- a/src/entity/set.js +++ b/src/entity/set.js @@ -1,26 +1,30 @@ +import { mix } from "mixwith"; import _ from "underscore"; -import {mix} from "mixwith"; import { InMemoryEntity } from "./in_memory"; -import {InMemoryEntitySetMixin, InMemoryEntityInSetMixin } from "./set/mixins"; +import { InMemoryEntityInSetMixin, InMemoryEntitySetMixin } from "./set/mixins"; export class InMemoryEntitySet extends mix(InMemoryEntity).with( InMemoryEntitySetMixin, InMemoryEntityInSetMixin, - ) { + get isEntitySet() { + return this.prop("isEntitySet"); + } - get isEntitySet() {return this.prop('isEntitySet')} - - get entitySetType() {return this.prop('entitySetType')} + get entitySetType() { + return this.prop("entitySetType"); + } - get entityCls() {return this.prop('entityCls')} + get entityCls() { + return this.prop("entityCls"); + } - get cls() {return this.entityCls || super.cls} + get cls() { + return this.entityCls || super.cls; + } toJSONForInclusionInEntity() { - return _.pick(this.toJSON(), ['_id', 'type']); - + return _.pick(this.toJSON(), ["_id", "type"]); } - } diff --git a/src/entity/set/factory.js b/src/entity/set/factory.js index e4db49bd..02dbe928 100644 --- a/src/entity/set/factory.js +++ b/src/entity/set/factory.js @@ -1,16 +1,14 @@ -import { ENTITY_SET_TYPES } from "./enums"; import { InMemoryEntitySet } from "../set"; +import { ENTITY_SET_TYPES } from "./enums"; import { OrderedInMemoryEntitySet } from "./ordered"; -export const constructEntitySetFactoryByConfig = ( - { - entitySetCls = InMemoryEntitySet, - orderedEntitySetCls = OrderedInMemoryEntitySet, - } -) => (config, entityCls) => { - const cls = config.entitySetType === ENTITY_SET_TYPES.ordered ? orderedEntitySetCls : entitySetCls; - return new cls({ - ...config, - entityCls: entityCls, - }); -}; +export const constructEntitySetFactoryByConfig = + ({ entitySetCls = InMemoryEntitySet, orderedEntitySetCls = OrderedInMemoryEntitySet }) => + (config, entityCls) => { + const Cls = + config.entitySetType === ENTITY_SET_TYPES.ordered ? orderedEntitySetCls : entitySetCls; + return new Cls({ + ...config, + entityCls, + }); + }; diff --git a/src/entity/set/mixins.js b/src/entity/set/mixins.js index 5280b36e..8f1e21c0 100644 --- a/src/entity/set/mixins.js +++ b/src/entity/set/mixins.js @@ -1,19 +1,28 @@ -export const InMemoryEntitySetMixin = (superclass) => class extends superclass { - - containsEntity(entity) {return entity.inSet.some(ref => ref._id === this.id)} - -}; - -export const InMemoryEntityInSetMixin = (superclass) => class extends superclass { - - get inSet() {return this.prop('inSet', [])} - - set inSet(inSet) {this.setProp('inSet', inSet)} - - getInSetFilteredByCls(cls) {return this.inSet.filter(ref => ref.cls === cls)} - - // finds a parent entity set of the same cls (hence `cls` field is absent) - // NOTE: assumes that only one entry of this kind is present => gets the first one - get parentEntitySetReference() {return this.inSet.find(item => item._id && !item.cls)} - -}; +/* eslint-disable max-classes-per-file */ +export const InMemoryEntitySetMixin = (superclass) => + class extends superclass { + containsEntity(entity) { + return entity.inSet.some((ref) => ref._id === this.id); + } + }; + +export const InMemoryEntityInSetMixin = (superclass) => + class extends superclass { + get inSet() { + return this.prop("inSet", []); + } + + set inSet(inSet) { + this.setProp("inSet", inSet); + } + + getInSetFilteredByCls(cls) { + return this.inSet.filter((ref) => ref.cls === cls); + } + + // finds a parent entity set of the same cls (hence `cls` field is absent) + // NOTE: assumes that only one entry of this kind is present => gets the first one + get parentEntitySetReference() { + return this.inSet.find((item) => item._id && !item.cls); + } + }; diff --git a/src/entity/set/ordered.js b/src/entity/set/ordered.js index 56614ff8..42b6675f 100644 --- a/src/entity/set/ordered.js +++ b/src/entity/set/ordered.js @@ -1,6 +1,9 @@ import { mix } from "mixwith"; + import { InMemoryEntitySet } from "../set"; -import { OrderedInMemoryEntitySetMixin, OrderedInMemoryEntityInSetMixin } from "./ordered/mixins"; +import { OrderedInMemoryEntityInSetMixin, OrderedInMemoryEntitySetMixin } from "./ordered/mixins"; -export class OrderedInMemoryEntitySet extends mix(InMemoryEntitySet).with(OrderedInMemoryEntitySetMixin, OrderedInMemoryEntityInSetMixin) { -} +export class OrderedInMemoryEntitySet extends mix(InMemoryEntitySet).with( + OrderedInMemoryEntitySetMixin, + OrderedInMemoryEntityInSetMixin, +) {} diff --git a/src/entity/set/ordered/mixins.js b/src/entity/set/ordered/mixins.js index 7b6c5e33..a2ba3ee5 100644 --- a/src/entity/set/ordered/mixins.js +++ b/src/entity/set/ordered/mixins.js @@ -1,18 +1,19 @@ +/* eslint-disable max-classes-per-file */ import { ENTITY_SET_TYPES } from "../enums"; // NOTE: these mixins are meant to be used together with `InMemoryEntity{In}SetMixin`s only -export const OrderedInMemoryEntitySetMixin = (superclass) => class extends superclass { +export const OrderedInMemoryEntitySetMixin = (superclass) => + class extends superclass { + get isOrderedSet() { + return this.entitySetType === ENTITY_SET_TYPES.ordered; + } + }; - get isOrderedSet() {return this.entitySetType === ENTITY_SET_TYPES.ordered} - -}; - -export const OrderedInMemoryEntityInSetMixin = (superclass) => class extends superclass { - - getIndexByIdInOrderedSet(setId) { - const setData = this.inSet.find(s => s._id === setId); - return setData ? setData.index : 0; - } - -}; +export const OrderedInMemoryEntityInSetMixin = (superclass) => + class extends superclass { + getIndexByIdInOrderedSet(setId) { + const setData = this.inSet.find((s) => s._id === setId); + return setData ? setData.index : 0; + } + }; diff --git a/src/entity/set/ordered/utils.js b/src/entity/set/ordered/utils.js index 48974ffd..479e922b 100644 --- a/src/entity/set/ordered/utils.js +++ b/src/entity/set/ordered/utils.js @@ -3,7 +3,17 @@ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort for more info. */ export const compareEntitiesInOrderedSetForSorting = (a, b, setId, descending = true) => { - const aIndex = a ? a.getIndexByIdInOrderedSet(setId) : descending ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; - const bIndex = b ? b.getIndexByIdInOrderedSet(setId) : descending ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; - return descending ? (bIndex - aIndex) : (aIndex - bIndex); + // eslint-disable-next-line no-nested-ternary + const aIndex = a + ? a.getIndexByIdInOrderedSet(setId) + : descending + ? Number.POSITIVE_INFINITY + : Number.NEGATIVE_INFINITY; + // eslint-disable-next-line no-nested-ternary + const bIndex = b + ? b.getIndexByIdInOrderedSet(setId) + : descending + ? Number.POSITIVE_INFINITY + : Number.NEGATIVE_INFINITY; + return descending ? bIndex - aIndex : aIndex - bIndex; }; diff --git a/src/entity/set/selectors.js b/src/entity/set/selectors.js index 95d17be3..28ed8dfc 100644 --- a/src/entity/set/selectors.js +++ b/src/entity/set/selectors.js @@ -1,36 +1,38 @@ import { safeMakeArray } from "../../utils"; -const getInSetEntrySelectorBuilder = function (config) { +const getInSetEntrySelectorBuilder = (config) => { return { inSet: { - $elemMatch: config - } - } + $elemMatch: config, + }, + }; }; -const getInSetEntrySelectorByIdsCls = function (ids, cls = 'Team') { - ids = safeMakeArray(ids); +const getInSetEntrySelectorByIdsCls = (ids, cls = "Team") => { + const newIds = safeMakeArray(ids); const config = { - _id: {$in: ids}, - ...cls ? {cls} : {}, + _id: { $in: newIds }, + ...(cls ? { cls } : {}), }; return getInSetEntrySelectorBuilder(config); }; const getInSetEntrySelectorByIds = (ids) => getInSetEntrySelectorByIdsCls(ids, null); -const getInSetEntrySelector = function (cls, _id) { +const getInSetEntrySelector = (cls, _id) => { return { inSet: { $elemMatch: { - ...cls ? {cls} : {}, - ..._id ? {_id} : {}, - } - } - } + ...(cls ? { cls } : {}), + ...(_id ? { _id } : {}), + }, + }, + }; }; -const getInSetEntryWithoutClsOnly = {inSet: {$not: {$elemMatch: {cls: {$exists: false}}}}}; +const getInSetEntryWithoutClsOnly = { + inSet: { $not: { $elemMatch: { cls: { $exists: false } } } }, +}; export { getInSetEntrySelectorByIdsCls, @@ -38,4 +40,4 @@ export { getInSetEntrySelectorByIds, getInSetEntrySelectorBuilder, getInSetEntrySelector, -} +}; diff --git a/src/index.js b/src/index.js index a31b3f06..c27c9098 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,5 @@ -import * as entity from "./entity"; - import * as context from "./context"; - +import * as entity from "./entity"; import * as utils from "./utils"; export const Code = { diff --git a/src/math.js b/src/math.js index 2b853a43..322ab21f 100644 --- a/src/math.js +++ b/src/math.js @@ -1,5 +1,6 @@ -import _ from "underscore"; +/* eslint-disable */ import mathjs from "mathjs"; +import _ from "underscore"; import { tolerance as TOLERANCE } from "./constants"; @@ -187,8 +188,8 @@ const combinationsFromIntervals = (arrA, arrB, arrC) => { }; const roundValueToNDecimals = (value, decimals = 3) => { - return parseFloat(value.toFixed(decimals)); -} + return parseFloat(value.toFixed(decimals)); +}; /** * @summary Returns n splits of the passed segment. @@ -198,9 +199,9 @@ const roundValueToNDecimals = (value, decimals = 3) => { */ const calculateSegmentsBetweenPoints3D = (point1, point2, n) => { // 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) => parseFloat(x)); + const point2_ = point2.map((x) => parseFloat(x)); + const n_ = parseInt(n); const result = []; for (let i = 1; i < n_; i++) { @@ -208,11 +209,11 @@ const calculateSegmentsBetweenPoints3D = (point1, point2, n) => { result.push([ (point1_[0] + lambda * point2_[0]) / (1 + lambda), (point1_[1] + lambda * point2_[1]) / (1 + lambda), - (point1_[2] + lambda * point2_[2]) / (1 + lambda) + (point1_[2] + lambda * point2_[2]) / (1 + lambda), ]); } return result; -} +}; /** * @summary Wrapper for native [Number.toPrecision](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Number/toPrecision) method. @@ -226,7 +227,6 @@ const calculateSegmentsBetweenPoints3D = (point1, point2, n) => { * @param {Number} precision Optional. An integer specifying the number of significant digits. */ export function numberToPrecision(number, precision) { - if (_.isNumber(number)) { return number.toPrecision(precision); } diff --git a/src/utils/array.js b/src/utils/array.js index 5a57e7a4..815c0b4a 100644 --- a/src/utils/array.js +++ b/src/utils/array.js @@ -1,5 +1,5 @@ -import _ from 'underscore'; import lodash from "lodash"; +import _ from "underscore"; export function safeMakeArray(x) { if (!lodash.isArray(x)) return [x]; @@ -12,11 +12,12 @@ export function safeMakeArray(x) { * @param objects */ export function convertToCompactCSVArrayOfObjects(objects) { - const headers = _.uniq(_.flatten(objects.map(x => _.keys(x)))); + const headers = _.uniq(_.flatten(objects.map((x) => _.keys(x)))); const result = [headers]; - objects.forEach(x => { + objects.forEach((x) => { const row = []; - headers.forEach(header => { + headers.forEach((header) => { + // eslint-disable-next-line no-prototype-builtins row.push(x.hasOwnProperty(header) ? x[header] : null); }); result.push(row); diff --git a/src/utils/class.js b/src/utils/class.js index ca1072d9..6dc7ebc1 100644 --- a/src/utils/class.js +++ b/src/utils/class.js @@ -1,5 +1,5 @@ export function cloneClass(classToClone) { - return Object.assign(Object.create(Object.getPrototypeOf(classToClone)), classToClone) + return Object.assign(Object.create(Object.getPrototypeOf(classToClone)), classToClone); } /** @@ -14,26 +14,32 @@ export function cloneClass(classToClone) { */ export function extendClass(childClass, parentClass, excludedProps = [], ...args) { const parentNonStaticProps = Object.getOwnPropertyNames(parentClass.prototype); - parentNonStaticProps.filter(p => !excludedProps.includes(p)).forEach(prop => { - if (prop === 'constructor') { - Object.assign(childClass.prototype, new parentClass.prototype.constructor(...args)); - } else { - const getter = parentClass.prototype.__lookupGetter__(prop); - const setter = parentClass.prototype.__lookupSetter__(prop); - if (getter) childClass.prototype.__defineGetter__(prop, getter); - if (setter) childClass.prototype.__defineSetter__(prop, setter); - if (!(getter || setter)) childClass.prototype[prop] = parentClass.prototype[prop]; - } - }); + parentNonStaticProps + .filter((p) => !excludedProps.includes(p)) + .forEach((prop) => { + if (prop === "constructor") { + Object.assign(childClass.prototype, new parentClass.prototype.constructor(...args)); + } else { + const get = parentClass.prototype.__lookupGetter__(prop); + const set = parentClass.prototype.__lookupSetter__(prop); + if (get || set) { + Object.defineProperty(childClass.prototype, prop, { get, set }); + } else { + childClass.prototype[prop] = parentClass.prototype[prop]; + } + } + }); } -export function extendClassStaticProps(childClass, parentClass, excludedProps = [], ...args) { - const parentStaticProps = Object.getOwnPropertyNames(parentClass).filter(p => ![ - "length", "name", "prototype" - ].includes(p)); - parentStaticProps.filter(p => !excludedProps.includes(p)).forEach(prop => { - childClass[prop] = parentClass[prop] - }); +export function extendClassStaticProps(childClass, parentClass, excludedProps = []) { + const parentStaticProps = Object.getOwnPropertyNames(parentClass).filter( + (p) => !["length", "name", "prototype"].includes(p), + ); + parentStaticProps + .filter((p) => !excludedProps.includes(p)) + .forEach((prop) => { + childClass[prop] = parentClass[prop]; + }); } /** @@ -50,15 +56,21 @@ export function extendThis(childClass, parentClass, config) { while (Object.getPrototypeOf(obj)) { protos = Object.getPrototypeOf(obj); props = Object.getOwnPropertyNames(protos); - props.filter(p => !exclude.includes(p)).map((prop) => { - if (seen.includes(prop)) return; - const getter = protos.__lookupGetter__(prop); - const setter = protos.__lookupSetter__(prop); - if (getter) childClass.prototype.__defineGetter__(prop, getter); - if (setter) childClass.prototype.__defineSetter__(prop, setter); - if (!(getter || setter)) childClass.prototype[prop] = protos[prop]; - seen.push(prop); - }) + props + .filter((p) => !exclude.includes(p)) + // eslint-disable-next-line no-loop-func + .map((prop) => { + if (seen.includes(prop)) return; + const get = protos.__lookupGetter__(prop); + const set = protos.__lookupSetter__(prop); + if (get || set) { + Object.defineProperty(childClass.prototype, prop, { get, set }); + } else { + childClass.prototype[prop] = parentClass.prototype[prop]; + } + seen.push(prop); // don't override with older definition in hierarchy + return null; + }); obj = protos; } } diff --git a/src/utils/codemirror.js b/src/utils/codemirror.js index 52c03695..face68c1 100644 --- a/src/utils/codemirror.js +++ b/src/utils/codemirror.js @@ -1,7 +1,7 @@ -import lodash from 'lodash'; +import lodash from "lodash"; -export const refreshCodeMirror = function (containerId) { +export const refreshCodeMirror = (containerId) => { const container = document.getElementById(containerId); - const editors = container.getElementsByClassName('CodeMirror'); - lodash.each(editors, cm => cm.CodeMirror.refresh()); + const editors = container.getElementsByClassName("CodeMirror"); + lodash.each(editors, (cm) => cm.CodeMirror.refresh()); }; diff --git a/src/utils/file.js b/src/utils/file.js index 557452e4..d560ed2c 100644 --- a/src/utils/file.js +++ b/src/utils/file.js @@ -1,10 +1,10 @@ const FILE_EXTENSION_TO_PROGRAMMING_LANGUAGE_MAP = { - "in": "fortran", - "sh": "shell", - "bash": "shell", - "zsh": "shell", - "pbs": "shell", - "py": "python" + in: "fortran", + sh: "shell", + bash: "shell", + zsh: "shell", + pbs: "shell", + py: "python", }; /** @@ -12,8 +12,8 @@ const FILE_EXTENSION_TO_PROGRAMMING_LANGUAGE_MAP = { * @param filename {String} * @param defaultLanguage {String} */ -export function getProgrammingLanguageFromFileExtension(filename, defaultLanguage = 'fortran') { - const fileExt = filename.split('.').pop().toLowerCase(); +export function getProgrammingLanguageFromFileExtension(filename, defaultLanguage = "fortran") { + const fileExt = filename.split(".").pop().toLowerCase(); return FILE_EXTENSION_TO_PROGRAMMING_LANGUAGE_MAP[fileExt] || defaultLanguage; } @@ -25,16 +25,6 @@ export function getProgrammingLanguageFromFileExtension(filename, defaultLanguag export function formatFileSize(size, decimals = 2) { if (size === 0) return "0 Bytes"; const index = Math.floor(Math.log(size) / Math.log(1024)); - const units = [ - "Bytes", - "KB", - "MB", - "GB", - "TB", - "PB", - "EB", - "ZB", - "YB" - ]; - return parseFloat((size / Math.pow(1024, index)).toFixed(decimals)) + " " + units[index] + const units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + return parseFloat((size / 1024 ** index).toFixed(decimals)) + " " + units[index]; } diff --git a/src/utils/hash.js b/src/utils/hash.js index 81517b5e..ba0281dc 100644 --- a/src/utils/hash.js +++ b/src/utils/hash.js @@ -1,5 +1,6 @@ -import _ from "underscore"; import CryptoJS from "crypto-js"; +import _ from "underscore"; + import { sortKeysDeepForObject } from "./object"; /** diff --git a/src/utils/index.js b/src/utils/index.js index 32df15cd..473e5083 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,45 +1,43 @@ import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; -import { safeMakeArray, convertToCompactCSVArrayOfObjects } from "./array"; -import { extendThis, extendClass, extendClassStaticProps, cloneClass } from "./class"; +import { convertToCompactCSVArrayOfObjects, safeMakeArray } from "./array"; +import { cloneClass, extendClass, extendClassStaticProps, extendThis } from "./class"; import { deepClone } from "./clone"; import { refreshCodeMirror } from "./codemirror"; -import { getProgrammingLanguageFromFileExtension, formatFileSize } from "./file"; -import { calculateHashFromObject, calculateHashFromString, removeTimestampableKeysFromConfig } from "./hash"; +import { formatFileSize, getProgrammingLanguageFromFileExtension } from "./file"; +import { + calculateHashFromObject, + calculateHashFromString, + removeTimestampableKeysFromConfig, +} from "./hash"; import { - getOneMatchFromObject, - safeMakeObject, convertKeysToCamelCaseForObject, flattenObject, + getOneMatchFromObject, renameKeysForObject, + safeMakeObject, sortKeysDeepForObject, stringifyObject, } from "./object"; -import { getUUID } from "./uuid"; +import { getSearchQuerySelector } from "./selector"; import { - removeNewLinesAndExtraSpaces, randomAlphanumeric, - removeEmptyLinesFromString, removeCommentsFromSourceCode, + removeEmptyLinesFromString, + removeNewLinesAndExtraSpaces, toFixedLocale, } from "./str"; - -import { getSearchQuerySelector } from "./selector"; +import { getUUID } from "./uuid"; export { compareEntitiesInOrderedSetForSorting, - safeMakeArray, convertToCompactCSVArrayOfObjects, - cloneClass, extendThis, extendClass, extendClassStaticProps, - deepClone, - refreshCodeMirror, - getOneMatchFromObject, safeMakeObject, convertKeysToCamelCaseForObject, @@ -47,21 +45,16 @@ export { renameKeysForObject, sortKeysDeepForObject, stringifyObject, - getProgrammingLanguageFromFileExtension, formatFileSize, - calculateHashFromObject, calculateHashFromString, removeTimestampableKeysFromConfig, - removeNewLinesAndExtraSpaces, randomAlphanumeric, removeEmptyLinesFromString, removeCommentsFromSourceCode, toFixedLocale, - getUUID, - getSearchQuerySelector, }; diff --git a/src/utils/object.js b/src/utils/object.js index 9ab9c54f..5cf2bcde 100644 --- a/src/utils/object.js +++ b/src/utils/object.js @@ -1,5 +1,5 @@ -import _ from 'underscore'; import lodash from "lodash"; +import _ from "underscore"; import { deepClone } from "./clone"; @@ -40,10 +40,10 @@ export function getOneMatchFromObject(obj, attribute, value) { * @param obj {Object} */ export function convertKeysToCamelCaseForObject(obj) { - obj = deepClone(obj); - return lodash.mapKeys(obj, function (v, k) { + const newObj = deepClone(obj); + return lodash.mapKeys(newObj, (v, k) => { return lodash.camelCase(k); - }) + }); } /* @@ -53,113 +53,111 @@ export function convertKeysToCamelCaseForObject(obj) { * @param {Array} keysRenamed - List of keys to rename original keys to, in the same order */ export function renameKeysForObject(o, keysOriginal = [], keysRenamed = []) { - if (!lodash.isObject(o)) { return o; } if (lodash.isArray(o)) { - return o.map(x => renameKeysForObject(x, keysOriginal, keysRenamed)); + return o.map((x) => renameKeysForObject(x, keysOriginal, keysRenamed)); } - let result = {}, origKey, destKey, idx, value; + const result = {}; - for (origKey in o) { + Object.entries(o).map(([origKey, origValue]) => { // Get the destination key - idx = keysOriginal.indexOf(origKey); - if (idx === -1) { - destKey = origKey; - } else { - destKey = keysRenamed[idx]; - } - // Get the value - value = o[origKey]; - // If this is an object, recurse - if (typeof value === 'object') { - value = renameKeysForObject(value, keysOriginal, keysRenamed); - } - // Set it on the result using the destination key - result[destKey] = value; - } + const idx = keysOriginal.indexOf(origKey); + const destKey = idx === -1 ? origKey : keysRenamed[idx]; + const destValue = + typeof origValue === "object" + ? renameKeysForObject(origValue, keysOriginal, keysRenamed) + : origValue; + result[destKey] = destValue; + return null; + }); return result; } /** - * @summary Flattens complex object into object with single key-value pair. Required properties for object: "name", "value". - * "units" property is ignored. Only one extra property is allowed. E.g. - * {name: 'propName', value: 1} -> {propName: 1} - * {name: "propName", value: 1, extraProp: {name: "extraPropName", value: "2"}} -> {"propName:extraPropName=2": 1} + * @summary Converts object into string. Recursive. Required properties for object: "name", "value". + * "units" property is ignored. Only one extra property is allowed. Function is called recursively on extraProperty. + * E.g. {name: "propName", value: 1} -> 'propName=1' + * {name: "propName", value: 1, extraProp: {name: "extraPropName", value: "2"}} -> "propName=1:extraPropName=2" * @param {Object} obj Object to stringify. * @param {String} [levelSeparator] ':' by default. * @param {String} [keyValueSeparator] '=' by default. - * @param {String} [suffix] - * @return {Object} + * @param {String} [prefix] Empty by default. + * @return {String} */ -export function flattenObject(obj, levelSeparator = ':', keyValueSeparator = '=', suffix) { - const requiredKeys = ['name', 'value']; - const allowedKeys = requiredKeys.concat(['units']); +export function stringifyObject(obj, levelSeparator = ":", keyValueSeparator = "=", prefix = "") { + const requiredKeys = ["name", "value"]; + const allowedKeys = requiredKeys.concat(["units"]); const extraKeys = _.keys(_.omit(obj, allowedKeys)); // If there is more than one extra key, raise an exception if (extraKeys.length > 1) { - throw new Error('flattenObject: more than one extra property') + throw new Error("stringifyObject: more than one extra property"); } - const tailSuffix = _.isEmpty(suffix) ? '' : `${levelSeparator}${suffix}`; - if (extraKeys.length === 0) { - return {[`${obj.name}${tailSuffix}`]: obj.value}; + return `${obj.name}${keyValueSeparator}${obj.value}`; } const extraPropertyKey = extraKeys[0]; const extraPropertyValue = obj[extraKeys[0]]; + // eslint-disable-next-line no-param-reassign + prefix = _.isEmpty(prefix) + ? `${obj.name}${keyValueSeparator}${obj.value}` + : `${prefix}${levelSeparator}${obj.name}${keyValueSeparator}${obj.value}`; + if (!_.isObject(extraPropertyValue)) { - return { - [`${obj.name}${levelSeparator}${extraPropertyKey}=${extraPropertyValue}${tailSuffix}`]: obj.value - }; + return `${prefix}:${extraPropertyKey}${keyValueSeparator}${extraPropertyValue}`; } - const flatSubObj = stringifyObject(extraPropertyValue, levelSeparator, keyValueSeparator); - const key = `${obj.name}${levelSeparator}${flatSubObj}${tailSuffix}`; - return {[key]: obj.value}; + return stringifyObject(extraPropertyValue, levelSeparator, keyValueSeparator, prefix); } /** - * @summary Converts object into string. Recursive. Required properties for object: "name", "value". - * "units" property is ignored. Only one extra property is allowed. Function is called recursively on extraProperty. - * E.g. {name: "propName", value: 1} -> 'propName=1' - * {name: "propName", value: 1, extraProp: {name: "extraPropName", value: "2"}} -> "propName=1:extraPropName=2" + * @summary Flattens complex object into object with single key-value pair. Required properties for object: "name", "value". + * "units" property is ignored. Only one extra property is allowed. E.g. + * {name: 'propName', value: 1} -> {propName: 1} + * {name: "propName", value: 1, extraProp: {name: "extraPropName", value: "2"}} -> {"propName:extraPropName=2": 1} * @param {Object} obj Object to stringify. * @param {String} [levelSeparator] ':' by default. * @param {String} [keyValueSeparator] '=' by default. - * @param {String} [prefix] Empty by default. - * @return {String} + * @param {String} [suffix] + * @return {Object} */ -export function stringifyObject(obj, levelSeparator = ':', keyValueSeparator = '=', prefix = '') { - const requiredKeys = ['name', 'value']; - const allowedKeys = requiredKeys.concat(['units']); +// eslint-disable-next-line default-param-last +export function flattenObject(obj, levelSeparator = ":", keyValueSeparator = "=", suffix) { + const requiredKeys = ["name", "value"]; + const allowedKeys = requiredKeys.concat(["units"]); const extraKeys = _.keys(_.omit(obj, allowedKeys)); // If there is more than one extra key, raise an exception if (extraKeys.length > 1) { - throw new Error('stringifyObject: more than one extra property') + throw new Error("flattenObject: more than one extra property"); } + const tailSuffix = _.isEmpty(suffix) ? "" : `${levelSeparator}${suffix}`; + if (extraKeys.length === 0) { - return `${obj.name}${keyValueSeparator}${obj.value}`; + return { [`${obj.name}${tailSuffix}`]: obj.value }; } const extraPropertyKey = extraKeys[0]; const extraPropertyValue = obj[extraKeys[0]]; - prefix = _.isEmpty(prefix) ? `${obj.name}${keyValueSeparator}${obj.value}` : `${prefix}${levelSeparator}${obj.name}${keyValueSeparator}${obj.value}`; - if (!_.isObject(extraPropertyValue)) { - return `${prefix}:${extraPropertyKey}${keyValueSeparator}${extraPropertyValue}`; + return { + [`${obj.name}${levelSeparator}${extraPropertyKey}=${extraPropertyValue}${tailSuffix}`]: + obj.value, + }; } - return stringifyObject(extraPropertyValue, levelSeparator, keyValueSeparator, prefix); + const flatSubObj = stringifyObject(extraPropertyValue, levelSeparator, keyValueSeparator); + const key = `${obj.name}${levelSeparator}${flatSubObj}${tailSuffix}`; + return { [key]: obj.value }; } /** @@ -171,8 +169,10 @@ export function sortKeysDeepForObject(obj) { } if (_.isObject(obj)) { const sortedObject = {}; - _.keys(obj).sort().map(key => sortedObject[key] = sortKeysDeepForObject(obj[key])); - return sortedObject + _.keys(obj) + .sort() + .map((key) => (sortedObject[key] = sortKeysDeepForObject(obj[key]))); + return sortedObject; } return obj; } diff --git a/src/utils/object.tests.js b/src/utils/object.tests.js deleted file mode 100644 index 5e4afd36..00000000 --- a/src/utils/object.tests.js +++ /dev/null @@ -1,50 +0,0 @@ -import { expect } from "chai"; -import { flattenObject } from "./object"; - -describe("flattenObject", function() { - it("serializes simple object", function() { - - const obj = { - "value": 1.0, - "name": "p-norm", - "degree": 2, - }; - - const expectedObj = { "p-norm:degree=2": 1 }; - expect(expectedObj).to.deep.equal(flattenObject(obj)); - - }); - - it("serialize complex object", function() { - const obj = { - "value": 1.0, - "name": "p-norm", - "extraProp": { - "name": "zeta", - "value": 6, - "extraProp": { - "name": "alpha", - "value": 3, - "veracity": 7, - }, - }, - }; - - const expectedObj = { "p-norm:zeta=6:alpha=3:veracity=7": 1 }; - expect(expectedObj).to.deep.equal(flattenObject(obj)); - }); - - it("throws error for wrong object", function() { - const obj = { - "value": 1.0, - "name": "p-norm", - "degree": 2, - "extraProperty": 1, - }; - - expect(() => { - flattenObject(obj); - }).to.throw(); - - }); -}); diff --git a/src/utils/selector.js b/src/utils/selector.js index fc8cccfe..882d2970 100644 --- a/src/utils/selector.js +++ b/src/utils/selector.js @@ -7,14 +7,14 @@ export function getSearchQuerySelector(searchQuery, fields = []) { const selector = {}; if (searchQuery) { - selector.$or = fields.map(field => { + selector.$or = fields.map((field) => { return { [field]: { $regex: searchQuery, - $options: 'i' - } - } - }) + $options: "i", + }, + }; + }); } return selector; } diff --git a/src/utils/str.js b/src/utils/str.js index ae52cfc3..c6d3cf27 100644 --- a/src/utils/str.js +++ b/src/utils/str.js @@ -1,7 +1,7 @@ import _ from "underscore"; export function removeNewLinesAndExtraSpaces(str) { - return str.replace(/[\n\r]/g, "").replace(/ +/g, ' ') + return str.replace(/[\n\r]/g, "").replace(/ +/g, " "); } /** @@ -17,7 +17,12 @@ export function randomAlphanumeric(length) { // Random letter is required in generated string because of when // the result is used as username and contains only numbers, the // slug will be inappropriate (e.g., "user-1232", "user-12" both have "user" as slug). - return randomLetter + Math.random().toString(36).substring(2, 2 + length - 1); + return ( + randomLetter + + Math.random() + .toString(36) + .substring(2, 2 + length - 1) + ); } export function toFixedLocale(number, precision) { @@ -35,9 +40,9 @@ export function toFixedLocale(number, precision) { */ export function removeCommentsFromSourceCode(text, language = "shell") { const regexList = { - "shell": /^(\s+)?#(?!!).*$/gm, + shell: /^(\s+)?#(?!!).*$/gm, }; - return text.replace(regexList[language], '') + return text.replace(regexList[language], ""); } /** @@ -47,5 +52,5 @@ export function removeCommentsFromSourceCode(text, language = "shell") { */ export function removeEmptyLinesFromString(string) { // remove "\n" on empty lines AND the very last "\n" - return string.replace(/^\s*[\r\n]/gm, '').trim() + return string.replace(/^\s*[\r\n]/gm, "").trim(); } diff --git a/src/utils/uuid.js b/src/utils/uuid.js index be47b377..7cfd6a50 100644 --- a/src/utils/uuid.js +++ b/src/utils/uuid.js @@ -1,4 +1,4 @@ -import {v4 as uuidv4} from "uuid"; +import { v4 as uuidv4 } from "uuid"; export function getUUID() { return uuidv4(); diff --git a/tests/in_memory.tests.js b/tests/in_memory.tests.js index 3175c95c..80338dcb 100644 --- a/tests/in_memory.tests.js +++ b/tests/in_memory.tests.js @@ -1,17 +1,19 @@ import { expect } from "chai"; + import { InMemoryEntity } from "../src/entity/in_memory"; describe("InMemoryEntity", () => { - const obj = { - "a": "b", - "name": "test", - } + a: "b", + name: "test", + }; it("can be created", () => { const empty = new InMemoryEntity(); + // eslint-disable-next-line no-unused-expressions expect(empty).to.exist; const entity = new InMemoryEntity(obj); + // eslint-disable-next-line no-unused-expressions expect(entity).to.exist; }); @@ -35,6 +37,7 @@ describe("InMemoryEntity", () => { const entity = new InMemoryEntity(obj); expect(entity.prop("a")).to.equal("b"); entity.unsetProp("a"); + // eslint-disable-next-line no-unused-expressions expect(entity.prop("a")).not.to.exist; }); @@ -42,5 +45,4 @@ describe("InMemoryEntity", () => { const entity = new InMemoryEntity(obj); expect(JSON.stringify(entity.toJSON())).to.be.equal(JSON.stringify(obj)); }); - }); diff --git a/tests/object.tests.js b/tests/object.tests.js new file mode 100644 index 00000000..9a230144 --- /dev/null +++ b/tests/object.tests.js @@ -0,0 +1,48 @@ +import { expect } from "chai"; + +import { flattenObject } from "../src/utils/object"; + +describe("flattenObject", () => { + it("serializes simple object", () => { + const obj = { + value: 1.0, + name: "p-norm", + degree: 2, + }; + + const expectedObj = { "p-norm:degree=2": 1 }; + expect(expectedObj).to.deep.equal(flattenObject(obj)); + }); + + it("serialize complex object", () => { + const obj = { + value: 1.0, + name: "p-norm", + extraProp: { + name: "zeta", + value: 6, + extraProp: { + name: "alpha", + value: 3, + veracity: 7, + }, + }, + }; + + const expectedObj = { "p-norm:zeta=6:alpha=3:veracity=7": 1 }; + expect(expectedObj).to.deep.equal(flattenObject(obj)); + }); + + it("throws error for wrong object", () => { + const obj = { + value: 1.0, + name: "p-norm", + degree: 2, + extraProperty: 1, + }; + + expect(() => { + flattenObject(obj); + }).to.throw(); + }); +}); diff --git a/tests/provider.tests.js b/tests/provider.tests.js index 24130f77..3a38fee1 100644 --- a/tests/provider.tests.js +++ b/tests/provider.tests.js @@ -1,13 +1,14 @@ import { expect } from "chai"; + import { ContextProvider } from "../src/context/provider"; describe("ContextProvider", () => { - const minimal = { name: "name" }; const data = { a: "test" }; it("can be created", () => { const provider = new ContextProvider(minimal); + // eslint-disable-next-line no-unused-expressions expect(provider).to.exist; }); @@ -18,9 +19,7 @@ describe("ContextProvider", () => { provider.setIsEdited(true); expect(JSON.stringify(provider.getData())).to.equal(JSON.stringify(data)); expect(() => provider.defaultData).to.throw("Not implemented."); - }) + }); // transform, yieldData, yieldDataForRendering - - }); diff --git a/tests/setup.js b/tests/setup.js index d2aa5842..c693a944 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,2 +1,2 @@ +// eslint-disable-next-line no-unused-vars import chai from "chai"; - diff --git a/tests/utils.class.js b/tests/utils.class.js index 0616d282..1170034a 100644 --- a/tests/utils.class.js +++ b/tests/utils.class.js @@ -1,40 +1,33 @@ -import { mix } from "mixwith"; +/* eslint-disable max-classes-per-file, class-methods-use-this */ import { expect } from "chai"; -import { InMemoryEntity, NamedInMemoryEntity, DefaultableMixin, RuntimeItemsMixin } from "../src/entity"; -import { deepClone } from "../src/utils/clone"; -import { extendClass, extendThis } from "../src/utils/class"; +import { mix } from "mixwith"; +import { + DefaultableMixin, + InMemoryEntity, + NamedInMemoryEntity, + RuntimeItemsMixin, +} from "../src/entity"; +import { extendClass, extendThis } from "../src/utils/class"; class BaseEntity extends mix(InMemoryEntity).with(RuntimeItemsMixin) { - - constructor(config) { - super(config); - } - baseMethod() { return "base"; } - } - class ExtendClassEntity extends mix(NamedInMemoryEntity).with(DefaultableMixin) { - constructor(config, excluded = []) { super(config); extendClass(ExtendClassEntity, BaseEntity, excluded, [config]); - } baseMethod() { return "derived"; } - } - class BaseBetweenEntity extends NamedInMemoryEntity { - static staticAttr = "base"; constructor(config) { @@ -45,12 +38,9 @@ class BaseBetweenEntity extends NamedInMemoryEntity { betweenMethod() { return "base"; } - } - class BetweenEntity extends BaseBetweenEntity { - static staticAttr = "between"; constructor(config) { @@ -63,24 +53,18 @@ class BetweenEntity extends BaseBetweenEntity { } } - class ExtendThisEntity extends mix(BetweenEntity).with(DefaultableMixin) { - - constructor(config, excluded = []) { + constructor(config) { super(config); extendThis(ExtendThisEntity, BaseEntity, config); - } baseMethod() { return "derived"; } - } - describe("extendClass", () => { - it("extends classes no excluded props", () => { const obj = new ExtendClassEntity({}); expect(obj.baseMethod()).to.be.equal("base"); @@ -92,23 +76,20 @@ describe("extendClass", () => { }); it("should have results but doesnt", () => { - const obj = new ExtendClassEntity({"results": ["test"]}); - expect(JSON.stringify(obj.results)).not.to.be.equal(JSON.stringify([{"name": "test"}])); + const obj = new ExtendClassEntity({ results: ["test"] }); + expect(JSON.stringify(obj.results)).not.to.be.equal(JSON.stringify([{ name: "test" }])); }); - }); - describe("extendThis", () => { - it("extends this prefer child method", () => { const obj = new ExtendThisEntity({}); expect(obj.baseMethod()).to.be.equal("derived"); }); it("extends this support base mixins", () => { - const obj = new ExtendThisEntity({"results": ["test"]}); - expect(JSON.stringify(obj.results)).to.be.equal(JSON.stringify([{"name": "test"}])); + const obj = new ExtendThisEntity({ results: ["test"] }); + expect(JSON.stringify(obj.results)).to.be.equal(JSON.stringify([{ name: "test" }])); }); it("remembers intermediate methods", () => { @@ -129,5 +110,4 @@ describe("extendThis", () => { expect(BaseBetweenEntity.staticAttr).to.be.equal("base"); expect(ExtendThisEntity.staticAttr).to.be.equal("between"); }); - }); diff --git a/tests/utils.tests.js b/tests/utils.tests.js index 4b4c50bb..6cd2b27e 100644 --- a/tests/utils.tests.js +++ b/tests/utils.tests.js @@ -1,23 +1,24 @@ import { expect } from "chai"; + import { deepClone } from "../src/utils/clone"; describe("deepClone", () => { const obj = { - "number": 1.0, - "string": "test", - "array": [1.0], - "object": {"a": "b"}, - } + number: 1.0, + string: "test", + array: [1.0], + object: { a: "b" }, + }; it("clones an object", () => { - const clone = deepClone(obj) - expect(clone).to.deep.equal(obj) - expect(clone) + const clone = deepClone(obj); + expect(clone).to.deep.equal(obj); + expect(clone); }); it("deep clones", () => { - const clone = deepClone(obj) - expect(clone).to.haveOwnProperty("object") - delete obj.object - const other = deepClone(obj) - expect(other).not.to.haveOwnProperty("object") - }) + const clone = deepClone(obj); + expect(clone).to.haveOwnProperty("object"); + delete obj.object; + const other = deepClone(obj); + expect(other).not.to.haveOwnProperty("object"); + }); }); From ce6a3293206f3bac6e4f0059d062055736c16ebd Mon Sep 17 00:00:00 2001 From: tjduigna Date: Tue, 26 Jul 2022 11:18:19 -0400 Subject: [PATCH 5/5] chore: remove template script --- template.py | 85 ----------------------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 template.py diff --git a/template.py b/template.py deleted file mode 100644 index b6811a47..00000000 --- a/template.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -""" -Safely delete this script and commit edited files after use -""" - -files = [ - "package.json", -] - -params = [ - "PROJECT_NAME", - "PROJECT_DESCRIPTION", -] - -readme = """\ -[![npm version](https://badge.fury.io/js/%40exabyte-io%2FPROJECT_NAME.svg)](https://badge.fury.io/js/%40exabyte-io%2FPROJECT_NAME) -[![License: Apache](https://img.shields.io/badge/License-Apache-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) - -# PROJECT_NAME - -PROJECT_NAME houses entity definitions for use in the Mat3ra platform. - - -### Installation - -For usage within a javascript project: - -```bash -npm install @exabyte-io/PROJECT_NAME -``` - -For development: - -```bash -git clone https://github.com/Exabyte-io/PROJECT_NAME.git -``` - - -### Contribution - -This repository is an [open-source](LICENSE.md) work-in-progress and we welcome contributions. - -We regularly deploy the latest code containing all accepted contributions online as part of the -[Mat3ra.com](https://mat3ra.com) platform, so contributors will see their code in action there. - -See [ESSE](https://github.com/Exabyte-io/esse) for additional context regarding the data schemas used here. - -Useful commands for development: - -```bash -# run linter without persistence -npm run lint - -# run linter and save edits -npm run lint:fix - -# compile the library -npm run transpile - -# run tests -npm run test -``` - -""" - -values = {} -for param in params: - values[param] = input(f"Please provide a value for {param}: ") - - -def replace(content, values): - for key, val in values.items(): - content = content.replace(key, val) - return content - - -for fl in files: - with open(fl, "r") as f: - content = f.read() - with open(fl, "w") as f: - f.write(replace(content, values)) - - -with open("README.md", "w") as f: - f.write(replace(readme, values))