diff --git a/.babelrc b/.babelrc index 4fce77d..4800916 100644 --- a/.babelrc +++ b/.babelrc @@ -9,6 +9,7 @@ } ], "@babel/preset-react", + "@babel/preset-typescript" ], "plugins": [ "@babel/plugin-proposal-class-properties" diff --git a/.eslintrc.json b/.eslintrc.json index 0b5cb28..1bee895 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,7 @@ { - "extends": ["@exabyte-io/eslint-config"] + "extends": [ + "@exabyte-io/eslint-config", + "plugin:import/typescript" + ] } diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..ec3216d --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extension": ["ts", "js"], + "spec": "tests/**/*.test.*", + "require": ["ts-node/register"] +} diff --git a/package-lock.json b/package-lock.json index 6568ef6..5666a72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -288,6 +288,11 @@ "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + }, "@babel/helper-validator-identifier": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", @@ -391,6 +396,16 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.16.0.tgz", + "integrity": "sha512-kFAhaIbh5qbBwETRNa/cgGmPJ/BicXhIyrZhAkyYhf/Z9LXCTRGO1mvUwczto0Hl1q4YtzP9cRtTKT4wujm38Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-default-from": "^7.16.0" + } + }, "@babel/plugin-proposal-export-namespace-from": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", @@ -528,6 +543,23 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.22.5.tgz", + "integrity": "sha512-ODAqWWXB/yReh/jVQDag/3/tl6lgBueQkk/TcfW/59Oykm4c8a55XloX0CTk2k2VJiFWMgHby9xNX29IbCv9dQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + } + } + }, "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", @@ -616,6 +648,21 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + } + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", @@ -920,6 +967,158 @@ "@babel/helper-plugin-utils": "^7.18.9" } }, + "@babel/plugin-transform-typescript": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz", + "integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "requires": { + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, "@babel/plugin-transform-unicode-escapes": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz", @@ -1050,6 +1249,104 @@ "@babel/plugin-transform-react-pure-annotations": "^7.16.7" } }, + "@babel/preset-typescript": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", + "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-typescript": "^7.22.15" + }, + "dependencies": { + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==" + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "requires": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@babel/register": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", @@ -1071,9 +1368,9 @@ } }, "@babel/runtime-corejs2": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.22.15.tgz", - "integrity": "sha512-CcAMW2o5uqgeXIXYYPrgmaYj1HOLvQb2DrBi7+bELD4nUVSKk+Sth+yYuGqSRf+aAiOv3sIZJTUiJBhoASJRLg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.23.2.tgz", + "integrity": "sha512-lTwRWGcAUBANnxD0A4c5/wKQ0eLhgdAy9kdY2rzTmmliumBQ8u8awykMnaQAnZR3PC47jLRjGoj+hozZqy9Bww==", "dev": true, "requires": { "core-js": "^2.6.12", @@ -1191,6 +1488,29 @@ } } }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } + } + }, + "@eslint-community/regexpp": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "dev": true + }, "@eslint/eslintrc": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", @@ -1241,10 +1561,71 @@ } } }, + "@exabyte-io/application-flavors.js": { + "version": "git+https://github.com/Exabyte-io/application-flavors.git#b3de5b1111d5f1300fe97cd6483265ac28640466", + "from": "git+https://github.com/Exabyte-io/application-flavors.git#b3de5b1111d5f1300fe97cd6483265ac28640466", + "dev": true, + "requires": { + "@babel/cli": "7.16.0", + "@babel/core": "7.16.7", + "@babel/eslint-parser": "7.16.3", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-export-default-from": "7.16.0", + "@babel/preset-env": "7.16.4", + "@babel/register": "7.16.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "underscore": "^1.12.1", + "underscore.string": "^3.3.4" + }, + "dependencies": { + "@babel/core": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz", + "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.16.7", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + } + }, + "@babel/register": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.0.tgz", + "integrity": "sha512-lzl4yfs0zVXnooeLE0AAfYaT7F3SPA8yB2Bj4W1BiZwLbMS3MZH35ZvCWSRHvneUugwuM+Wsnrj7h0F7UmU3NQ==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, "@exabyte-io/code.js": { - "version": "2023.9.14-1", - "resolved": "https://registry.npmjs.org/@exabyte-io/code.js/-/code.js-2023.9.14-1.tgz", - "integrity": "sha512-Auwr0iw7OWz3caoVWwVkEIMVj0CK93Z1eE4ZrEtqS6HAqGVAavp1FfgNVrNPjZinzVZNfyykKOCGe4D+H/ReKA==", + "version": "git+https://github.com/Exabyte-io/code.js.git#b94c987f98d620790466cefc04ba354395a1c62d", + "from": "git+https://github.com/Exabyte-io/code.js.git#b94c987f98d620790466cefc04ba354395a1c62d", "dev": true, "requires": { "@babel/cli": "7.16.0", @@ -1255,7 +1636,7 @@ "@babel/preset-react": "7.16.7", "@babel/register": "^7.16.0", "@babel/runtime-corejs3": "7.16.8", - "@exabyte-io/esse.js": "2023.8.31-0", + "@exabyte-io/esse.js": "^2023.10.24-0", "@types/chai": "^4.3.5", "@types/crypto-js": "^4.1.1", "@types/js-yaml": "^4.0.5", @@ -1296,15 +1677,15 @@ } }, "@exabyte-io/eslint-config": { - "version": "2022.11.17-0", - "resolved": "https://registry.npmjs.org/@exabyte-io/eslint-config/-/eslint-config-2022.11.17-0.tgz", - "integrity": "sha512-BYTDSqvjj6ZiWb8l46T5BKrVfkelct+vK2mh7joHu5UWtJMUzLkb0KQMV1+6SUy4xHFnws33XS7/+JSW1yeZOQ==", + "version": "2023.8.29-1", + "resolved": "https://registry.npmjs.org/@exabyte-io/eslint-config/-/eslint-config-2023.8.29-1.tgz", + "integrity": "sha512-2da786Y5j3soXcxRi/MST6qc2aIUgTjCjcqfm+xQkGfJSV8FaQR/jccENLZ5i5ynYUMqQ8Elir2Q3n4LBFqeBg==", "dev": true }, "@exabyte-io/esse.js": { - "version": "2023.8.31-0", - "resolved": "https://registry.npmjs.org/@exabyte-io/esse.js/-/esse.js-2023.8.31-0.tgz", - "integrity": "sha512-thSlEJ7ToUJg/y5tMLtzfMAWPU7IQ7H1NcYt+Y86F/MYBF3N+20jFJeohafLJ+OJe432LqBZPP7F/IRr4kD6fA==", + "version": "2023.10.24-0", + "resolved": "https://registry.npmjs.org/@exabyte-io/esse.js/-/esse.js-2023.10.24-0.tgz", + "integrity": "sha512-6Oz0azZlCpiQ0vlO7m+JjBfpQf33I75dnOgV3hztIs5XC/sz0i3DnoPwNzbXR6LpYkiu40XjW+lO/Z0hDhSm+g==", "dev": true, "requires": { "@babel/cli": "7.16.0", @@ -1570,6 +1951,32 @@ "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", "optional": true }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1601,9 +2008,9 @@ "dev": true }, "@types/crypto-js": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.2.tgz", - "integrity": "sha512-t33RNmTu5ufG/sorROIafiCVJMx3jz95bXUMoPAZcUD14fxMXnuTzqzXZoxpR0tNx2xpw11Dlmem9vGCsrSOfA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.3.tgz", + "integrity": "sha512-YP1sYYayLe7Eg5oXyLLvOLfxBfZ5Fgpz6sVWkpB18wDMywCLPWmqzRz+9gyuOoLF0fzDTTFwlyNbx7koONUwqA==", "dev": true }, "@types/glob": { @@ -1635,9 +2042,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.198", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz", - "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==", + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", "dev": true }, "@types/minimatch": { @@ -1665,15 +2072,15 @@ "dev": true }, "@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "version": "15.7.9", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", + "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", "dev": true }, "@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", "dev": true, "requires": { "@types/prop-types": "*", @@ -1682,9 +2089,9 @@ } }, "@types/react-jsonschema-form": { - "version": "1.7.8", - "resolved": "https://registry.npmjs.org/@types/react-jsonschema-form/-/react-jsonschema-form-1.7.8.tgz", - "integrity": "sha512-oFyNOa8VDSt1jGN4r+prTFD2hojZBsqLoTkRfo+XvANR3taLUeMJlGhtOP+hpi/k19OxpEb24TZciMmQyPZ9TA==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@types/react-jsonschema-form/-/react-jsonschema-form-1.7.10.tgz", + "integrity": "sha512-WycAa8c+f78wYVvEgCoN7Pv6u8t8LN2rgZirv898OWFAXSK96QXH1v0FnJvHvhdTqG7ap/Mk/ODaSZK2Aa0XLw==", "dev": true, "requires": { "@types/json-schema": "*", @@ -1692,9 +2099,15 @@ } }, "@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", + "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", + "dev": true + }, + "@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, "@types/underscore": { @@ -1703,6 +2116,152 @@ "integrity": "sha512-M63wKUdsjDFUfyFt1TCUZHGFk9KDAa5JP0adNUErbm0U45Lr06HtANdYRP+GyleEopEoZ4UyBcdAC5TnW4Uz2w==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -1887,6 +2446,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -2411,9 +2976,9 @@ "dev": true }, "crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "dev": true }, "csstype": { @@ -2511,6 +3076,15 @@ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2537,6 +3111,16 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -2884,6 +3468,52 @@ } } }, + "eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "dependencies": { + "eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + } + } + }, "eslint-module-utils": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", @@ -3057,6 +3687,15 @@ } } }, + "eslint-plugin-mui-path-imports": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/eslint-plugin-mui-path-imports/-/eslint-plugin-mui-path-imports-0.0.15.tgz", + "integrity": "sha512-u61kgRBtUAG+zoApuf8oWuW6mf3SIfrpMq/gSQEM2h/3qzkqvWXB4RRmPzVryS6bpeXT0QsW8rFcdcMVnoz0hw==", + "dev": true, + "requires": { + "requireindex": "^1.2.0" + } + }, "eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -3282,6 +3921,19 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "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", @@ -3294,6 +3946,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "file": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/file/-/file-0.2.2.tgz", @@ -3479,6 +4140,15 @@ "get-intrinsic": "^1.1.1" } }, + "get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -3514,12 +4184,46 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -3585,6 +4289,23 @@ } } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + } + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -4554,6 +5275,12 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -4587,7 +5314,8 @@ "mixwith": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/mixwith/-/mixwith-0.1.1.tgz", - "integrity": "sha512-DQsf/liljH/9e+94jR+xfK8vlKceeKdOM9H9UEXLwGuvEEpO6debNtJ9yt1ZKzPKPrwqGxzMdu0BR1fnQb6i4A==" + "integrity": "sha512-DQsf/liljH/9e+94jR+xfK8vlKceeKdOM9H9UEXLwGuvEEpO6debNtJ9yt1ZKzPKPrwqGxzMdu0BR1fnQb6i4A==", + "dev": true }, "mkdirp": { "version": "1.0.4", @@ -4799,6 +5527,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -5240,6 +5974,12 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -5333,6 +6073,12 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5501,6 +6247,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -5517,6 +6269,12 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", @@ -5533,6 +6291,12 @@ "signal-exit": "^3.0.2" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", @@ -5548,6 +6312,15 @@ "glob": "^7.1.3" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "rxjs": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", @@ -5894,6 +6667,12 @@ } } }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -6034,6 +6813,23 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", diff --git a/package.json b/package.json index a358054..80e266b 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "0.0.0", "description": "MOdel and method DEfinitions", "scripts": { - "test": "nyc --reporter=text mocha --recursive --bail --require @babel/register/lib --require tests/setup.js tests", + "test": "mocha", "lint": "eslint src tests && prettier --write src tests", "lint:fix": "eslint --fix --cache src tests && prettier --write src tests", "build:assets": "node build_entities.js && node build_filter.js", - "transpile": "babel --out-dir dist src", + "transpile": "tsc", "postinstall": "npm run transpile", "prettier": "prettier --check src tests", "prepare": "husky install || exit 0" @@ -23,7 +23,8 @@ "/src", ".babelrc", "build_entities.js", - "build_filter.js" + "build_filter.js", + "tsconfig.json" ], "author": "Exabyte Inc.", "bugs": { @@ -38,27 +39,38 @@ "@babel/plugin-proposal-class-properties": "7.16.0", "@babel/preset-env": "7.16.4", "@babel/preset-react": "7.16.7", + "@babel/preset-typescript": "^7.22.5", "@babel/register": "^7.16.0", "@babel/runtime-corejs3": "7.16.8", "ajv": "4.1.7", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "mixwith": "^0.1.1", "underscore": "^1.13.3", "underscore.string": "^3.3.4" }, "devDependencies": { - "@exabyte-io/code.js": "2023.9.14-1", - "@exabyte-io/eslint-config": "^2022.11.17-0", + "@babel/preset-typescript": "^7.22.5", + "@exabyte-io/application-flavors.js": "git+https://github.com/Exabyte-io/application-flavors.git#b3de5b1111d5f1300fe97cd6483265ac28640466", + "@exabyte-io/code.js": "git+https://github.com/Exabyte-io/code.js.git#b94c987f98d620790466cefc04ba354395a1c62d", + "@exabyte-io/eslint-config": "^2023.8.29-1", "@exabyte-io/made.js": "2022.6.15-0", + "@types/chai": "^4.3.5", + "@types/js-yaml": "^4.0.5", + "@types/mocha": "^10.0.1", + "@types/node": "^20.4.2", + "@types/underscore": "^1.11.6", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", "chai": "^4.3.4", "eslint": "7.32.0", "eslint-config-airbnb": "19.0.2", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-exports": "^1.0.0-beta.2", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "2.25.3", "eslint-plugin-jsdoc": "37.1.0", "eslint-plugin-jsx-a11y": "6.5.1", + "eslint-plugin-mui-path-imports": "0.0.15", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "7.30.0", "eslint-plugin-simple-import-sort": "7.0.0", @@ -66,10 +78,13 @@ "lint-staged": "^12.1.2", "mocha": "^9.1.3", "nyc": "^15.1.0", - "prettier": "^2.7.1" + "prettier": "^2.7.1", + "ts-node": "^10.9.1", + "typescript": "^4.5.5" }, "peerDependencies": { "@exabyte-io/ade.js": "*", + "@exabyte-io/application-flavors.js": "*", "@exabyte-io/code.js": "*", "@exabyte-io/made.js": "*" }, @@ -77,7 +92,7 @@ "node": ">=12.0.0" }, "lint-staged": { - "*.js": "eslint --cache --fix", - "*.{js,css}": "prettier --write" + "*.{js,ts}": "eslint --cache --fix", + "*.{js,ts,css}": "prettier --write" } } diff --git a/src/default_methods.js b/src/default_methods.js deleted file mode 100644 index 85d91c8..0000000 --- a/src/default_methods.js +++ /dev/null @@ -1,38 +0,0 @@ -import lodash from "lodash"; - -import { MODEL_NAMES, MODEL_TREE } from "./tree"; - -export const PseudopotentialMethodConfig = { - type: "pseudopotential", - subtype: "us", -}; - -export const LocalOrbitalMethodConfig = { - type: "localorbital", - subtype: "pople", -}; - -export const UnknownMethodConfig = { - type: "unknown", - subtype: "unknown", -}; - -export function allowedTypes(model) { - return lodash - .keys(lodash.get(MODEL_TREE, `${model.type}.${model.subtype}.methods`, [])) - .map((x) => { - return { - slug: x, - name: lodash.get(MODEL_NAMES, x, x), - }; - }); -} - -export function allowedSubtypes(model, type) { - return lodash.get(MODEL_TREE, `${model.type}.${model.subtype}.methods.${type}`, []).map((x) => { - return { - slug: x, - name: lodash.get(MODEL_NAMES, x, x), - }; - }); -} diff --git a/src/default_methods.ts b/src/default_methods.ts new file mode 100644 index 0000000..80f27af --- /dev/null +++ b/src/default_methods.ts @@ -0,0 +1,20 @@ +import { + LegacyMethodLocalorbital, + LegacyMethodPseudopotential, + LegacyMethodUnknown, +} from "@exabyte-io/code.js/dist/types"; + +export const PseudopotentialMethodConfig: LegacyMethodPseudopotential = { + type: "pseudopotential", + subtype: "us", +}; + +export const LocalOrbitalMethodConfig: LegacyMethodLocalorbital = { + type: "localorbital", + subtype: "pople", +}; + +export const UnknownMethodConfig: LegacyMethodUnknown = { + type: "unknown", + subtype: "unknown", +}; diff --git a/src/default_models.js b/src/default_models.js deleted file mode 100644 index 3614747..0000000 --- a/src/default_models.js +++ /dev/null @@ -1,9 +0,0 @@ -export const DFTModelConfig = { - type: "dft", - subtype: "gga", -}; - -export const UnknownModelConfig = { - type: "unknown", - subtype: "unknown", -}; diff --git a/src/default_models.ts b/src/default_models.ts new file mode 100644 index 0000000..4f773de --- /dev/null +++ b/src/default_models.ts @@ -0,0 +1,14 @@ +import { + LegacyModelDensityFunctionalTheory, + LegacyModelUnknown, +} from "@exabyte-io/code.js/dist/types"; + +export const DFTModelConfig: Omit = { + type: "dft", + subtype: "gga", +}; + +export const UnknownModelConfig: Omit = { + type: "unknown", + subtype: "unknown", +}; diff --git a/src/filter.js b/src/filter.js new file mode 100644 index 0000000..b99f462 --- /dev/null +++ b/src/filter.js @@ -0,0 +1,62 @@ +import { filterEntityList, mergeTerminalNodes } from "@exabyte-io/code.js/dist/utils"; +import lodash from "lodash"; + +import modelMethodMap from "./data/model_method_map"; + +function safelyGet(obj, ...args) { + return lodash.get(obj, args, undefined); +} + +/** + * Create list of filter objects based on model categories. + * @param {Object} filterTree - filter tree constructed from assets + * @param {string} tier1 - Level 1 tier + * @param {string} tier2 - Level 2 tier + * @param {string} tier3 - Level 3 tier + * @param {string} type - Type + * @param {string} subtype - Subtype + * @return {*[]} + */ +function getMethodFilterObjects({ filterTree, tier1, tier2, tier3, type, subtype }) { + let filterList; + if (!tier1) { + filterList = mergeTerminalNodes(filterTree); + } else if (!tier2) { + filterList = mergeTerminalNodes(safelyGet(filterTree, tier1)); + } else if (!tier3) { + filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2)); + } else if (!type) { + filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2, tier3)); + } else if (!subtype) { + filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2, tier3, type)); + } else { + filterList = safelyGet(filterTree, tier1, tier2, tier3, type, subtype); + } + const extractUniqueBy = (name) => { + return lodash + .chain(filterList) + .filter(Boolean) + .filter((o) => Boolean(o[name])) + .uniqBy(name) + .value(); + }; + + return [].concat(extractUniqueBy("path"), extractUniqueBy("regex")); +} + +/** + * Filter list of method configs based on model + * @param {Object[]} methodList - Array of method configs + * @param {Object} model - Model config for which methods should be filtered + * @return {Object[]} + */ +export function filterMethodsByModel({ methodList, model }) { + if (!model) return []; + const { categories } = model; + const filterObjects = getMethodFilterObjects({ filterTree: modelMethodMap, ...categories }); + return filterEntityList({ + entitiesOrPaths: methodList, + filterObjects, + multiPathSeparator: "::", + }); +} diff --git a/src/method.js b/src/method.js index 96af12f..f90ddbf 100644 --- a/src/method.js +++ b/src/method.js @@ -1,10 +1,11 @@ -import { InMemoryEntity } from "@exabyte-io/code.js/dist/entity"; +import { DefaultableInMemoryEntity } from "@exabyte-io/code.js/dist/entity"; import { deepClone } from "@exabyte-io/code.js/dist/utils"; -import lodash from "lodash"; +import isEmpty from "lodash/isEmpty"; +import omit from "lodash/omit"; import { PseudopotentialMethodConfig } from "./default_methods"; -export class Method extends InMemoryEntity { +export class Method extends DefaultableInMemoryEntity { constructor(config) { const data = config.data || {}; super({ ...config, data }); @@ -57,7 +58,7 @@ export class Method extends InMemoryEntity { get omitInHashCalculation() { const data = this.prop("data"); - return !data.searchText && lodash.isEmpty(lodash.omit(data, "searchText")); + return !data.searchText && isEmpty(omit(data, "searchText")); } // data without client-only fields diff --git a/src/methods/pseudopotential.js b/src/methods/pseudopotential.js index ff0b588..479333f 100644 --- a/src/methods/pseudopotential.js +++ b/src/methods/pseudopotential.js @@ -1,5 +1,5 @@ import { safeMakeArray } from "@exabyte-io/code.js/dist/utils"; -import _ from "underscore"; +import sortBy from "lodash/sortBy"; import { Method } from "../method"; @@ -71,7 +71,7 @@ export class PseudopotentialMethod extends Method { // sort by alphabetical order to ensure elements order consistency in VASP POSCAR/POTCAR this.setData({ ...this.data, - pseudo: _.sortBy(pseudopotentials, "element").map((x) => x.toJSON()), + pseudo: sortBy(pseudopotentials, ["element"]).map((x) => x.toJSON()), }); } @@ -82,7 +82,7 @@ export class PseudopotentialMethod extends Method { // sort by alphabetical order to ensure elements order consistency in VASP POSCAR/POTCAR this.setData({ ...this.data, - allPseudo: _.sortBy(pseudopotentials, "element").map((x) => x.toJSON()), + allPseudo: sortBy(pseudopotentials, ["element"]).map((x) => x.toJSON()), }); } diff --git a/src/model.js b/src/model.js index f48575d..da95d09 100644 --- a/src/model.js +++ b/src/model.js @@ -1,16 +1,18 @@ -import { InMemoryEntity } from "@exabyte-io/code.js/dist/entity"; +import { DefaultableInMemoryEntity } from "@exabyte-io/code.js/dist/entity"; import lodash from "lodash"; import { DFTModelConfig } from "./default_models"; import { Method } from "./method"; import { MethodFactory } from "./methods/factory"; -import { getTreeByApplicationNameAndVersion, MODEL_TREE, treeSlugToNamedObject } from "./tree"; +import { MethodInterface } from "./utils/method_interface"; +import { ModelInterface } from "./utils/model_interface"; -export class Model extends InMemoryEntity { +export class Model extends DefaultableInMemoryEntity { constructor({ application, ...config }) { super(config); this._application = application; this._MethodFactory = MethodFactory; + this._defaultCategorized = this.getDefaultCategorizedModel(); } get type() { @@ -26,37 +28,12 @@ export class Model extends InMemoryEntity { this.setMethod(this._MethodFactory.create(this.defaultMethodConfig)); } - get allowedTypes() { - return Object.keys(this.tree).map((modelSlug) => treeSlugToNamedObject(modelSlug)); - } - - get allowedSubtypes() { - return Object.keys(this.treeBranchForType).map((slug) => treeSlugToNamedObject(slug)); - } - get defaultType() { - return this.allowedTypes[0]?.slug; + return this._defaultConfig.type; } get defaultSubtype() { - return this.allowedSubtypes[0]?.slug; - } - - get tree() { - return (this._application && this.treeByApplicationNameAndVersion) || MODEL_TREE; - } - - get treeBranchForType() { - return this.tree[this.type] || {}; - } - - get treeBranchForSubType() { - return this.treeBranchForType[this.subtype] || {}; - } - - get treeByApplicationNameAndVersion() { - const [name, version] = [this._application.name, this._application.version]; - return getTreeByApplicationNameAndVersion({ name, version }); + return this._defaultConfig.subtype; } get groupSlug() { @@ -75,23 +52,29 @@ export class Model extends InMemoryEntity { this._method = method; } - // Consider moving the below to `Method` - get methodsFromTree() { - return this.treeBranchForSubType.methods || {}; + getCategorizedMethods() { + const catModel = ModelInterface.convertToCategorized(this._json); + return MethodInterface.filterCategorizedMethods({ + application: this._application, + model: catModel, + }); } - get methodTypes() { - return Object.keys(this.methodsFromTree).map((m) => treeSlugToNamedObject(m)); + get defaultMethodConfig() { + const [defaultCategorizedMethod] = this.getCategorizedMethods(); + return MethodInterface.convertToSimple(defaultCategorizedMethod); } - get methodSubtypes() { - return this.methodsFromTree[this.method.type].map((m) => treeSlugToNamedObject(m)) || []; + /** + * @returns {{ path: string }[]} - Array of categorized models + */ + getCategorizedModels() { + return ModelInterface.filterCategorizedModels(this._application); } - get defaultMethodConfig() { - const type = Object.keys(this.methodsFromTree)[0]; - const subtype = (this.methodsFromTree[type] || [])[0]; - return { type, subtype }; + getDefaultCategorizedModel() { + if (this.type === "unknown") return undefined; + return this.getCategorizedModels()[0]; } static get defaultConfig() { @@ -101,8 +84,16 @@ export class Model extends InMemoryEntity { }; } - static get allTypes() { - return Object.keys(this.tree).map((modelSlug) => treeSlugToNamedObject(modelSlug)); + /** + * Instance method for default config. + * This is used to obtain default properties such as type/subtype. + */ + get _defaultConfig() { + // TODO: Add suitable method, given application/model + const defaultModel = ModelInterface.convertToSimple(this._defaultCategorized); + return { + ...defaultModel, + }; } toJSON() { diff --git a/src/models/dft.js b/src/models/dft.js index 7fef6b7..9a2bc63 100644 --- a/src/models/dft.js +++ b/src/models/dft.js @@ -1,8 +1,8 @@ -import _ from "underscore"; +import { filterEntityList } from "@exabyte-io/code.js/dist/utils"; import { MethodFactory } from "../methods/factory"; import { Model } from "../model"; -import { treeSlugToNamedObject } from "../tree"; +import { safelyGetSlug, stringToSlugifiedEntry } from "../utils/slugifiedEntry"; export class DFTModel extends Model { constructor(config) { @@ -29,7 +29,10 @@ export class DFTModel extends Model { } get defaultFunctional() { - return treeSlugToNamedObject(this.treeBranchForSubType.functionals[0]); + const functional = this._defaultConfig?.functional + ? safelyGetSlug(this._defaultConfig?.functional) + : "pbe"; + return stringToSlugifiedEntry(functional); } // eslint-disable-next-line class-methods-use-this @@ -43,7 +46,8 @@ export class DFTModel extends Model { } get functional() { - return this.prop("functional", this.defaultFunctional); + const functional = this.prop("functional", this.defaultFunctional); + return typeof functional === "string" ? stringToSlugifiedEntry(functional) : functional; } get refiners() { @@ -54,19 +58,32 @@ export class DFTModel extends Model { return this.prop("modifiers", this.defaultModifiers); } + getDefaultCategorizedModel() { + const subtype = this.prop("subtype", "gga"); + + const filterObj = { + regex: "\\/pb\\/qm\\/dft\\/ksdft\\/" + subtype + "\\?functional=([A-Za-z0-9_-]+)", + }; + const filtered = filterEntityList({ + entitiesOrPaths: this.getCategorizedModels(), + filterObjects: [filterObj], + }); + return filtered[0]; + } + setSubtype(subtype) { this.setProp("subtype", subtype); this.setFunctional(this.defaultFunctional); } setFunctional(functional) { - this.setProp("functional", this._stringToSlugifiedObject(functional)); + this.setProp("functional", stringToSlugifiedEntry(functional)); this.setMethod(this._MethodFactory.create(this.defaultMethodConfig)); } _setArrayProp(name, data) { // eslint-disable-next-line no-param-reassign, no-undef - data = safeMakeArray(data).map((r) => this._stringToSlugifiedObject(r)); + data = safeMakeArray(data).map((r) => stringToSlugifiedEntry(r)); this.setProp(name, data); this[`_${name}`] = data; } @@ -80,36 +97,12 @@ export class DFTModel extends Model { } toJSON() { - const pickSlugFromObject = (o) => _.pick(o, "slug"); + const functional = safelyGetSlug(this.functional); return { ...super.toJSON(), - functional: pickSlugFromObject(this.functional), // only store slug for `functional` + functional, refiners: this.refiners, modifiers: this.modifiers, }; } - - /** - * Get all functionals in the form of {name: ..., slug: ...} for further use in UI - * @returns {Object.[]} - List of functional objects - */ - get allFunctionals() { - return this.treeBranchForSubType.functionals.map((x) => treeSlugToNamedObject(x)); - } - - /** - * Get all refiners in the form of {name: ..., slug: ...} for further use in UI - * @returns {Object.[]} - List of refiner objects - */ - get allRefiners() { - return this.treeBranchForSubType.refiners.map((x) => treeSlugToNamedObject(x)); - } - - /** - * Get all modifiers in the form of {name: ..., slug: ...} for further use in UI - * @returns {Object.[]} - List of modifier objects - */ - get allModifiers() { - return this.treeBranchForSubType.modifiers.map((x) => treeSlugToNamedObject(x)); - } } diff --git a/src/models/factory.js b/src/models/factory.js index decbd6f..bafc745 100644 --- a/src/models/factory.js +++ b/src/models/factory.js @@ -1,5 +1,8 @@ +import { filterModelsByApplicationParameters } from "@exabyte-io/application-flavors.js/lib/js/models"; + +import { allModels as categorizedModelList } from "../data/model_list"; import { Model } from "../model"; -import { getDefaultModelTypeForApplication } from "../tree"; +import { ModelInterface } from "../utils/model_interface"; import { DFTModel } from "./dft"; export class ModelFactory { @@ -16,13 +19,20 @@ export class ModelFactory { } } + static getDefaultModelForApplication(application) { + if (!application) return ModelInterface.convertToSimple(categorizedModelList[0]); + const filteredModels = filterModelsByApplicationParameters({ + modelList: categorizedModelList, + appName: application?.name, + version: application?.version, + build: application?.build, + }); + return ModelInterface.convertToSimple(filteredModels[0]); + } + static createFromApplication(config) { const { application } = config; - const type = application && getDefaultModelTypeForApplication(application); - if (!type) - throw new Error( - `ModelFactory.createFromApplication: cannot determine model type: ${type}`, - ); - return this.create({ ...config, type }); + const defaultModel = this.getDefaultModelForApplication(application); + return this.create({ ...config, ...defaultModel }); } } diff --git a/src/modules.d.ts b/src/modules.d.ts new file mode 100644 index 0000000..252d374 --- /dev/null +++ b/src/modules.d.ts @@ -0,0 +1,41 @@ +declare module "@exabyte-io/application-flavors.js/lib/js/methods" { + // TODO: add TS to application-flavors + + interface FilterPropsMethod { + methodList: object[]; + appName?: string; + version?: string; + build?: string; + executable?: string; + flavor?: string; + } + + export function filterMethodsByApplicationParameters({ + methodList, + appName, + version, + build, + executable, + flavor, + }: FilterProps): object[]; +} + +declare module "@exabyte-io/application-flavors.js/lib/js/models" { + interface FilterPropsModel { + modelList: object[]; + appName?: string; + version?: string; + build?: string; + executable?: string; + flavor?: string; + } + + export function filterModelsByApplicationParameters({ + modelList, + appName, + version, + build, + executable, + flavor, + }: FilterPropsModel): object[]; +} diff --git a/src/tree.js b/src/tree.js deleted file mode 100644 index ec6bab8..0000000 --- a/src/tree.js +++ /dev/null @@ -1,222 +0,0 @@ -import { deepClone, filterEntityList, mergeTerminalNodes } from "@exabyte-io/code.js/dist/utils"; -import lodash from "lodash"; -import _ from "underscore"; - -import modelMethodMap from "./data/model_method_map"; - -// TODO: migrate to use manifest instead - -export const METHODS = { - pseudopotential: "pseudopotential", - localorbital: "localorbital", - unknown: "unknown", -}; - -const methods = { - [METHODS.pseudopotential]: ["paw", "nc", "us"], - // TODO: Add additional basis set options, once user choice of specific (i.e 3-21G vs cc-pVDZ) is implemented. - [METHODS.localorbital]: ["pople"], - [METHODS.unknown]: ["unknown"], -}; - -export const getPseudopotentialTypesFromTree = () => methods[METHODS.pseudopotential]; - -// DFT-specific - -const DFTModelRefiners = ["hse", "g0w0"]; -const DFTModelModifiers = ["soc", "magn"]; - -const DFTModelTree = { - gga: { - refiners: DFTModelRefiners, - modifiers: DFTModelModifiers, - methods, - functionals: ["pbe", "pbesol", "pw91", "other"], - }, - lda: { - refiners: DFTModelRefiners, - modifiers: DFTModelModifiers, - methods, - functionals: ["pz", "pw", "vwn", "other"], - }, - hybrid: { - methods, - functionals: ["b3lyp", "hse06"], - }, - other: { - methods, - functionals: ["other"], - }, -}; - -export const getDFTFunctionalsFromTree = () => Object.keys(DFTModelTree); - -export const getDFTFunctionalsByApproximation = (approximation) => { - const branch = DFTModelTree[approximation]; - return branch && branch.functionals; -}; - -// GENERAL - -export const MODEL_TREE = { - dft: DFTModelTree, - ml: { - re: { - methods: { - linear: ["least_squares", "ridge"], - kernel_ridge: ["least_squares"], - }, - }, - }, - unknown: { - unknown: { - methods: { - unknown: ["unknown"], - }, - }, - }, -}; - -export const MODEL_NAMES = { - dft: "density functional theory", - lda: "local density approximation", - gga: "generalized gradient approximation", - hybrid: "hybrid functional", - ml: "machine learning", - re: "regression", -}; - -export const treeSlugToNamedObject = (modelSlug) => { - return { - slug: modelSlug, - name: lodash.get(MODEL_NAMES, modelSlug, modelSlug), - }; -}; - -// TODO: find a better way to handle application-specific model-method combination -// must be a subset of the MODEL_TREE above -// demonstrate how tree can be modified -// VASP_MODELS_TREE.gga.functionals = _.omit(VASP_MODELS_TREE.gga.functionals); - -const VASP_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")); -const ESPRESSO_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")); -const NWCHEM_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")); - -["gga", "lda"].forEach((approximation) => { - // pick "paw" for vasp - VASP_MODELS_TREE.dft[approximation].methods.pseudopotential = VASP_MODELS_TREE.dft[ - approximation - ].methods.pseudopotential.splice(0, 1); - - // assert "us" is the first option - ESPRESSO_MODELS_TREE.dft[approximation].methods.pseudopotential = - ESPRESSO_MODELS_TREE.dft[approximation].methods.pseudopotential.reverse(); -}); - -const UNKNOWN_MODELS_TREE = _.pick(MODEL_TREE, "unknown"); -const ML_MODELS_TREE = _.pick(MODEL_TREE, "ml"); - -const MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION = [ - { - name: "vasp", - tree: VASP_MODELS_TREE, - }, - { - name: "espresso", - tree: ESPRESSO_MODELS_TREE, - }, - { - name: "python", - tree: UNKNOWN_MODELS_TREE, - }, - { - name: "shell", - tree: UNKNOWN_MODELS_TREE, - }, - { - name: "exabyteml", - tree: ML_MODELS_TREE, - }, - { - name: "jupyterLab", - tree: UNKNOWN_MODELS_TREE, - }, - { - name: "nwchem", - tree: NWCHEM_MODELS_TREE, - }, -]; - -export const getTreeByApplicationNameAndVersion = ({ - name, - // eslint-disable-next-line no-unused-vars - version, -}) => { - // TODO: add logic to filter by version when necessary - const cfgs = MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION.filter( - (cfg) => cfg.name === name, - ).map((x) => x.tree); - return Object.assign({}, ...cfgs); -}; - -export const getDefaultModelTypeForApplication = (application) => { - return Object.keys(getTreeByApplicationNameAndVersion(application))[0]; -}; - -function safelyGet(obj, ...args) { - return lodash.get(obj, args, undefined); -} - -/** - * Create list of filter objects based on model categories. - * @param {Object} filterTree - filter tree constructed from assets - * @param {string} tier1 - Level 1 tier - * @param {string} tier2 - Level 2 tier - * @param {string} tier3 - Level 3 tier - * @param {string} type - Type - * @param {string} subtype - Subtype - * @return {*[]} - */ -function getMethodFilterObjects({ filterTree, tier1, tier2, tier3, type, subtype }) { - let filterList; - if (!tier1) { - filterList = mergeTerminalNodes(filterTree); - } else if (!tier2) { - filterList = mergeTerminalNodes(safelyGet(filterTree, tier1)); - } else if (!tier3) { - filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2)); - } else if (!type) { - filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2, tier3)); - } else if (!subtype) { - filterList = mergeTerminalNodes(safelyGet(filterTree, tier1, tier2, tier3, type)); - } else { - filterList = safelyGet(filterTree, tier1, tier2, tier3, type, subtype); - } - const extractUniqueBy = (name) => { - return lodash - .chain(filterList) - .filter(Boolean) - .filter((o) => Boolean(o[name])) - .uniqBy(name) - .value(); - }; - - return [].concat(extractUniqueBy("path"), extractUniqueBy("regex")); -} - -/** - * Filter list of method configs based on model - * @param {Object[]} methodList - Array of method configs - * @param {Object} model - Model config for which methods should be filtered - * @return {Object[]} - */ -export function filterMethodsByModel({ methodList, model }) { - if (!model) return []; - const { categories } = model; - const filterObjects = getMethodFilterObjects({ filterTree: modelMethodMap, ...categories }); - return filterEntityList({ - entitiesOrPaths: methodList, - filterObjects, - multiPathSeparator: "::", - }); -} diff --git a/src/tree.ts b/src/tree.ts new file mode 100644 index 0000000..cde5ecf --- /dev/null +++ b/src/tree.ts @@ -0,0 +1,57 @@ +// TODO: migrate to use manifest instead +import { MethodInterface } from "./utils/method_interface"; +import { ModelInterface } from "./utils/model_interface"; +import { safelyGetSlug } from "./utils/slugifiedEntry"; + +export const METHODS = { + pseudopotential: "pseudopotential", + localorbital: "localorbital", + unknown: "unknown", +}; + +export const MODEL_NAMES = { + dft: "density functional theory", + lda: "local density approximation", + gga: "generalized gradient approximation", + hybrid: "hybrid functional", + ml: "machine learning", + re: "regression", +}; + +export function getDFTApproximations(): string[] { + const approximations = ModelInterface.filterCategorizedModels().reduce( + (accumulator, item) => { + if (item.categories.type === "ksdft" && item.categories.subtype) { + accumulator.push(safelyGetSlug(item.categories.subtype)); + } + return accumulator; + }, + [], + ); + return [...new Set(approximations)]; +} + +export function getDFTFunctionalsByApproximation(approximation: string): string[] { + const functionals = ModelInterface.filterCategorizedModels().reduce( + (accumulator, item) => { + // @ts-ignore todo: make sure it is dft model + if (item.categories?.subtype === approximation && item.parameters?.functional) { + // @ts-ignore + accumulator.push(item.parameters.functional); + } + return accumulator; + }, + [], + ); + return [...new Set(functionals)]; +} + +export function getPseudopotentialTypes(): string[] { + const subtypes = MethodInterface.filterLegacyMethods().reduce((accumulator, item) => { + if (item.type === METHODS.pseudopotential) { + accumulator.push(safelyGetSlug(item.subtype)); + } + return accumulator; + }, []); + return [...new Set(subtypes)]; +} diff --git a/src/utils/method_interface.ts b/src/utils/method_interface.ts new file mode 100644 index 0000000..2dabdc8 --- /dev/null +++ b/src/utils/method_interface.ts @@ -0,0 +1,153 @@ +import { filterMethodsByApplicationParameters } from "@exabyte-io/application-flavors.js/lib/js/methods"; +import { + ApplicationSchemaBase, + BaseMethod, + CategorizedMethod, + CategorizedModel, + LegacyMethodLocalorbital, + LegacyMethodPseudopotential, + LegacyMethodRegression, + LegacyMethodUnknown, + UnitMethodPseudopotential, + UnitMethodRegression, +} from "@exabyte-io/code.js/dist/types"; + +import { allMethods as categorizedMethodList } from "../data/method_list"; +import { LocalOrbitalMethodConfig, UnknownMethodConfig } from "../default_methods"; +import { filterMethodsByModel } from "../filter"; +import { safelyGetSlug } from "./slugifiedEntry"; + +/** + * The method interface converts between the legacy method data structure (type, subtype) + * and the categorized method data structure (units with tier1, tier2, ...). + */ +export class MethodInterface { + static convertToSimple(cm: CategorizedMethod | undefined): BaseMethod { + if (!cm) return this.convertUnknownToSimple(); + const pspUnits = cm.units.filter((u) => u.categories.type === "psp"); + const aoUnit = cm.units.find((u) => u.categories.type === "ao"); + const reUnit = cm.units.find( + (u) => u.name && u.name.includes("regression"), + ) as UnitMethodRegression; + if (pspUnits.length) return this.convertPspUnitsToSimple(pspUnits); + if (aoUnit) return this.convertAoUnitToSimple(); + if (reUnit) return this.convertRegressionUnitToSimple(reUnit); + return this.convertRegressionUnitToSimple(reUnit); + } + + static convertUnknownToSimple(): LegacyMethodUnknown { + // @ts-ignore todo: move default_methods to TS + return UnknownMethodConfig; + } + + static convertPspUnitsToSimple( + cm: UnitMethodPseudopotential[], + ): LegacyMethodUnknown | LegacyMethodPseudopotential { + const [firstUnit, ...otherUnits] = cm; + if (!firstUnit || !firstUnit.categories?.subtype) return this.convertUnknownToSimple(); + const subtype = otherUnits?.length ? "any" : firstUnit.categories.subtype; + return { + type: "pseudopotential", + subtype, + } as LegacyMethodPseudopotential; + } + + static convertAoUnitToSimple(): LegacyMethodLocalorbital { + // @ts-ignore todo: move default_methods to TS + return LocalOrbitalMethodConfig; + } + + static convertRegressionUnitToSimple(cm: UnitMethodRegression): LegacyMethodRegression { + const type = cm.categories.type || "linear"; + const subtype = cm.categories.subtype || "least_squares"; + return { + type: safelyGetSlug(type) as "linear" | "kernel_ridge", + subtype: safelyGetSlug(subtype) as "least_squares" | "ridge", + data: cm.data, + precision: cm.precision, + }; + } + + static convertToCategorized(sm?: BaseMethod): CategorizedMethod | undefined { + switch (sm?.type) { + case "pseudopotential": + return this.convertPspToCategorized(sm as LegacyMethodPseudopotential); + case "localorbital": + return this.convertAoToCategorized(); + case "linear": + return this.convertRegressionToCategorized(sm as LegacyMethodRegression); + case "kernel_ridge": + return this.convertRegressionToCategorized(sm as LegacyMethodRegression); + default: + return undefined; + } + } + + static convertPspToCategorized(sm: LegacyMethodPseudopotential): CategorizedMethod { + // TODO: support other PSP methods, e.g. PSP + conjugate gradient + const subtype = safelyGetSlug(sm.subtype); + // the "any" subtype is equivalent to the method representing all planewave-pseudopotential + // methods. All other subtypes are equivalent to using a specific PW-PSP method. + const path = + subtype === "any" + ? "/qm/wf/none/psp/us::/qm/wf/none/psp/nc::/qm/wf/none/psp/paw::/qm/wf/none/pw/none" + : `/qm/wf/none/smearing/gaussian::/linalg/diag/none/davidson/none::/qm/wf/none/psp/${subtype}::/qm/wf/none/pw/none`; + + return categorizedMethodList.find((catMethod) => { + return catMethod.path === path; + }) as CategorizedMethod; + } + + static convertAoToCategorized(): CategorizedMethod { + // TODO: support other localorbital methods + const path = "/qm/wf/none/ao/pople?basisSlug=6-31G"; + return categorizedMethodList.find((cm) => cm.path === path) as CategorizedMethod; + } + + static convertRegressionToCategorized(sm: LegacyMethodRegression): CategorizedMethod { + const type = safelyGetSlug(sm.type); + const subtype = safelyGetSlug(sm.subtype); + const { precision, data } = sm; + const path = `/none/none/none/${type}/${subtype}`; + const method = categorizedMethodList.find((cm) => cm.path === path) as CategorizedMethod; + Object.assign(method.units[0], { precision, data }); + return method; + } + + static filterCategorizedMethods(params?: { + model?: CategorizedModel; + application?: ApplicationSchemaBase; + }): CategorizedMethod[] { + let filteredMethods = categorizedMethodList; + if (!params) return filteredMethods; + const { model, application } = params; + if (model) { + // @ts-ignore todo: sort out types of filter function + filteredMethods = filterMethodsByModel({ + // @ts-ignore + methodList: filteredMethods, + model, + }); + } + if (application) { + // @ts-ignore todo: sort out types of filter function + filteredMethods = filterMethodsByApplicationParameters({ + methodList: filteredMethods, + appName: application?.name, + version: application?.version, + build: application?.build, + }); + } + return filteredMethods; + } + + static filterLegacyMethods(params?: { + model?: CategorizedModel; + application?: ApplicationSchemaBase; + }): BaseMethod[] { + let _params = params; + if (!params) _params = {}; + const categorizedMethods = this.filterCategorizedMethods(params); + return categorizedMethods.map((cm) => this.convertToSimple(cm)); + } +} diff --git a/src/utils/model_interface.ts b/src/utils/model_interface.ts new file mode 100644 index 0000000..3bcec7e --- /dev/null +++ b/src/utils/model_interface.ts @@ -0,0 +1,126 @@ +import { filterModelsByApplicationParameters } from "@exabyte-io/application-flavors.js/lib/js/models"; +import { + ApplicationSchemaBase, + BaseModel, + CategorizedModel, + LegacyModelDensityFunctionalTheory, + LegacyModelRegression, + LegacyModelUnknown, + ModelGeneralizedGradientApproximation, + ModelHybridFunctional, + ModelLocalDensityApproximation, + ModelRegression, +} from "@exabyte-io/code.js/dist/types"; + +import { allModels as categorizedModelList } from "../data/model_list"; +import { safelyGetSlug, stringToSlugifiedEntry } from "./slugifiedEntry"; + +type SimpleModel = Omit; +type CategorizedModel_ = Omit; +type CategorizedDftModel = + | Omit + | Omit + | Omit; + +/** + * The model interface converts between the legacy model data structure (type, subtype, functional) + * and the categorized model data structure (tier1, tier2, ...). + */ +export class ModelInterface { + static convertToSimple(cm?: CategorizedModel_): SimpleModel { + if (!cm) return this.convertUnknownToSimple(); + + switch (cm.categories.tier3) { + case "dft": + return this.convertDftToSimple(cm); + case "ml": + return this.convertMlToSimple(); + default: + return this.convertUnknownToSimple(); + } + } + + private static functionalsPerSubtype(subtype: string): string[] { + return categorizedModelList.reduce((accumulator, item) => { + if (item.categories?.subtype === subtype && item.parameters.functional) { + accumulator.push(item.parameters.functional); + } + return accumulator; + }, []); + } + + static convertDftToSimple( + cm: CategorizedDftModel, + ): Omit { + if (!cm.categories?.subtype) return this.convertUnknownToSimple(); + const { subtype } = cm.categories; + const functional = cm.parameters?.functional; + return { + type: "dft", + subtype, + // @ts-ignore todo: cover undefined functional case + functional: stringToSlugifiedEntry(functional), + }; + } + + static convertMlToSimple(): Omit { + return { + type: "ml", + subtype: "re", + }; + } + + static convertUnknownToSimple(): Omit { + return { + type: "unknown", + subtype: "unknown", + }; + } + + static convertToCategorized(sm?: SimpleModel): CategorizedModel_ | undefined { + switch (sm?.type) { + case "dft": + return this.convertDftToCategorized(sm as LegacyModelDensityFunctionalTheory); + case "ml": + return this.convertMlToCategorized(); + case "unknown": + return undefined; + default: + return undefined; + } + } + + static convertDftToCategorized(sm: LegacyModelDensityFunctionalTheory): CategorizedDftModel { + const { subtype, functional: functionalStringOrObject } = sm; + let functional: string; + if (!functionalStringOrObject) { + [functional] = this.functionalsPerSubtype(subtype); + } else { + functional = safelyGetSlug(functionalStringOrObject); + } + // TODO: cover other parameter combinations, e.g. functional + spin-orbit + const path = `/pb/qm/dft/ksdft/${subtype}?functional=${functional}`; + return categorizedModelList.find((cm) => cm.path === path) as CategorizedDftModel; + } + + static convertMlToCategorized(): Omit { + // TODO: allow other ML types + const path = "/st/det/ml/re/none"; + // @ts-ignore todo: adjust ESSE schemas + return categorizedModelList.find((cm) => cm.path === path); + } + + static filterCategorizedModels(application?: ApplicationSchemaBase): CategorizedModel_[] { + // @ts-ignore todo: adjust type of model list + if (!application) return categorizedModelList; + const filteredModels = filterModelsByApplicationParameters({ + modelList: categorizedModelList, + appName: application?.name, + version: application?.version, + build: application?.build, + }); + + // @ts-ignore todo: adjust type of model list + return filteredModels; + } +} diff --git a/src/utils/slugifiedEntry.ts b/src/utils/slugifiedEntry.ts new file mode 100644 index 0000000..d84d2b2 --- /dev/null +++ b/src/utils/slugifiedEntry.ts @@ -0,0 +1,17 @@ +import { SlugifiedEntry } from "@exabyte-io/code.js/src/types"; + +export function slugifiedEntryToString(entry: SlugifiedEntry): string { + return entry.slug; +} + +export function stringToSlugifiedEntry(slug: string, name?: string): SlugifiedEntry { + const _name = !name ? slug : name; + return { + name: _name, + slug, + }; +} + +export function safelyGetSlug(slugObj: SlugifiedEntry | string): string { + return typeof slugObj === "string" ? slugObj : slugifiedEntryToString(slugObj); +} diff --git a/tests/dft_model.test.ts b/tests/dft_model.test.ts new file mode 100644 index 0000000..181482a --- /dev/null +++ b/tests/dft_model.test.ts @@ -0,0 +1,66 @@ +import { expect } from "chai"; + +import { DFTModelConfig } from "../src/default_models"; +import { DFTModel } from "../src/models/dft"; +import { ModelFactory } from "../src/models/factory"; + +describe("DFTModel", () => { + it("should have a default functional", () => { + const config = { type: "dft", subtype: "lda" }; + const model = new DFTModel(config); + expect(model.defaultFunctional.slug).to.be.equal("pz"); + }); + + it("can be created from the factory", () => { + const config = { type: "dft", subtype: "lda", functional: "pz" }; + const model = ModelFactory.create(config) as DFTModel; + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("lda"); + expect(model.functional?.slug).to.be.equal("pz"); + }); + + it("can be created from the factory with incomplete config", () => { + const config = { type: "dft" }; + const model = ModelFactory.create(config) as DFTModel; + expect(model.functional?.slug).to.be.equal("pbe"); + }); + + it("can be created from the factory given an application", () => { + const config = { + application: { + name: "espresso", + version: "6.3", + build: "Default", + }, + otherProperty: 42, + }; + const model = ModelFactory.createFromApplication(config); + expect(model).to.be.instanceof(DFTModel); + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("gga"); + // @ts-ignore + expect(model.functional?.slug).to.be.equal("pbe"); + expect(model._json.otherProperty).to.be.equal(42); + expect(model.method.type).to.be.equal("pseudopotential"); + }); + + it("can be created from default model config", () => { + const model = ModelFactory.create(DFTModelConfig); + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("gga"); + // @ts-ignore + expect(model.functional.slug).to.be.equal("pbe"); + }); + + it("creates the group slug 'qe:dft:gga:pbe' for DFT GGA", () => { + const application = { + name: "espresso", + shortName: "qe", + version: "6.3", + build: "Default", + }; + const model = ModelFactory.createFromApplication({ application }); + const expectedGroupSlug = "qe:dft:gga:pbe"; + expect(model.groupSlug).to.be.equal(expectedGroupSlug); + }); +}); diff --git a/tests/filter.test.js b/tests/filter.test.js index 7b910a1..c87714b 100644 --- a/tests/filter.test.js +++ b/tests/filter.test.js @@ -1,6 +1,6 @@ import { expect } from "chai"; -import { filterMethodsByModel } from "../src/tree"; +import { filterMethodsByModel } from "../src/filter"; describe("model-method filter", () => { const methodConfigs = [ diff --git a/tests/model.test.js b/tests/model.test.js deleted file mode 100644 index 920fa0c..0000000 --- a/tests/model.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { expect } from "chai"; - -import { Model } from "../src/model"; - -describe("Model", () => { - const obj = { type: "dft" }; - - it("can be created", () => { - const app = new Model(obj); - expect(app.type).to.equal("dft"); - }); -}); diff --git a/tests/model.test.ts b/tests/model.test.ts new file mode 100644 index 0000000..60a1998 --- /dev/null +++ b/tests/model.test.ts @@ -0,0 +1,61 @@ +import { expect } from "chai"; + +import { Model } from "../src/model"; +import { ModelFactory } from "../src/models/factory"; + +describe("Model", () => { + const obj = { type: "dft" }; + + it("can be created", () => { + // @ts-ignore + const model = new Model(obj); + expect(model.type).to.equal("dft"); + }); + + it("can be created from the model factory", () => { + const model = ModelFactory.create(obj); + expect(model.type).to.be.equal("dft"); + }); + + it("should have 'unknown' model as default if type is 'unknown'", () => { + const config = { type: "unknown" }; + const model = ModelFactory.create(config); + expect(model.type).to.be.equal("unknown"); + expect(model.subtype).to.be.equal("unknown"); + expect(model._defaultCategorized).to.be.undefined; + }); + + it("default model for espresso is DFT PBE", () => { + const application = { name: "espresso", version: "6.3", build: "Default" }; + const model = ModelFactory.createFromApplication({ application }); + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("gga"); + // @ts-ignore + expect(model.functional.slug).to.be.equal("pbe"); + }); + + it("default model for vasp is DFT PBE", () => { + const application = { name: "vasp", version: "5.4.4", build: "Default" }; + const model = ModelFactory.createFromApplication({ application }); + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("gga"); + // @ts-ignore + expect(model.functional.slug).to.be.equal("pbe"); + }); + + it("default model for nwchem is DFT B3LYP", () => { + const application = { name: "nwchem", version: "6.6", build: "Default" }; + const model = ModelFactory.createFromApplication({ application }); + expect(model.type).to.be.equal("dft"); + expect(model.subtype).to.be.equal("hybrid"); + // @ts-ignore + expect(model.functional.slug).to.be.equal("b3lyp"); + }); + + it("default model for exabyteml is regression", () => { + const application = { name: "exabyteml", version: "0.2.0", build: "Default" }; + const model = ModelFactory.createFromApplication({ application }); + expect(model.type).to.be.equal("ml"); + expect(model.subtype).to.be.equal("re"); + }); +}); diff --git a/tests/setup.js b/tests/setup.js deleted file mode 100644 index c693a94..0000000 --- a/tests/setup.js +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line no-unused-vars -import chai from "chai"; diff --git a/tests/tree.test.ts b/tests/tree.test.ts new file mode 100644 index 0000000..d399bde --- /dev/null +++ b/tests/tree.test.ts @@ -0,0 +1,30 @@ +import { expect } from "chai"; + +import { + getDFTApproximations, + getDFTFunctionalsByApproximation, + getPseudopotentialTypes, +} from "../src/tree"; + +describe("tree", () => { + it("can get a list of available DFT functionals", () => { + const approximations = getDFTApproximations(); + const supportedApproximations = ["lda", "gga", "hybrid"]; + expect(approximations).to.have.members(supportedApproximations); + }); + + it("can get a list of functions by approximation", () => { + const ldaFunctionals = getDFTFunctionalsByApproximation("lda"); + expect(ldaFunctionals).to.include("pz"); + const ggaFunctionals = getDFTFunctionalsByApproximation("gga"); + expect(ggaFunctionals).to.include("pbe"); + const hybridFunctionals = getDFTFunctionalsByApproximation("hybrid"); + expect(hybridFunctionals).to.include("hse06"); + }); + + it("can get a list of pseudopotential types", () => { + const ppTypes = getPseudopotentialTypes(); + const supportedPseudoTypes = ["paw", "us", "nc", "any"]; + expect(ppTypes).to.have.members(supportedPseudoTypes); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f28e65f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2018", + "jsx": "react", + "lib": ["ES2019", "dom"], + "allowJs": true, + "module": "commonjs", + "moduleResolution": "Node", + "declaration": true, + "outDir": "./dist", + "noEmitOnError": false, + "isolatedModules": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "types": ["mocha", "node"], + "rootDir": "./src", + "baseUrl": "./" + }, + "include": [ + "./src" + ], + "exclude": [ + "node_modules", + "dist" + ], + "ts-node": { + "files": true, + "compilerOptions": {} + }, +}