From d696215d08f5f4c2215f65a7fbca6e273f84f0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wieland=20Sch=C3=B6bl?= Date: Wed, 30 Jun 2021 13:53:44 +0200 Subject: [PATCH] refactor: replace TSLint with ESLint --- .eslintignore | 1 + .eslintrc.json | 120 + .gitlab-ci.yml | 5 + angular.json | 49 +- package-lock.json | 3486 ++++++++++++----- package.json | 18 +- .../_helpers/data/resources/test-resources.ts | 2 +- src/app/_helpers/data/sample-configuration.ts | 13 +- src/app/_helpers/data/sample-facets.ts | 103 +- src/app/_helpers/data/sample-things.ts | 32 +- src/app/_helpers/errors.ts | 5 +- src/app/_helpers/fake-backend.interceptor.ts | 18 +- src/app/_helpers/fakesearch/filters.ts | 96 +- src/app/_helpers/ts-logger.ts | 2 +- src/app/app-routing.module.ts | 4 +- src/app/app.component.spec.ts | 29 +- src/app/app.component.ts | 66 +- src/app/app.module.ts | 57 +- src/app/modules/config/config.module.ts | 9 +- .../modules/config/config.provider.spec.ts | 128 +- src/app/modules/config/config.provider.ts | 27 +- src/app/modules/config/errors.ts | 14 +- .../data/chips/action-chip-list.component.ts | 8 +- .../modules/data/chips/action-chip-list.html | 10 +- .../data/chips/add-event-popover.component.ts | 48 +- .../modules/data/chips/add-event-popover.html | 58 +- .../data/add-event-action-chip.component.ts | 75 +- .../chips/data/add-event-action-chip.html | 13 +- .../data/locate-action-chip.component.ts | 3 +- .../data/chips/data/locate-action-chip.html | 8 +- .../modules/data/data-facets.provider.spec.ts | 90 +- src/app/modules/data/data-facets.provider.ts | 71 +- src/app/modules/data/data-icon.pipe.ts | 8 +- src/app/modules/data/data-routing.module.ts | 8 +- src/app/modules/data/data-routing.service.ts | 2 +- src/app/modules/data/data.module.ts | 100 +- src/app/modules/data/data.provider.spec.ts | 107 +- src/app/modules/data/data.provider.ts | 104 +- .../detail/data-detail-content.component.ts | 1 - .../data/detail/data-detail-content.html | 83 +- .../data/detail/data-detail.component.spec.ts | 43 +- .../data/detail/data-detail.component.ts | 28 +- src/app/modules/data/detail/data-detail.html | 36 +- .../modules/data/elements/address-detail.html | 42 +- .../elements/long-inline-text.component.ts | 3 +- .../data/elements/long-inline-text.html | 4 +- .../data/elements/offers-detail.component.ts | 6 +- .../modules/data/elements/offers-detail.html | 33 +- .../data/elements/offers-in-list.component.ts | 5 +- .../modules/data/elements/offers-in-list.html | 7 +- .../modules/data/elements/origin-detail.html | 58 +- .../modules/data/elements/origin-in-list.html | 4 +- .../data/elements/simple-card.component.ts | 9 +- .../modules/data/elements/simple-card.html | 17 +- .../elements/skeleton-list-item.component.ts | 3 +- .../data/elements/skeleton-list-item.html | 10 +- .../skeleton-segment-button.component.ts | 3 +- .../elements/skeleton-segment-button.html | 3 +- .../skeleton-simple-card.component.ts | 3 +- .../data/elements/skeleton-simple-card.html | 2 +- .../data/list/data-list-item.component.ts | 2 +- src/app/modules/data/list/data-list-item.html | 106 +- .../data/list/data-list.component.spec.ts | 9 +- .../modules/data/list/data-list.component.ts | 36 +- src/app/modules/data/list/data-list.html | 28 +- .../data/list/food-data-list.component.ts | 10 +- .../data/list/search-page.component.ts | 85 +- src/app/modules/data/list/search-page.html | 13 +- .../data/stapps-web-http-client.provider.ts | 28 +- .../types/article/article-detail-content.html | 18 +- .../article/article-list-item.component.ts | 13 +- .../data/types/article/article-list-item.html | 9 +- .../types/catalog/catalog-detail-content.html | 5 +- .../catalog/catalog-list-item.component.ts | 13 +- .../data/types/catalog/catalog-list-item.html | 9 +- .../date-series-detail-content.html | 28 +- .../date-series-list-item.component.ts | 13 +- .../date-series/date-series-list-item.html | 22 +- .../data/types/dish/dish-detail-content.html | 68 +- .../types/dish/dish-list-item.component.ts | 11 +- .../data/types/dish/dish-list-item.html | 11 +- .../event/event-detail-content.component.ts | 11 +- .../types/event/event-detail-content.html | 48 +- .../types/event/event-list-item.component.ts | 12 +- .../data/types/event/event-list-item.html | 16 +- .../favorite/favorite-list-item.component.ts | 13 +- .../types/favorite/favorite-list-item.html | 16 +- .../types/message/message-detail-content.html | 28 +- .../message/message-list-item.component.ts | 13 +- .../data/types/message/message-list-item.html | 9 +- .../organization-detail-content.html | 12 +- .../organization-list-item.component.ts | 13 +- .../organization/organization-list-item.html | 11 +- .../types/person/person-detail-content.html | 97 +- .../person/person-list-item.component.ts | 13 +- .../data/types/person/person-list-item.html | 24 +- .../place/place-detail-content.component.ts | 28 +- .../types/place/place-detail-content.html | 31 +- .../types/place/place-list-item.component.ts | 13 +- .../data/types/place/place-list-item.html | 11 +- .../mensa/place-mensa-detail.component.ts | 4 +- .../special/mensa/place-mensa-service.ts | 31 +- .../place/special/mensa/place-mensa.html | 20 +- .../semester/semester-detail-content.html | 16 +- .../semester/semester-list-item.component.ts | 12 +- .../types/semester/semester-list-item.html | 9 +- .../types/video/video-detail-content.html | 24 +- .../types/video/video-list-item.component.ts | 12 +- .../data/types/video/video-list-item.html | 16 +- .../context/context-menu.component.spec.ts | 187 +- .../menu/context/context-menu.component.ts | 73 +- .../modules/menu/context/context-menu.html | 129 +- .../menu/context/context-menu.service.spec.ts | 81 +- .../menu/context/context-menu.service.ts | 109 +- src/app/modules/menu/context/context-type.ts | 2 - src/app/modules/menu/menu.module.ts | 18 +- .../menu/navigation/navigation.component.ts | 23 +- .../modules/menu/navigation/navigation.html | 9 +- src/app/modules/news/news.module.ts | 22 +- src/app/modules/news/news.provider.ts | 16 +- .../modules/news/page/news-item.component.ts | 1 - src/app/modules/news/page/news-item.html | 40 +- .../modules/news/page/news-page.component.ts | 11 +- src/app/modules/news/page/news-page.html | 9 +- .../news/page/skeleton-news-item.component.ts | 3 +- .../modules/news/page/skeleton-news-item.html | 18 +- .../settings/item/settings-item.component.ts | 40 +- .../modules/settings/item/settings-item.html | 80 +- .../settings/page/settings-page.component.ts | 52 +- .../modules/settings/page/settings-page.html | 31 +- src/app/modules/settings/settings.module.ts | 18 +- .../settings/settings.provider.spec.ts | 173 +- src/app/modules/settings/settings.provider.ts | 149 +- src/app/modules/storage/storage.module.ts | 8 +- .../modules/storage/storage.provider.spec.ts | 50 +- src/app/modules/storage/storage.provider.ts | 15 +- src/app/translation/common-string-pipes.ts | 45 +- src/app/translation/thing-translate.module.ts | 51 +- src/app/translation/thing-translate.parser.ts | 19 +- src/app/translation/thing-translate.pipe.ts | 57 +- .../translation/thing-translate.service.ts | 73 +- src/environments/environment.prod.ts | 1 + src/index.html | 36 +- src/main.ts | 2 +- src/polyfills.ts | 2 +- src/test.ts | 14 +- tslint.json | 8 - 147 files changed, 5471 insertions(+), 2704 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json delete mode 100644 tslint.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..15298306 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/app/_helpers/data diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..d797c8e4 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,120 @@ +{ + "root": true, + "ignorePatterns": [ + "projects/**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "project": [ + "tsconfig.json", + "e2e/tsconfig.e2e.json" + ], + "createDefaultProgram": true + }, + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates", + "plugin:jsdoc/recommended", + "plugin:unicorn/recommended" + ], + "plugins": [ + "eslint-plugin-unicorn", + "eslint-plugin-jsdoc", + "prettier" + ], + "settings": { + "jsdoc": { + "mode": "typescript" + } + }, + "rules": { + "unicorn/filename-case": "error", + "unicorn/no-array-callback-reference": "off", + "unicorn/prevent-abbreviations": [ + "error", + { + "replacements": { + "ref": false, + "i": false + } + } + ], + "unicorn/no-nested-ternary": "off", + "unicorn/better-regex": "off", + + "jsdoc/no-types": "error", + "jsdoc/require-param": "off", + "jsdoc/require-param-description": "error", + "jsdoc/check-param-names": "error", + "jsdoc/require-returns": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-returns-type": "off", + + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "args": "after-used", + "argsIgnorePattern": "^_" + } + ], + "@typescript-eslint/lines-between-class-members": [ + "error", + "always" + ], + "@typescript-eslint/no-explicit-any": "error", + "@angular-eslint/use-lifecycle-interface": "error", + + "prettier/prettier": [ + "error", + { + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "consistent", + "trailingComma": "all", + "bracketSpacing": false, + "arrowParens": "avoid", + "endOfLine": "lf" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "extends": [ + "plugin:prettier/recommended", + "plugin:@angular-eslint/template/recommended" + ], + "rules": { + "prettier/prettier": [ + "error", + { + "parser": "angular", + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "consistent", + "trailingComma": "all", + "bracketSpacing": false, + "arrowParens": "avoid", + "endOfLine": "lf" + } + ] + } + } + ] +} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 40bb7b56..1fe86b81 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -40,6 +40,11 @@ build: paths: - www +lint: + stage: build + script: + - npm run lint + unit: stage: test script: diff --git a/angular.json b/angular.json index 1f3a648d..6f6f944a 100644 --- a/angular.json +++ b/angular.json @@ -20,7 +20,8 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "src/tsconfig.app.json", - "assets": [{ + "assets": [ + { "glob": "**/*", "input": "src/assets", "output": "assets" @@ -36,7 +37,8 @@ "output": "./svg" } ], - "styles": [{ + "styles": [ + { "input": "src/theme/variables.scss" }, { @@ -47,10 +49,12 @@ }, "configurations": { "production": { - "fileReplacements": [{ - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" - }], + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], "optimization": true, "outputHashing": "all", "sourceMap": false, @@ -84,8 +88,8 @@ "fake": { "fileReplacements": [ { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.fake.ts" + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.fake.ts" } ], "optimization": true, @@ -144,7 +148,8 @@ "karmaConfig": "src/karma.conf.js", "styles": [], "scripts": [], - "assets": [{ + "assets": [ + { "glob": "favicon.ico", "input": "src/", "output": "/" @@ -164,10 +169,20 @@ } }, "lint": { - "builder": "@angular-devkit/build-angular:tslint", + "builder": "@angular-eslint/builder:lint", "options": { - "tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"], - "exclude": ["**/node_modules/**"] + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"], + "eslintConfig": ".eslintrc.json", + "ignorePath": ".eslintignore" + } + }, + "lint:fix": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"], + "fix": true, + "eslintConfig": ".eslintrc.json", + "ignorePath": ".eslintignore" } }, "ionic-cordova-build": { @@ -213,17 +228,19 @@ } }, "lint": { - "builder": "@angular-devkit/build-angular:tslint", + "builder": "@angular-eslint/builder:lint", "options": { - "tsConfig": "e2e/tsconfig.e2e.json", - "exclude": ["**/node_modules/**"] + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"], + "eslintConfig": ".eslintrc.json", + "ignorePath": ".eslintignore" } } } } }, "cli": { - "defaultCollection": "@ionic/angular-toolkit" + "defaultCollection": "@ionic/angular-toolkit", + "analytics": false }, "schematics": { "@ionic/angular-toolkit:component": { diff --git a/package-lock.json b/package-lock.json index b194f3af..51d76f57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -341,6 +341,200 @@ } } }, + "@angular-eslint/builder": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-12.2.0.tgz", + "integrity": "sha512-AlVe8VcJr9d/BohtHvAyxn3pyVGE9o0g3BqnmthQl6+g5G/WZ5SH5CyQlPF6ycyMbxuHuICgVBbIK9jedZxM1A==", + "dev": true + }, + "@angular-eslint/eslint-plugin": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-12.2.0.tgz", + "integrity": "sha512-VKeRAql5AzhMrFFP865FjwkheUSsSGKpdTCa8jYZXZkmsXQnqta+omexBqvKT3CSYAEjSN3FLpQyqSXWWZysWg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.23.0" + } + }, + "@angular-eslint/eslint-plugin-template": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-12.2.0.tgz", + "integrity": "sha512-DLZiv6x2ZF0OJ3a3KR/APQkhA3HZqebdVCJd29EzdF3qnZGQybNV5GfFONf67vDkm/wA/UaF8rO4Rc8WQv2PHQ==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.23.0", + "aria-query": "^4.2.2", + "axobject-query": "^2.2.0" + } + }, + "@angular-eslint/schematics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-1.2.0.tgz", + "integrity": "sha512-F0Mb6XyLWGmmtov5kv/BHvt22Uo/FuD4y2WhO7NUA9rZRJd+anmyHCkC9HXmNKUuLQIUKjJ4DJgsmD0Kh0Hr2g==", + "dev": true, + "requires": { + "@angular-eslint/eslint-plugin": "1.2.0", + "@angular-eslint/eslint-plugin-template": "1.2.0", + "strip-json-comments": "3.1.1", + "tslint-to-eslint-config": "2.0.1" + }, + "dependencies": { + "@angular-eslint/eslint-plugin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-1.2.0.tgz", + "integrity": "sha512-HxSDdAS2/lbwYBJmRVRKlx5wjiKdeBPl7JJlciwhrP7QR01a66AWun+fW1ZpMnnqivkF+D5sISsoedRLthRcwA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.3.0" + } + }, + "@angular-eslint/eslint-plugin-template": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-1.2.0.tgz", + "integrity": "sha512-Oi/y+N/FETuyhbVuFxbkCqSfLo61CAvIPwnQQCfDku/IsCSTI1SjW+B2xO9thDI5po7t5V+3n26uMLQsWNZmlw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.3.0", + "aria-query": "^4.2.2", + "axobject-query": "^2.2.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.3.0.tgz", + "integrity": "sha512-cmmIK8shn3mxmhpKfzMMywqiEheyfXLV/+yPDnOTvQX/ztngx7Lg/OD26J8gTZfkLKUmaEBxO2jYP3keV7h2OQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.3.0", + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/typescript-estree": "4.3.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.3.0.tgz", + "integrity": "sha512-cTeyP5SCNE8QBRfc+Lgh4Xpzje46kNUhXYfc3pQWmJif92sjrFuHT9hH4rtOkDTo/si9Klw53yIr+djqGZS1ig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0" + } + }, + "@typescript-eslint/types": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.3.0.tgz", + "integrity": "sha512-Cx9TpRvlRjOppGsU6Y6KcJnUDOelja2NNCX6AZwtVHRzaJkdytJWMuYiqi8mS35MRNA3cJSwDzXePfmhU6TANw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.3.0.tgz", + "integrity": "sha512-ZAI7xjkl+oFdLV/COEz2tAbQbR3XfgqHEGy0rlUXzfGQic6EBCR4s2+WS3cmTPG69aaZckEucBoTxW9PhzHxxw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.3.0.tgz", + "integrity": "sha512-xZxkuR7XLM6RhvLkgv9yYlTcBHnTULzfnw4i6+z2TGBLy9yljAypQaZl9c3zFvy7PNI7fYWyvKYtohyF8au3cw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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" + } + } + } + }, + "@angular-eslint/template-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-1.2.0.tgz", + "integrity": "sha512-EfNJh0nFGJInHa2ccVw8Eb9ujWoUAwaQMCi9GppzYrqhSPc0YZqdQg4eIW2AlZs1giHD2Ko/V1rphzw+9gisCw==", + "dev": true, + "requires": { + "eslint-scope": "^5.1.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + } + } + }, "@angular/cdk": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.0.0.tgz", @@ -351,9 +545,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" } } }, @@ -621,17 +815,17 @@ "integrity": "sha512-+qCaXa9y0nsRhzjAYBqmGoQ2YkrdXgftZwuFDf6t4qEi30EXa0oS97KrlFq0M5GKdLIDGrbUm9PcdHSTOI+ZhA==" }, "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", "requires": { - "@babel/highlight": "^7.12.13" + "@babel/highlight": "^7.14.5" } }, "@babel/compat-data": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz", - "integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", "dev": true }, "@babel/core": { @@ -659,9 +853,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -687,6 +881,35 @@ } } }, + "@babel/eslint-parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.14.7.tgz", + "integrity": "sha512-6WPwZqO5priAGIwV6msJcdc9TsEPzYeYdS/Xuoap+/ihkgN6dzHp2bcAAwyWZ5bLzk0vvjDmKvRwkqNaiJ8BiQ==", + "dev": true, + "requires": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/generator": { "version": "7.9.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.3.tgz", @@ -708,33 +931,33 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.5" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz", - "integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-compilation-targets": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", - "integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.15", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.14.5", + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", "semver": "^6.3.0" }, "dependencies": { @@ -747,245 +970,244 @@ } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.3.tgz", - "integrity": "sha512-JIB2+XJrb7v3zceV2XzDhGIB902CmKGSpSl4q2C6agU9SNLG/2V1RtFRGPG1Ajh9STj3+q6zJMOC+N/pp2P9DA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-annotate-as-pure": "^7.14.5", "regexpu-core": "^4.7.1" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", - "integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", "dev": true, "requires": { - "@babel/types": "^7.13.0" + "@babel/types": "^7.14.5" } }, "@babel/helper-function-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", - "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.14.2" + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" }, "dependencies": { "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" } } } }, "@babel/helper-get-function-arity": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", - "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.5" } }, "@babel/helper-hoist-variables": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz", - "integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", "dev": true, "requires": { - "@babel/traverse": "^7.13.15", - "@babel/types": "^7.13.16" + "@babel/types": "^7.14.5" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", - "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", "dev": true, "requires": { - "@babel/types": "^7.13.12" + "@babel/types": "^7.14.5" } }, "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", "dev": true, "requires": { - "@babel/types": "^7.13.12" + "@babel/types": "^7.14.5" } }, "@babel/helper-module-transforms": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz", - "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-simple-access": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.2" + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" }, "dependencies": { "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" } } } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", - "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.5" } }, "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz", - "integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-wrap-function": "^7.13.0", - "@babel/types": "^7.13.0" + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-replace-supers": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.3.tgz", - "integrity": "sha512-Rlh8qEWZSTfdz+tgNV/N4gz1a0TMNwCUcENhMjHTHKp3LseYH5Jha0NSlyTQWMnjbYcwFt+bqAMqSLHVXkQ6UA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.2" + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-simple-access": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", - "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", "dev": true, "requires": { - "@babel/types": "^7.13.12" + "@babel/types": "^7.14.5" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", - "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.14.5" } }, "@babel/helper-split-export-declaration": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", - "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.5" } }, "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==" }, "@babel/helper-validator-option": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", - "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz", - "integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.0" + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" }, "dependencies": { "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" } } } }, "@babel/helpers": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", - "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", "dev": true, "requires": { - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" }, "dependencies": { "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" } } } }, "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "requires": { - "@babel/helper-validator-identifier": "^7.14.0", + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -1037,104 +1259,104 @@ } }, "@babel/parser": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", - "integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.2.tgz", - "integrity": "sha512-b1AM4F6fwck4N8ItZ/AtC4FP/cqZqmKRQ4FaTDutwSYyjuhtvsGEMLK4N/ztV/ImP40BjIDyMgBQAeAMsQYVFQ==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-remap-async-to-generator": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.2.tgz", - "integrity": "sha512-oxVQZIWFh91vuNEMKltqNsKLFWkOIyJc95k2Gv9lWVyDfPUQGSSlbDEgWuJUU1afGE9WwlzpucMZ3yDRHIItkA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.2.tgz", - "integrity": "sha512-w2DtsfXBBJddJacXMBhElGEYqCZQqN99Se1qeYn8DVLB33owlrlLftIbMzn5nz1OITfDVknXF433tBrLEAOEjA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz", - "integrity": "sha512-ebR0zU9OvI2N4qiAC38KIAK75KItpIPTpAtd2r4OZmMFeKbKJpUFLYP2EuDut82+BmYi8sz42B+TfTptJ9iG5Q==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.2.tgz", - "integrity": "sha512-DcTQY9syxu9BpU3Uo94fjCB3LN9/hgPS8oUL7KrSW3bA2ePrKZZPJcc5y0hoJAM9dft3pGfErtEUvxXQcfLxUg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz", - "integrity": "sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.0", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/compat-data": "^7.14.7", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.14.2" + "@babel/plugin-transform-parameters": "^7.14.5" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.2.tgz", - "integrity": "sha512-XtkJsmJtBaUbOxZsNk0Fvrv8eiqgneug0A6aqLFZ4TSkar2L5dSXWcnUKHgmjJt49pyB/6ZHvkr3dPgl9MOWRQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz", - "integrity": "sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz", - "integrity": "sha512-XyJmZidNfofEkqFV5VC/bLabGmO5QzenPO/YOfGuEbgU+2sSwMmio3YLb4WtBgcmmdwZHyVyv8on77IUjQ5Gvg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-async-generators": { @@ -1210,315 +1432,315 @@ } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz", - "integrity": "sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz", - "integrity": "sha512-96lgJagobeVmazXFaDrbmCLQxBysKu7U6Do3mLsx27gf5Dk85ezysrs2BZUpXD703U/Su1xTBDxxar2oa4jAGg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.13.0.tgz", - "integrity": "sha512-3j6E004Dx0K3eGmhxVJxwwI89CTJrce7lg3UrtFuDAVQ/2+SJ/h/aSFOeE6/n0WB1GsOffsJp6MnPQNQ8nmwhg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-remap-async-to-generator": "^7.13.0" + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.13.tgz", - "integrity": "sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.2.tgz", - "integrity": "sha512-neZZcP19NugZZqNwMTH+KoBjx5WyvESPSIOQb4JHpfd+zPfqcH65RMu5xJju5+6q/Y2VzYrleQTr+b6METyyxg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.2.tgz", - "integrity": "sha512-7oafAVcucHquA/VZCsXv/gmuiHeYd64UJyyTYU+MPfNu0KeNlxw06IeENBO8bJjXVbolu+j1MM5aKQtH1OMCNg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.13.0.tgz", - "integrity": "sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-destructuring": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz", - "integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.13.tgz", - "integrity": "sha512-foDrozE65ZFdUC2OfgeOCrEPTxdB3yjqxpXh8CH+ipd9CHd4s/iq81kcUpyH8ACGNEPdFqbtzfgzbT/ZGlbDeQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.13.tgz", - "integrity": "sha512-NfADJiiHdhLBW3pulJlJI2NB0t4cci4WTZ8FtdIuNc2+8pslXdPtRRAEWqUY+m9kNOk2eRYbTAOipAxlrOcwwQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.13.tgz", - "integrity": "sha512-fbUelkM1apvqez/yYx1/oICVnGo2KM5s63mhGylrmXUxK/IAXSIf87QIxVfZldWf4QsOafY6vV3bX8aMHSvNrA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-for-of": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.13.0.tgz", - "integrity": "sha512-IHKT00mwUVYE0zzbkDgNRP6SRzvfGCYsOxIRz8KsiaaHCcT9BWIkO+H9QRJseHBLOGBZkHUdHiqj6r0POsdytg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.13.tgz", - "integrity": "sha512-6K7gZycG0cmIwwF7uMK/ZqeCikCGVBdyP2J5SKNCXO5EOHcqi+z7Jwf8AmyDNcBgxET8DrEtCt/mPKPyAzXyqQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.13.tgz", - "integrity": "sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.13.tgz", - "integrity": "sha512-kxLkOsg8yir4YeEPHLuO2tXP9R/gTjpuTOjshqSpELUN3ZAg2jfDnKUvzzJxObun38sw3wm4Uu69sX/zA7iRvg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.2.tgz", - "integrity": "sha512-hPC6XBswt8P3G2D1tSV2HzdKvkqOpmbyoy+g73JG0qlF/qx2y3KaMmXb1fLrpmWGLZYA0ojCvaHdzFWjlmV+Pw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.2", - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz", - "integrity": "sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz", - "integrity": "sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.13.0", - "@babel/helper-module-transforms": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz", - "integrity": "sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.13.tgz", - "integrity": "sha512-Xsm8P2hr5hAxyYblrfACXpQKdQbx4m2df9/ZZSQ8MAhsadw06+jW7s9zsSw6he+mJZXRlVMyEnVktJo4zjk1WA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.14.5" } }, "@babel/plugin-transform-new-target": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.13.tgz", - "integrity": "sha512-/KY2hbLxrG5GTQ9zzZSc3xWiOy379pIETEhbtzwZcw9rvuaVV4Fqy7BYGYOWZnaoXIQYbbJ0ziXLa/sKcGCYEQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-object-super": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz", - "integrity": "sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/helper-replace-supers": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" } }, "@babel/plugin-transform-parameters": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz", - "integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-property-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz", - "integrity": "sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-regenerator": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.13.15.tgz", - "integrity": "sha512-Bk9cOLSz8DiurcMETZ8E2YtIVJbFCPGW28DJWUakmyVWtQSm6Wsf0p4B4BfEr/eL2Nkhe/CICiUiMOCi1TPhuQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", "dev": true, "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.13.tgz", - "integrity": "sha512-xhUPzDXxZN1QfiOy/I5tyye+TRz6lA7z6xaT4CLOjPRMVg1ldRf0LHw0TDBpYL4vG78556WuHdyO9oi5UmzZBg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz", - "integrity": "sha512-xpL49pqPnLtf0tVluuqvzWIgLEhuPpZzvs2yabUHSKRNlN7ScYU7aMlmavOeyXJZKgZKQRBlh8rHbKiJDraTSw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-spread": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.13.0.tgz", - "integrity": "sha512-V6vkiXijjzYeFmQTr3dBxPtZYLPcUfY34DebOU27jIl2M/Y8Egm52Hw82CSjjPqd54GTlJs5x+CR7HeNr24ckg==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.13.tgz", - "integrity": "sha512-Jc3JSaaWT8+fr7GRvQP02fKDsYk4K/lYwWq38r/UGfaxo89ajud321NH28KRQ7xy1Ybc0VUE5Pz8psjNNDUglg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-template-literals": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.13.0.tgz", - "integrity": "sha512-d67umW6nlfmr1iehCcBv69eSUSySk1EsIS8aTDX4Xo9qajAh6mYtcl4kJrBkGXuxZPEgVr7RVfAvNW6YQkd4Mw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.13.tgz", - "integrity": "sha512-eKv/LmUJpMnu4npgfvs3LiHhJua5fo/CysENxa45YCQXZwKnGCQKAg87bvoqSW1fFT+HA32l03Qxsm8ouTY3ZQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.13.tgz", - "integrity": "sha512-mDRzSNY7/zopwisPZ5kM9XKCfhchqIYwAKRERtEnhYscZB79VRekuRSoYbN0+KVe3y8+q1h6A4svXtP7N+UoCA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/preset-env": { @@ -1619,13 +1841,23 @@ } }, "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", "requires": { "regenerator-runtime": "^0.13.4" } }, + "@babel/runtime-corejs3": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", + "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", + "dev": true, + "requires": { + "core-js-pure": "^3.15.0", + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", @@ -1638,36 +1870,37 @@ } }, "@babel/traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", - "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.2", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.2", - "@babel/types": "^7.14.2", + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.7", + "@babel/types": "^7.14.5", "debug": "^4.1.0", "globals": "^11.1.0" }, "dependencies": { "@babel/generator": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", - "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", "dev": true, "requires": { - "@babel/types": "^7.14.2", + "@babel/types": "^7.14.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -1688,12 +1921,12 @@ } }, "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.0", + "@babel/helper-validator-identifier": "^7.14.5", "to-fast-properties": "^2.0.0" } }, @@ -1834,6 +2067,12 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "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 } } }, @@ -1855,9 +2094,9 @@ "dev": true }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true } } @@ -1884,32 +2123,147 @@ "is-negated-glob": "^1.0.0" } }, + "@es-joy/jsdoccomment": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.8.0.tgz", + "integrity": "sha512-Xd3GzYsL2sz2pcdtYt5Q0Wz1ol/o9Nt2UQL4nFPDcaEomvPmwjJsbjkKx1SKhl2h3TgwazNBLdcNr2m0UiGiFA==", + "dev": true, + "requires": { + "comment-parser": "^1.1.5", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "1.0.4" + } + }, + "@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, "@hapi/hoek": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" }, "@hapi/topo": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", - "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "requires": { "@hapi/hoek": "^9.0.0" } }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true + }, "@ionic-native/core": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-5.29.0.tgz", "integrity": "sha512-dmS6rL38FAWCX9Xry2rtaMEe144MJgZ/8YVR5tVfWNSRmOOnDg+cZTYwt8Qeqm9ndqFBCjGh8PE7mteC8FvUGg==", "requires": { "@types/cordova": "^0.0.34" - }, - "dependencies": { - "@types/cordova": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", - "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" - } } }, "@ionic-native/geolocation": { @@ -1918,13 +2272,6 @@ "integrity": "sha512-hv8h7sgN57KDBl+hOWB/w2egrS7DEJJLmM098e+Rq/6PEKfV+Spx6fDgGaZvfppoKThayoL3enJoWd3NHcQeDQ==", "requires": { "@types/cordova": "^0.0.34" - }, - "dependencies": { - "@types/cordova": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", - "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" - } } }, "@ionic-native/network": { @@ -1933,13 +2280,6 @@ "integrity": "sha512-dSN7jaiXXgm8kVcvxcD39wWPFg2NujWTrEnj9Fq7Fx2aGKkxPkocNsxoy02aFVyBp1LQZvp+uiDNmVIVRjrA7A==", "requires": { "@types/cordova": "^0.0.34" - }, - "dependencies": { - "@types/cordova": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", - "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" - } } }, "@ionic-native/splash-screen": { @@ -1948,13 +2288,6 @@ "integrity": "sha512-F/AvowDaIwlb3+DcR10ezmaFQR7HyiSAu7R4Hf25HPU4PsqCuTezTARbEqa2xM5+5JkkIlIQKG/CPvipG4FV3w==", "requires": { "@types/cordova": "^0.0.34" - }, - "dependencies": { - "@types/cordova": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", - "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" - } } }, "@ionic-native/status-bar": { @@ -1963,13 +2296,6 @@ "integrity": "sha512-fv4mfH3Fb99fIEOtoxUFYvw+YW10Nk0lUCUkdGTX4LV8Big2o3TfEcUczGQOXJ28Wz1WrAuzh6l9A5JiK3umLw==", "requires": { "@types/cordova": "^0.0.34" - }, - "dependencies": { - "@types/cordova": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", - "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" - } } }, "@ionic/angular": { @@ -2103,9 +2429,9 @@ } }, "ws": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", - "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.2.tgz", + "integrity": "sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ==", "dev": true } } @@ -2121,9 +2447,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" } } }, @@ -2201,13 +2527,6 @@ "assert-plus": "^1.0.0", "extsprintf": "^1.4.0", "lodash": "^4.17.15" - }, - "dependencies": { - "extsprintf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz", - "integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=" - } } }, "@ngtools/webpack": { @@ -2281,25 +2600,25 @@ } }, "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "requires": { - "@nodelib/fs.stat": "2.0.4", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", "requires": { - "@nodelib/fs.scandir": "2.1.4", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, @@ -2355,11 +2674,6 @@ "version": "14.17.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.1.tgz", "integrity": "sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, @@ -2384,6 +2698,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.14.tgz", "integrity": "sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw==" }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2466,35 +2789,6 @@ } } }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2505,11 +2799,6 @@ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" - }, "got": { "version": "10.7.0", "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", @@ -2597,40 +2886,11 @@ } } }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "@types/node": { "version": "14.14.41", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==" }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", @@ -2657,9 +2917,9 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" }, "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -2841,6 +3101,11 @@ "@types/node": "*" } }, + "@types/cordova": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz", + "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" + }, "@types/deepmerge": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@types/deepmerge/-/deepmerge-2.2.0.tgz", @@ -2850,11 +3115,6 @@ "deepmerge": "*" } }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" - }, "@types/express": { "version": "4.17.12", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz", @@ -2867,9 +3127,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz", - "integrity": "sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==", + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.22.tgz", + "integrity": "sha512-WdqmrUsRS4ootGha6tVwk/IVHM1iorU8tGehftQD2NWiPniw/sm7xdJOIlXLwqdInL9wBw/p7oO8vaYEF3NDmA==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -2891,20 +3151,12 @@ "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" }, "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "requires": { - "@types/events": "*", "@types/minimatch": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", - "integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==" - } } }, "@types/got": { @@ -3059,13 +3311,6 @@ "integrity": "sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", - "integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==" - } } }, "@types/serve-static": { @@ -3084,9 +3329,9 @@ "dev": true }, "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", + "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==" }, "@types/traverse": { "version": "0.6.32", @@ -3107,9 +3352,9 @@ } }, "@types/webpack-sources": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", - "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.9.tgz", + "integrity": "sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new==", "dev": true, "requires": { "@types/node": "*", @@ -3122,6 +3367,355 @@ "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.2.0.tgz", "integrity": "sha512-GW8b9qM+ebgW3/zjzPm0I1NxMvLaz/YKT9Ph6tTb+Fkeyzd9yLTvQ6ciQ2MorTRmb/qXmfjMerRpG4LviixaqQ==" }, + "@typescript-eslint/eslint-plugin": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.3.0.tgz", + "integrity": "sha512-RqEcaHuEKnn3oPFislZ6TNzsBLqpZjN93G69SS+laav/I8w/iGMuMq97P0D2/2/kW4SCebHggqhbcCfbDaaX+g==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.3.0", + "@typescript-eslint/scope-manager": "4.3.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.3.0.tgz", + "integrity": "sha512-cmmIK8shn3mxmhpKfzMMywqiEheyfXLV/+yPDnOTvQX/ztngx7Lg/OD26J8gTZfkLKUmaEBxO2jYP3keV7h2OQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.3.0", + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/typescript-estree": "4.3.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.3.0.tgz", + "integrity": "sha512-cTeyP5SCNE8QBRfc+Lgh4Xpzje46kNUhXYfc3pQWmJif92sjrFuHT9hH4rtOkDTo/si9Klw53yIr+djqGZS1ig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0" + } + }, + "@typescript-eslint/types": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.3.0.tgz", + "integrity": "sha512-Cx9TpRvlRjOppGsU6Y6KcJnUDOelja2NNCX6AZwtVHRzaJkdytJWMuYiqi8mS35MRNA3cJSwDzXePfmhU6TANw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.3.0.tgz", + "integrity": "sha512-ZAI7xjkl+oFdLV/COEz2tAbQbR3XfgqHEGy0rlUXzfGQic6EBCR4s2+WS3cmTPG69aaZckEucBoTxW9PhzHxxw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.3.0.tgz", + "integrity": "sha512-xZxkuR7XLM6RhvLkgv9yYlTcBHnTULzfnw4i6+z2TGBLy9yljAypQaZl9c3zFvy7PNI7fYWyvKYtohyF8au3cw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz", + "integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.23.0", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/typescript-estree": "4.23.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.3.0.tgz", + "integrity": "sha512-JyfRnd72qRuUwItDZ00JNowsSlpQGeKfl9jxwO0FHK1qQ7FbYdoy5S7P+5wh1ISkT2QyAvr2pc9dAemDxzt75g==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.3.0", + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/typescript-estree": "4.3.0", + "debug": "^4.1.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.3.0.tgz", + "integrity": "sha512-cTeyP5SCNE8QBRfc+Lgh4Xpzje46kNUhXYfc3pQWmJif92sjrFuHT9hH4rtOkDTo/si9Klw53yIr+djqGZS1ig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0" + } + }, + "@typescript-eslint/types": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.3.0.tgz", + "integrity": "sha512-Cx9TpRvlRjOppGsU6Y6KcJnUDOelja2NNCX6AZwtVHRzaJkdytJWMuYiqi8mS35MRNA3cJSwDzXePfmhU6TANw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.3.0.tgz", + "integrity": "sha512-ZAI7xjkl+oFdLV/COEz2tAbQbR3XfgqHEGy0rlUXzfGQic6EBCR4s2+WS3cmTPG69aaZckEucBoTxW9PhzHxxw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "@typescript-eslint/visitor-keys": "4.3.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.3.0.tgz", + "integrity": "sha512-xZxkuR7XLM6RhvLkgv9yYlTcBHnTULzfnw4i6+z2TGBLy9yljAypQaZl9c3zFvy7PNI7fYWyvKYtohyF8au3cw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.3.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz", + "integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0" + } + }, + "@typescript-eslint/types": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz", + "integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz", + "integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz", + "integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.23.0", + "eslint-visitor-keys": "^2.0.0" + } + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -3346,6 +3940,12 @@ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, "acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -3417,10 +4017,9 @@ } }, "ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", - "dev": true, + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3541,18 +4140,18 @@ } }, "apache-crypt": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.4.tgz", - "integrity": "sha512-Icze5ny5W5uv3xgMgl8U+iGmRCC0iIDrb2PVPuRBtL3Zy1Y5TMewXP1Vtc4r5X9eNNBEk7KYPu0Qby9m/PmcHg==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.5.tgz", + "integrity": "sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg==", "dev": true, "requires": { "unix-crypt-td-js": "^1.1.4" } }, "apache-md5": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.5.tgz", - "integrity": "sha512-sbLEIMQrkV7RkIruqTPXxeCMkAAycv4yzTkBzRgOR1BrR5UB7qZtupqxkersTJSf0HZ3sbaNRrNV80TnnM7cUw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.7.tgz", + "integrity": "sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw==", "dev": true }, "app-root-path": { @@ -3590,21 +4189,13 @@ } }, "aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", "dev": true, "requires": { - "ast-types-flow": "0.0.7", - "commander": "^2.11.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" } }, "arr-diff": { @@ -3826,6 +4417,12 @@ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -4186,9 +4783,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "core-js": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz", - "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==" + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", + "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==" }, "has-flag": { "version": "3.0.0", @@ -4781,9 +5378,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001228", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", - "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "version": "1.0.30001242", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001242.tgz", + "integrity": "sha512-KvNuZ/duufelMB3w2xtf9gEWCSxJwUgoxOx5b6ScLXC4kPc9xsczUVCPrQU26j5kOsHM4pSUL54tAZt5THQKug==", "dev": true }, "canonical-path": { @@ -4812,9 +5409,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4832,13 +5429,13 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "cheerio": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.9.tgz", - "integrity": "sha512-QF6XVdrLONO6DXRF5iaolY+odmhj2CLj+xzNod7INPWMi/x9X4SOylH0S/vaPpX+AUU6t04s34SQNh7DbkuCng==", + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", "dev": true, "requires": { - "cheerio-select": "^1.4.0", - "dom-serializer": "^1.3.1", + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", "domhandler": "^4.2.0", "htmlparser2": "^6.1.0", "parse5": "^6.0.1", @@ -4870,30 +5467,30 @@ "dev": true }, "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", "dev": true } } }, "cheerio-select": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.4.0.tgz", - "integrity": "sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", "dev": true, "requires": { - "css-select": "^4.1.2", - "css-what": "^5.0.0", + "css-select": "^4.1.3", + "css-what": "^5.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0", - "domutils": "^2.6.0" + "domutils": "^2.7.0" }, "dependencies": { "css-select": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz", - "integrity": "sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", "dev": true, "requires": { "boolbase": "^1.0.0", @@ -4904,9 +5501,9 @@ } }, "css-what": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.0.tgz", - "integrity": "sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", + "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", "dev": true }, "dom-serializer": { @@ -4927,9 +5524,9 @@ "dev": true }, "domutils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", - "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -4949,19 +5546,19 @@ } }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "dependencies": { "fsevents": { @@ -4985,6 +5582,12 @@ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true }, + "ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -5024,6 +5627,15 @@ } } }, + "clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -5103,17 +5715,6 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, - "clipboard": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz", - "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==", - "optional": true, - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -5288,6 +5889,22 @@ "sprintf-js": "^1.1.2" }, "dependencies": { + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5302,6 +5919,12 @@ } } }, + "coffeescript": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", + "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -5392,6 +6015,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" }, + "comment-parser": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.5.tgz", + "integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -5593,16 +6222,16 @@ } }, "conventional-changelog-core": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.2.tgz", - "integrity": "sha512-7pDpRUiobQDNkwHyJG7k9f6maPo9tfPzkSWbRq97GGiZqisElhnvUZSvyQH20ogfOjntB5aadvv6NNcKL1sReg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.3.tgz", + "integrity": "sha512-MwnZjIoMRL3jtPH5GywVNqetGILC7g6RQFvdb8LRU/fA/338JbeWAku3PZ8yQ+mtVRViiISqJlb0sOz0htBZig==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog-writer": "^4.0.18", + "conventional-changelog-writer": "^5.0.0", "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", - "get-pkg-repo": "^1.0.0", + "get-pkg-repo": "^4.0.0", "git-raw-commits": "^2.0.8", "git-remote-origin-url": "^2.0.0", "git-semver-tags": "^4.1.1", @@ -5611,7 +6240,6 @@ "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", - "shelljs": "^0.8.3", "through2": "^4.0.0" }, "dependencies": { @@ -5720,12 +6348,11 @@ "dev": true }, "conventional-changelog-writer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz", - "integrity": "sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", + "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", "dev": true, "requires": { - "compare-func": "^2.0.0", "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", "handlebars": "^4.7.6", @@ -5939,9 +6566,9 @@ "dev": true }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } @@ -6156,17 +6783,17 @@ "dev": true }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -6233,9 +6860,9 @@ }, "dependencies": { "cacache": { - "version": "15.0.6", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", - "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", + "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==", "dev": true, "requires": { "@npmcli/move-file": "^1.0.1", @@ -6264,9 +6891,9 @@ "dev": true }, "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -6606,9 +7233,9 @@ "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" }, "core-js-compat": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz", - "integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz", + "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==", "dev": true, "requires": { "browserslist": "^4.16.6", @@ -6623,12 +7250,28 @@ } } }, + "core-js-pure": { + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.2.tgz", + "integrity": "sha512-D42L7RYh1J2grW8ttxoY1+17Y4wXZeKe7uyplAI3FkNQyI5OgBIAjUfFiTPfL1rs0qLpxaabITNbjKl1Sp82tA==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -6726,6 +7369,15 @@ "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==", "dev": true }, + "cson-parser": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-4.0.7.tgz", + "integrity": "sha512-BSnAl0gllETWjU9/lb8MmeqhsGaRINPwhoPiBjI/TJBRvKf/24I9EVqnwvmk6R3Gt66cMRSGVktl6QicxIb72g==", + "dev": true, + "requires": { + "coffeescript": "1.12.7" + } + }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", @@ -7358,12 +8010,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "optional": true - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -7457,9 +8103,9 @@ "dev": true }, "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", "dev": true, "requires": { "ip": "^1.1.0", @@ -7616,9 +8262,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.730", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.730.tgz", - "integrity": "sha512-1Tr3h09wXhmqXnvDyrRe6MFgTeU0ZXy3+rMJWTrOHh/HNesWwBBrKnMxRJWZ86dzs8qQdw2c7ZE1/qeGHygImA==", + "version": "1.3.768", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.768.tgz", + "integrity": "sha512-I4UMZHhVSK2pwt8jOIxTi3GIuc41NkddtKT/hpuxp9GO5UWJgDKTBa4TACppbVAuKtKbMK6BhQZvT5tFF1bcNA==", "dev": true }, "elementtree": { @@ -7683,9 +8329,9 @@ }, "dependencies": { "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -7824,6 +8470,23 @@ "tapable": "^1.0.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", @@ -7861,9 +8524,9 @@ } }, "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -7874,14 +8537,14 @@ "has-symbols": "^1.0.2", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" + "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { @@ -8018,6 +8681,386 @@ } } }, + "eslint": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true + }, + "eslint-plugin-jsdoc": { + "version": "35.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.1.tgz", + "integrity": "sha512-lnpu2Bj+ta2eAqwCWnb6f3Xjc78TWKo/oMCpDH5NfpPhYnePNtGZJzoAMgU5uo9BQqmXJ8pql8aiodOhg82ofw==", + "dev": true, + "requires": { + "@es-joy/jsdoccomment": "^0.8.0", + "comment-parser": "1.1.5", + "debug": "^4.3.1", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "^1.0.4", + "lodash": "^4.17.21", + "regextras": "^0.8.0", + "semver": "^7.3.5", + "spdx-expression-parse": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", + "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-unicorn": { + "version": "34.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-34.0.1.tgz", + "integrity": "sha512-GUBtRYRhPVOW/GDu6QtOjrneSZxY/MulOT8puJU+47VKCzNmMgS/iHO2gZqoQ7KPMrpNYlebUlvCWy3IR1USVQ==", + "dev": true, + "requires": { + "ci-info": "^3.2.0", + "clean-regexp": "^1.0.0", + "eslint-template-visitor": "^2.3.2", + "eslint-utils": "^3.0.0", + "is-builtin-module": "^3.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.23", + "reserved-words": "^0.1.2", + "safe-regex": "^2.1.1", + "semver": "^7.3.5" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "requires": { + "regexp-tree": "~0.1.1" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -8028,11 +9071,163 @@ "estraverse": "^4.1.1" } }, + "eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helpers": "^7.14.6", + "@babel/parser": "^7.14.6", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5", + "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/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -8343,10 +9538,9 @@ } }, "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz", + "integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=" }, "eyes": { "version": "0.1.8", @@ -8376,17 +9570,22 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "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-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", + "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fast-json-parse": { @@ -8412,9 +9611,9 @@ "dev": true }, "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", + "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", "requires": { "reusify": "^1.0.4" } @@ -8443,6 +9642,15 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-loader": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz", @@ -8571,11 +9779,28 @@ "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=", "dev": true }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "flatted": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz", + "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==", + "dev": true + } + } + }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" }, "flush-write-stream": { "version": "1.1.1", @@ -8658,9 +9883,9 @@ } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fragment-cache": { "version": "0.2.1", @@ -8764,6 +9989,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -8805,34 +10036,17 @@ } }, "get-pkg-repo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", - "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.1.2.tgz", + "integrity": "sha512-/FjamZL9cBYllEbReZkxF2IMh80d8TJoC4e3bmLNif8ibHw95aj0N/tzqK0kZz9eU/3w3dL6lF4fnnX/sDdW3A==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "meow": "^3.3.0", - "normalize-package-data": "^2.3.0", - "parse-github-repo-url": "^1.3.0", + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "meow": "^7.0.0", "through2": "^2.0.0" }, "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -8840,132 +10054,140 @@ "dev": true }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { - "repeating": "^2.0.0" + "lru-cache": "^6.0.0" } }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "p-locate": "^4.1.0" + } + }, + "meow": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, "get-stream": { @@ -9189,9 +10411,9 @@ "dev": true }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } @@ -9397,9 +10619,9 @@ "dev": true }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } @@ -9461,15 +10683,6 @@ "slash": "^3.0.0" } }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "optional": true, - "requires": { - "delegate": "^3.1.2" - } - }, "got": { "version": "11.8.2", "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", @@ -9555,20 +10768,6 @@ "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - } } }, "hard-rejection": { @@ -9831,9 +11030,9 @@ "dev": true }, "domutils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", - "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -9853,6 +11052,14 @@ "apache-md5": "^1.0.6", "bcryptjs": "^2.3.0", "uuid": "^3.0.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "http-cache-semantics": { @@ -10290,6 +11497,18 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } } }, "inside": { @@ -10323,9 +11542,9 @@ } }, "ionicons": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz", - "integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.2.tgz", + "integrity": "sha512-SHVBBtzNVQjY4jtcqKEHkqL5nIQwA/o2MIdU9JtMz8kQAB0NRVJFv5AxwmVbXXKDpxz57SiEjeLp8Uzt7jirpw==", "requires": { "@stencil/core": "^2.5.0" } @@ -10454,6 +11673,23 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-builtin-module": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz", + "integrity": "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==", + "dev": true, + "requires": { + "builtin-modules": "^3.0.0" + }, + "dependencies": { + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true + } + } + }, "is-callable": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", @@ -10556,12 +11792,6 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -10724,12 +11954,6 @@ "unc-path-regex": "^0.1.2" } }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -10905,9 +12129,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -11035,6 +12259,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdoc-type-pratt-parser": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.0.4.tgz", + "integrity": "sha512-jzmW9gokeq9+bHPDR1nCeidMyFUikdZlbOhKzh9+/nJqB75XhpNKec1/UuxW5c4+O+Pi31Gc/dCboyfSm/pSpQ==", + "dev": true + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -11081,6 +12311,12 @@ "jsonify": "~0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -11148,6 +12384,12 @@ "verror": "1.10.0" }, "dependencies": { + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -11627,20 +12869,10 @@ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, "requires": { "websocket-driver": ">=0.5.1" @@ -11768,12 +13000,6 @@ "is-wsl": "^1.1.0" } }, - "proxy-middleware": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", - "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=", - "dev": true - }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -11819,41 +13045,28 @@ } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true } } }, @@ -11928,6 +13141,18 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -12009,9 +13234,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -12069,9 +13294,9 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, "macos-release": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", - "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", + "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", "dev": true }, "magic-string": { @@ -12407,16 +13632,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" }, "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "requires": { - "mime-db": "1.47.0" + "mime-db": "1.48.0" } }, "mimic-fn": { @@ -12703,6 +13928,12 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "multimap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==", + "dev": true + }, "multimatch": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", @@ -12756,6 +13987,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "ncp": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", @@ -12814,9 +14051,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" } } }, @@ -12882,9 +14119,9 @@ } }, "node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "dev": true }, "nodemailer": { @@ -12940,9 +14177,9 @@ "dev": true }, "normalize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.0.1.tgz", - "integrity": "sha512-VU4pzAuh7Kip71XEmO9aNREYAdMHFGTVj/i+CaTImS8x0i1d3jUZkXhqluy/PRgjPLMgsLQulYY3PJ/aSbSjpQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm-bundled": { "version": "1.1.2", @@ -13199,21 +14436,20 @@ } }, "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" + "es-abstract": "^1.18.2" } }, "objectorarray": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.4.tgz", - "integrity": "sha512-91k8bjcldstRz1bG6zJo8lWD7c6QXcB4nTDUqiEvIL1xAsLoZlOOZZG+nd6YPz+V7zY1580J4Xxh1vZtyv4i/w==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==" }, "obuf": { "version": "1.1.2", @@ -13343,6 +14579,18 @@ "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } } }, "original": { @@ -13664,6 +14912,23 @@ "readable-stream": "^2.1.5" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, "parse-asn1": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", @@ -13677,12 +14942,6 @@ "safe-buffer": "^5.1.1" } }, - "parse-github-repo-url": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", - "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -13786,9 +15045,9 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "0.1.7", @@ -13840,9 +15099,9 @@ } }, "pdfmake": { - "version": "0.1.71", - "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.1.71.tgz", - "integrity": "sha512-uXUy+NZ8R5pwJ6rYLJRu7VRw/w5ogBScNk440CHpMZ6Z0+E1uc1XvwK4I1U5ry0UZQ3qPD0dpSvbzAkRBKYoJA==", + "version": "0.1.72", + "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.1.72.tgz", + "integrity": "sha512-xZrPS+Safjf1I8ZYtMoXX83E6C6Pd1zFwa168yNTeeJWHclqf1z9DoYajjlY2uviN7gGyxwVZeou39uSk1oh1g==", "dev": true, "requires": { "iconv-lite": "^0.6.2", @@ -13853,9 +15112,9 @@ }, "dependencies": { "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -13870,9 +15129,9 @@ "dev": true }, "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, "pify": { "version": "4.0.1", @@ -13924,6 +15183,12 @@ "xmldom": "^0.5.0" } }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, "png-js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", @@ -14405,9 +15670,9 @@ "dev": true }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -14724,14 +15989,26 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", + "prettier": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "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": { - "clipboard": "^2.0.0" + "fast-diff": "^1.1.2" } }, + "prismjs": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz", + "integrity": "sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow==" + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -15008,14 +16285,20 @@ } }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, + "proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=", + "dev": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -15294,18 +16577,6 @@ "path-type": "^3.0.0" }, "dependencies": { - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -15320,12 +16591,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -15420,9 +16685,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -15499,6 +16764,12 @@ "safe-regex": "^1.1.0" } }, + "regexp-tree": { + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.23.tgz", + "integrity": "sha512-+7HWfb4Bvu8Rs2eQTUIpX9I/PlQkYOuTNbRpKLJlQpSgwSkzFYh+pUj0gtvglnOZLKB6YgnIgRuJ2/IlpL48qw==", + "dev": true + }, "regexp.prototype.flags": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", @@ -15509,6 +16780,12 @@ "define-properties": "^1.1.3" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "regexpu-core": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", @@ -15523,6 +16800,12 @@ "unicode-match-property-value-ecmascript": "^1.2.0" } }, + "regextras": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.8.0.tgz", + "integrity": "sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==", + "dev": true + }, "regjsgen": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", @@ -15564,15 +16847,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -15617,6 +16891,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "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 } } }, @@ -15626,6 +16906,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -15638,6 +16924,12 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -15891,20 +17183,6 @@ "@types/json-schema": "^7.0.5", "ajv": "^6.12.4", "ajv-keywords": "^3.5.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - } } }, "scope-analyzer": { @@ -15922,12 +17200,6 @@ "get-assigned-identifiers": "^1.1.0" } }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", - "optional": true - }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -16249,6 +17521,17 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, "smart-buffer": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", @@ -16481,6 +17764,14 @@ "faye-websocket": "^0.10.0", "uuid": "^3.4.0", "websocket-driver": "0.6.5" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "sockjs-client": { @@ -16507,9 +17798,9 @@ } }, "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, "requires": { "websocket-driver": ">=0.5.1" @@ -16667,9 +17958,9 @@ } }, "spdx-license-ids": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.8.tgz", - "integrity": "sha512-NDgA96EnaLSvtbM7trJj+t1LUR3pirkDCcz9nOUlPb5DMBGsH7oES6C3hs3j7R9oHEa1EMvReS/BUAIT5Tcr0g==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", "dev": true }, "spdy": { @@ -16686,9 +17977,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -16717,9 +18008,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -17163,6 +18454,12 @@ "min-indent": "^1.0.0" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "style-loader": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.1.3.tgz", @@ -17638,6 +18935,40 @@ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", + "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, "tail": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/tail/-/tail-0.4.0.tgz", @@ -17743,9 +19074,9 @@ }, "dependencies": { "cacache": { - "version": "15.0.6", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", - "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", + "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==", "dev": true, "requires": { "@npmcli/move-file": "^1.0.1", @@ -17833,6 +19164,12 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -17876,12 +19213,6 @@ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "optional": true - }, "tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -17992,9 +19323,9 @@ "dev": true }, "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, "trim-off-newlines": { @@ -18021,9 +19352,9 @@ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" }, "typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==" + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==" } } }, @@ -18425,6 +19756,62 @@ } } }, + "tslint-to-eslint-config": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslint-to-eslint-config/-/tslint-to-eslint-config-2.0.1.tgz", + "integrity": "sha512-RURU/zcBQpW9jKS7H2J6of4+64npTb0nrH7ND8tNhagMwryVjVnUDcucsl8DQuD7tO9RgjFO9bmJfDhyP0yV1w==", + "dev": true, + "requires": { + "chalk": "4.1.0", + "commander": "6.2.0", + "cson-parser": "4.0.7", + "eslint-config-prettier": "6.15.0", + "glob": "7.1.6", + "json5": "2.1.3", + "lodash": "4.17.20", + "minimatch": "3.0.4", + "tslint": "6.1.3", + "typescript": "4.1.2" + }, + "dependencies": { + "commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true + }, + "eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "typescript": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz", + "integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==", + "dev": true + } + } + }, "tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", @@ -18525,9 +19912,9 @@ "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" }, "uglify-js": { - "version": "3.13.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.6.tgz", - "integrity": "sha512-rRprLwl8RVaS+Qvx3Wh5hPfPBn9++G6xkGlUupya0s5aDmNjI7z3lnRLB3u7sN4OmbB0pWgzhM9BEJyiWAwtAA==", + "version": "3.13.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.10.tgz", + "integrity": "sha512-57H3ACYFXeo1IaZ1w02sfA71wI60MGco/IQFjOqK+WtKoprh7Go2/yvd2HPtoJILO2Or84ncLccI4xoHMTSbGg==", "optional": true }, "ultron": { @@ -18700,6 +20087,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "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 } } }, @@ -18945,9 +20338,14 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "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", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { @@ -19711,9 +21109,9 @@ } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -19955,6 +21353,14 @@ "requires": { "ansi-colors": "^3.0.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "webpack-merge": { @@ -20309,9 +21715,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", "dev": true, "requires": { "async-limiter": "~1.0.0" @@ -20521,9 +21927,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" } } } diff --git a/package.json b/package.json index 588e8d82..a4d3e02c 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "docker:serve": "sudo docker run -p 8100:8100 -p 35729:35729 -p 53703:53703 -v $PWD:/app -it registry.gitlab.com/openstapps/app bash -c \"npm start\"", "documentation": "compodoc -p tsconfig.json -d docs", "lint": "ng lint", + "lint:fix": "ng lint:fix", "ng": "ng", "postversion": "npm run changelog", "pree2e": "webdriver-manager clean && webdriver-manager update --gecko false --versions.chrome $(google-chrome --product-version)", @@ -36,8 +37,7 @@ "start:prod": "ionic serve -- --configuration=production", "start:fake": "ionic serve -- --configuration=fake", "start:external": "ionic serve --external", - "test": "ng test", - "tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'" + "test": "ng test" }, "dependencies": { "@angular/cdk": "12.0.0", @@ -88,6 +88,11 @@ "@angular-devkit/build-angular": "0.901.13", "@angular-devkit/core": "9.1.12", "@angular-devkit/schematics": "9.1.12", + "@angular-eslint/builder": "12.2.0", + "@angular-eslint/eslint-plugin": "12.2.0", + "@angular-eslint/eslint-plugin-template": "12.2.0", + "@angular-eslint/schematics": "1.2.0", + "@angular-eslint/template-parser": "1.2.0", "@angular/cli": "9.1.12", "@angular/compiler": "9.1.12", "@angular/compiler-cli": "9.1.12", @@ -100,8 +105,15 @@ "@types/jasminewd2": "2.0.6", "@types/lodash-es": "4.17.4", "@types/node": "14.14.37", + "@typescript-eslint/eslint-plugin": "4.3.0", + "@typescript-eslint/parser": "4.3.0", "codelyzer": "5.1.2", "conventional-changelog-cli": "2.0.12", + "eslint": "7.30.0", + "eslint-config-prettier": "8.3.0", + "eslint-plugin-jsdoc": "35.4.1", + "eslint-plugin-prettier": "3.4.0", + "eslint-plugin-unicorn": "34.0.1", "is-docker": "1.1.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", @@ -111,10 +123,10 @@ "karma-jasmine": "2.0.1", "karma-jasmine-html-reporter": "1.4.2", "karma-mocha-reporter": "2.2.5", + "prettier": "2.3.2", "protractor": "5.4.2", "surge": "0.21.3", "ts-node": "8.0.3", - "tslint": "6.1.3", "typescript": "3.8.3" }, "cordova": { diff --git a/src/app/_helpers/data/resources/test-resources.ts b/src/app/_helpers/data/resources/test-resources.ts index 9c333728..cc4aac5d 100644 --- a/src/app/_helpers/data/resources/test-resources.ts +++ b/src/app/_helpers/data/resources/test-resources.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -/* tslint:disable */ +/* eslint-disable */ import moment from 'moment' diff --git a/src/app/_helpers/data/sample-configuration.ts b/src/app/_helpers/data/sample-configuration.ts index c32bd28c..fadcf7fc 100644 --- a/src/app/_helpers/data/sample-configuration.ts +++ b/src/app/_helpers/data/sample-configuration.ts @@ -42,22 +42,15 @@ export const sampleAggregations: SCBackendAggregationConfiguration[] = [ }, { fieldName: 'academicTerms.acronym', - onlyOnTypes: [ - SCThingType.AcademicEvent, - SCThingType.SportCourse, - ], + onlyOnTypes: [SCThingType.AcademicEvent, SCThingType.SportCourse], }, { fieldName: 'academicTerm.acronym', - onlyOnTypes: [ - SCThingType.Catalog, - ], + onlyOnTypes: [SCThingType.Catalog], }, { fieldName: 'majors', - onlyOnTypes: [ - SCThingType.AcademicEvent, - ], + onlyOnTypes: [SCThingType.AcademicEvent], }, { fieldName: 'keywords', diff --git a/src/app/_helpers/data/sample-facets.ts b/src/app/_helpers/data/sample-facets.ts index 6e298ea7..7589a21c 100644 --- a/src/app/_helpers/data/sample-facets.ts +++ b/src/app/_helpers/data/sample-facets.ts @@ -16,95 +16,98 @@ import {SCFacet, SCThingType} from '@openstapps/core'; export const facetsMock: SCFacet[] = [ { - 'buckets': [ + buckets: [ { - 'count': 60, - 'key': 'academic event', + count: 60, + key: 'academic event', }, { - 'count': 160, - 'key': 'message', + count: 160, + key: 'message', }, { - 'count': 151, - 'key': 'date series', + count: 151, + key: 'date series', }, { - 'count': 106, - 'key': 'dish', + count: 106, + key: 'dish', }, { - 'count': 20, - 'key': 'building', + count: 20, + key: 'building', }, { - 'count': 20, - 'key': 'semester', + count: 20, + key: 'semester', }, ], - 'field': 'type', + field: 'type', }, { - 'buckets': [ + buckets: [ { - 'count': 12, - 'key': 'Max Mustermann', + count: 12, + key: 'Max Mustermann', }, { - 'count': 2, - 'key': 'Foo Bar', + count: 2, + key: 'Foo Bar', }, ], - 'field': 'performers', - 'onlyOnType': SCThingType.AcademicEvent, + field: 'performers', + onlyOnType: SCThingType.AcademicEvent, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'colloquium', + count: 5, + key: 'colloquium', }, { - 'count': 15, - 'key': 'course', + count: 15, + key: 'course', }, ], - 'field': 'categories', - 'onlyOnType': SCThingType.AcademicEvent, + field: 'categories', + onlyOnType: SCThingType.AcademicEvent, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'unipedia', - }], - 'field': 'categories', - 'onlyOnType': SCThingType.Article, + count: 5, + key: 'unipedia', + }, + ], + field: 'categories', + onlyOnType: SCThingType.Article, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'employees', + count: 5, + key: 'employees', }, { - 'count': 15, - 'key': 'students', - }], - 'field': 'audiences', - 'onlyOnType': SCThingType.Message, + count: 15, + key: 'students', + }, + ], + field: 'audiences', + onlyOnType: SCThingType.Message, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'main dish', + count: 5, + key: 'main dish', }, { - 'count': 15, - 'key': 'salad', - }], - 'field': 'categories', - 'onlyOnType': SCThingType.Dish, + count: 15, + key: 'salad', + }, + ], + field: 'categories', + onlyOnType: SCThingType.Dish, }, ]; diff --git a/src/app/_helpers/data/sample-things.ts b/src/app/_helpers/data/sample-things.ts index 70854b82..7dfda970 100644 --- a/src/app/_helpers/data/sample-things.ts +++ b/src/app/_helpers/data/sample-things.ts @@ -15,15 +15,29 @@ import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import { - SCAcademicEvent, SCArticle, SCBook, SCBuilding, SCCatalog, - SCDateSeries, SCDish, SCFavorite, SCMessage, SCPerson, SCRoom, SCSearchFilter, - SCThing, SCThingOriginType, SCThingType, SCToDo, SCToDoPriority, + SCAcademicEvent, + SCArticle, + SCBook, + SCBuilding, + SCCatalog, + SCDateSeries, + SCDish, + SCFavorite, + SCMessage, + SCPerson, + SCRoom, + SCSearchFilter, + SCThing, + SCThingOriginType, + SCThingType, + SCToDo, + SCToDoPriority, } from '@openstapps/core'; import {Observable, of} from 'rxjs'; import {checkFilter} from '../fakesearch/filters'; import {sampleResources} from './resources/test-resources'; -// tslint:disable:no-magic-numbers +/* eslint-disable */ const sampleMessages: SCMessage[] = [ { audiences: ['students'], @@ -385,9 +399,9 @@ export class SampleThings { /** * TODO */ - // tslint:disable-next-line:prefer-function-over-method no-any + // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any getSampleThing(uid: string): Observable { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const sampleThings: any[] = []; for (const resource of sampleResources) { if (resource.instance.uid as SCThingType === uid) { @@ -403,12 +417,12 @@ export class SampleThings { /** * TODO */ - // tslint:disable-next-line:prefer-function-over-method no-any + // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any getSampleThings(filter?: SCSearchFilter): Observable { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const sampleThings: any[] = []; for (const resource of sampleResources) { - // tslint:disable-next-line:max-line-length + // eslint-disable-next-line max-len // if ([SCThingType.Video].includes(resource.instance.type as SCThingType)) { if (typeof filter === 'undefined' || checkFilter(resource.instance as SCThing, filter)) { sampleThings.push(resource.instance); diff --git a/src/app/_helpers/errors.ts b/src/app/_helpers/errors.ts index 6151adc4..81305104 100644 --- a/src/app/_helpers/errors.ts +++ b/src/app/_helpers/errors.ts @@ -18,7 +18,10 @@ */ export class AppError extends Error { /** - * Instantiate a new error + * TODO + * + * @param name Name of the error + * @param message Message of the error */ constructor(name: string, message: string) { super(message); diff --git a/src/app/_helpers/fake-backend.interceptor.ts b/src/app/_helpers/fake-backend.interceptor.ts index 07b50e8b..f308ad84 100644 --- a/src/app/_helpers/fake-backend.interceptor.ts +++ b/src/app/_helpers/fake-backend.interceptor.ts @@ -22,14 +22,20 @@ import { HTTP_INTERCEPTORS, } from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {SCIndexResponse, SCSettingInputType, SCThingOriginType, SCThingType} from '@openstapps/core'; +import { + SCIndexResponse, + SCSettingInputType, + SCThingOriginType, + SCThingType, +} from '@openstapps/core'; import {Observable, of} from 'rxjs'; import {delay, map} from 'rxjs/operators'; import {dependencies} from '../../../package.json'; import {facetsMock} from './data/sample-facets'; import {SampleThings} from './data/sample-things'; -// tslint:disable:no-magic-numbers +/* eslint-disable unicorn/no-abusive-eslint-disable */ +/* eslint-disable */ export const sampleIndexResponse: SCIndexResponse = { app: { campusPolygon: { @@ -313,7 +319,7 @@ export const sampleIndexResponse: SCIndexResponse = { }, }; -// tslint:enable:no-magic-numbers +/* eslint-enable no-magic-numbers */ /** * TODO @@ -338,7 +344,7 @@ export class FakeBackendInterceptor implements HttpInterceptor { /** * TODO */ - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any intercept(request: HttpRequest, next: HttpHandler): Observable> { if (request.method === 'POST') { if (request.url.endsWith('/') && request.method === 'POST') { @@ -350,7 +356,7 @@ export class FakeBackendInterceptor implements HttpInterceptor { if (typeof request.body.filter !== 'undefined' && typeof request.body.filter.arguments !== 'undefined') { if (request.body.filter.arguments.field === 'uid') { return this.sampleFetcher.getSampleThing(request.body.filter.arguments.value) - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any .pipe(map((sampleData: any) => { return new HttpResponse({status: 200, body: {data: sampleData}}); }), delay(this.RESPONSE_DELAY)); // add delay for skeleton screens to be seen (see !16) @@ -358,7 +364,7 @@ export class FakeBackendInterceptor implements HttpInterceptor { } return this.sampleFetcher.getSampleThings(request.body.filter) - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any .pipe(map((sampleData: any) => { return new HttpResponse({status: 200, body: {data: sampleData, facets: facetsMock}}); }), delay(this.RESPONSE_DELAY)); // add delay for skeleton screens to be seen (see !16) diff --git a/src/app/_helpers/fakesearch/filters.ts b/src/app/_helpers/fakesearch/filters.ts index ef7fce99..9c59bbb4 100644 --- a/src/app/_helpers/fakesearch/filters.ts +++ b/src/app/_helpers/fakesearch/filters.ts @@ -13,7 +13,12 @@ * this program. If not, see . */ -import {SCSearchBooleanFilter, SCSearchFilter, SCSearchValueFilter, SCThing} from '@openstapps/core'; +import { + SCSearchBooleanFilter, + SCSearchFilter, + SCSearchValueFilter, + SCThing, +} from '@openstapps/core'; import {logger} from '../ts-logger'; /** @@ -21,17 +26,19 @@ import {logger} from '../ts-logger'; */ export function checkFilter(thing: SCThing, filter: SCSearchFilter): boolean { switch (filter.type) { - case 'availability': /*TODO*/ + case 'availability' /*TODO*/: break; case 'boolean': return applyBooleanFilter(thing, filter); - case 'distance': /*TODO*/ + case 'distance' /*TODO*/: break; case 'value': return applyValueFilter(thing, filter); } - void logger.error(`Not implemented filter method "${filter.type}" in fake backend!`); + void logger.error( + `Not implemented filter method "${filter.type}" in fake backend!`, + ); return false; } @@ -39,11 +46,18 @@ export function checkFilter(thing: SCThing, filter: SCSearchFilter): boolean { /** * Checks if a value filter applies to an SCThing */ -function applyValueFilter(thing: SCThing, filter: SCSearchValueFilter): boolean { +function applyValueFilter( + thing: SCThing, + filter: SCSearchValueFilter, +): boolean { const path = filter.arguments.field.split('.'); - const thingFieldValue = traverseToFieldPath(thing, path, filter.arguments.value); + const thingFieldValue = traverseToFieldPath( + thing, + path, + filter.arguments.value, + ); - if (!(thingFieldValue.found)) { + if (!thingFieldValue.found) { return false; } @@ -54,32 +68,40 @@ function applyValueFilter(thing: SCThing, filter: SCSearchValueFilter): boolean * Object that can be accessed using foo[bar] */ interface IndexableObject { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; } /** * Result of a search for a field and comparison to a desired value */ -type FieldSearchResult = { - /** - * Weather the field was found - */ - found: true; +type FieldSearchResult = + | { + /** + * Weather the field was found + */ + found: true; - /** - * The result of the comparison - */ - result: boolean; -} | { - /** - * Weather the field was found - */ - found: false; -}; + /** + * The result of the comparison + */ + result: boolean; + } + | { + /** + * Weather the field was found + */ + found: false; + }; -// tslint:disable-next-line:completed-docs -function traverseToFieldPath(value: IndexableObject, path: string[], desiredFieldValue: unknown): FieldSearchResult { +/** + * TODO + */ +function traverseToFieldPath( + value: IndexableObject, + path: string[], + desiredFieldValue: unknown, +): FieldSearchResult { if (path.length === 0) { void logger.error(`Value filter provided with zero length path`); @@ -90,7 +112,7 @@ function traverseToFieldPath(value: IndexableObject, path: string[], desiredFiel const nestedProperty = value[path[0]]; if (path.length === 1) { - return esStyleFieldHandler(nestedProperty, (nestedValue) => { + return esStyleFieldHandler(nestedProperty, nestedValue => { return { found: true, result: nestedValue === desiredFieldValue, @@ -98,13 +120,14 @@ function traverseToFieldPath(value: IndexableObject, path: string[], desiredFiel }); } - return esStyleFieldHandler(nestedProperty, (nestedValue) => { + return esStyleFieldHandler(nestedProperty, nestedValue => { if (typeof nestedValue === 'object') { return traverseToFieldPath( nestedValue as IndexableObject, - // tslint:disable-next-line:no-magic-numbers + // eslint-disable-next-line no-magic-numbers path.slice(1), - desiredFieldValue); + desiredFieldValue, + ); } return {found: false}; @@ -117,8 +140,10 @@ function traverseToFieldPath(value: IndexableObject, path: string[], desiredFiel /** * ES treats arrays like normal fields */ -function esStyleFieldHandler(field: T | T[], - handler: (value: T) => FieldSearchResult): FieldSearchResult { +function esStyleFieldHandler( + field: T | T[], + handler: (value: T) => FieldSearchResult, +): FieldSearchResult { if (Array.isArray(field)) { for (const nestedField of field) { const result = handler(nestedField); @@ -138,7 +163,10 @@ function esStyleFieldHandler(field: T | T[], /** * Checks if a boolean filter applies to an SCThing */ -function applyBooleanFilter(thing: SCThing, filter: SCSearchBooleanFilter): boolean { +function applyBooleanFilter( + thing: SCThing, + filter: SCSearchBooleanFilter, +): boolean { let out = false; switch (filter.arguments.operation) { @@ -164,7 +192,9 @@ function applyBooleanFilter(thing: SCThing, filter: SCSearchBooleanFilter): bool return false; } - void logger.error(`Not implemented boolean filter "${filter.arguments.operation}"`); + void logger.error( + `Not implemented boolean filter "${filter.arguments.operation}"`, + ); return false; } diff --git a/src/app/_helpers/ts-logger.ts b/src/app/_helpers/ts-logger.ts index 7dce02c7..766ab40d 100644 --- a/src/app/_helpers/ts-logger.ts +++ b/src/app/_helpers/ts-logger.ts @@ -16,4 +16,4 @@ import {NGXLogger} from 'ngx-logger'; export let logger: NGXLogger; -export const initLogger = (newLogger: NGXLogger) => logger = newLogger; +export const initLogger = (newLogger: NGXLogger) => (logger = newLogger); diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 3e7bfee0..2441d4af 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -15,9 +15,7 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; -const routes: Routes = [ - {path: '', redirectTo: '/news', pathMatch: 'full'}, -]; +const routes: Routes = [{path: '', redirectTo: '/news', pathMatch: 'full'}]; /** * TODO diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index eff8483c..1baf934b 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /* * Copyright (C) 2018, 2019 StApps * This program is free software: you can redistribute it and/or modify it @@ -24,10 +25,9 @@ import {ThingTranslateService} from './translation/thing-translate.service'; import {AppComponent} from './app.component'; import {ConfigProvider} from './modules/config/config.provider'; import {SettingsProvider} from './modules/settings/settings.provider'; -import {NGXLogger} from "ngx-logger"; +import {NGXLogger} from 'ngx-logger'; describe('AppComponent', () => { - let statusBarSpy: jasmine.SpyObj; let splashScreenSpy: jasmine.SpyObj; let platformReadySpy: any; @@ -42,15 +42,21 @@ describe('AppComponent', () => { statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']); splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']); platformReadySpy = Promise.resolve(); - platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy }); - translateServiceSpy = jasmine.createSpyObj('TranslateService', ['setDefaultLang', 'use']); - thingTranslateServiceSpy = jasmine.createSpyObj('ThingTranslateService', ['init']); - settingsProvider = jasmine.createSpyObj('SettingsProvider', - ['getSettingValue', 'provideSetting', 'setCategoriesOrder']); - configProvider = jasmine.createSpyObj('ConfigProvider', - ['init']); - ngxLogger = jasmine.createSpyObj('NGXLogger', - ['log', 'error', 'warn']); + platformSpy = jasmine.createSpyObj('Platform', {ready: platformReadySpy}); + translateServiceSpy = jasmine.createSpyObj('TranslateService', [ + 'setDefaultLang', + 'use', + ]); + thingTranslateServiceSpy = jasmine.createSpyObj('ThingTranslateService', [ + 'init', + ]); + settingsProvider = jasmine.createSpyObj('SettingsProvider', [ + 'getSettingValue', + 'provideSetting', + 'setCategoriesOrder', + ]); + configProvider = jasmine.createSpyObj('ConfigProvider', ['init']); + ngxLogger = jasmine.createSpyObj('NGXLogger', ['log', 'error', 'warn']); TestBed.configureTestingModule({ declarations: [AppComponent], @@ -83,5 +89,4 @@ describe('AppComponent', () => { }); // TODO: add more tests! - }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 98a70463..201da572 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -47,19 +47,19 @@ export class AppComponent { * @param platform TODO * @param statusBar TODO * @param splashScreen TODO - * @param translateService TODO - * @param thingTranslateService TODO * @param settingsProvider TODO * @param configProvider TODO * @param logger An angular logger */ - constructor(private readonly platform: Platform, - private readonly statusBar: StatusBar, - private readonly splashScreen: SplashScreen, - private readonly settingsProvider: SettingsProvider, - private readonly configProvider: ConfigProvider, - private readonly logger: NGXLogger) { - this.initializeApp(); + constructor( + private readonly platform: Platform, + private readonly statusBar: StatusBar, + private readonly splashScreen: SplashScreen, + private readonly settingsProvider: SettingsProvider, + private readonly configProvider: ConfigProvider, + private readonly logger: NGXLogger, + ) { + void this.initializeApp(); } /** @@ -67,32 +67,32 @@ export class AppComponent { */ async initializeApp() { // tslint:disable-next-line: no-floating-promises - this.platform.ready() - .then(async () => { - // Okay, so the platform is ready and our plugins are available. - // Here you can do any higher level native things you might need. - this.statusBar.styleDefault(); - this.splashScreen.hide(); + this.platform.ready().then(async () => { + // Okay, so the platform is ready and our plugins are available. + // Here you can do any higher level native things you might need. + this.statusBar.styleDefault(); + this.splashScreen.hide(); - // initialise the configProvider - try { - await this.configProvider.init(); - } catch (error) { - if (typeof error.name !== 'undefined') { - if (error.name === 'ConfigInitError') { - // @TODO: Issue #43 handle initialisation error and inform user - } - } - this.logger.error(error); + // initialise the configProvider + try { + await this.configProvider.init(); + } catch (error) { + if ( + typeof error.name !== 'undefined' && + error.name === 'ConfigInitError' + ) { + // TODO: Issue #43 handle initialisation error and inform user } + this.logger.error(error); + } - // set order of categories in settings - this.settingsProvider.setCategoriesOrder([ - 'profile', - 'privacy', - 'credentials', - 'others', - ]); - }); + // set order of categories in settings + this.settingsProvider.setCategoriesOrder([ + 'profile', + 'privacy', + 'credentials', + 'others', + ]); + }); } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ebab0953..aa3182de 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,7 +12,12 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {CommonModule, HashLocationStrategy, LocationStrategy, registerLocaleData} from '@angular/common'; +import { + CommonModule, + HashLocationStrategy, + LocationStrategy, + registerLocaleData, +} from '@angular/common'; import {HttpClient} from '@angular/common/http'; import localeDe from '@angular/common/locales/de'; import {APP_INITIALIZER, NgModule, Provider} from '@angular/core'; @@ -21,7 +26,11 @@ import {RouteReuseStrategy} from '@angular/router'; import {SplashScreen} from '@ionic-native/splash-screen/ngx'; import {StatusBar} from '@ionic-native/status-bar/ngx'; import {IonicModule, IonicRouteStrategy} from '@ionic/angular'; -import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core'; +import { + TranslateLoader, + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import {TranslateHttpLoader} from '@ngx-translate/http-loader'; import moment from 'moment'; import 'moment/min/locales'; @@ -47,21 +56,33 @@ registerLocaleData(localeDe); /** * Initializes settings from Config before other components * + * @param logger TODO * @param settingsProvider provider of settings (e.g. language that has been set) + * @param configProvider TODO + * @param translateService TODO */ - export function initSettingsFactory(logger: NGXLogger, - settingsProvider: SettingsProvider, - configProvider: ConfigProvider, - translateService: TranslateService) { +export function initSettingsFactory( + logger: NGXLogger, + settingsProvider: SettingsProvider, + configProvider: ConfigProvider, + translateService: TranslateService, +) { return async () => { initLogger(logger); await settingsProvider.init(); try { // set language from settings if (configProvider.firstSession) { - await settingsProvider.setSettingValue('profile', 'language', translateService.getBrowserLang()); + await settingsProvider.setSettingValue( + 'profile', + 'language', + translateService.getBrowserLang(), + ); } - const languageCode = (await settingsProvider.getValue('profile', 'language')) as string; + const languageCode = (await settingsProvider.getValue( + 'profile', + 'language', + )) as string; // this language will be used as a fallback when a translation isn't found in the current language translateService.setDefaultLang('en'); translateService.use(languageCode); @@ -81,7 +102,7 @@ export function createTranslateLoader(http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json'); } -const providers : Provider[] = [ +const providers: Provider[] = [ StatusBar, SplashScreen, { @@ -95,7 +116,7 @@ const providers : Provider[] = [ { provide: APP_INITIALIZER, multi: true, - deps: [NGXLogger,SettingsProvider,ConfigProvider,TranslateService], + deps: [NGXLogger, SettingsProvider, ConfigProvider, TranslateService], useFactory: initSettingsFactory, }, ]; @@ -122,14 +143,18 @@ const providers : Provider[] = [ loader: { deps: [HttpClient], provide: TranslateLoader, - useFactory: (createTranslateLoader), + useFactory: createTranslateLoader, }, }), // use maximal logging level when not in production, minimal (log only fatal errors) in production - LoggerModule.forRoot({level: environment.production ? NgxLoggerLevel.FATAL : NgxLoggerLevel.TRACE}), + LoggerModule.forRoot({ + level: environment.production + ? NgxLoggerLevel.FATAL + : NgxLoggerLevel.TRACE, + }), ], - providers: - environment.use_fake_backend ? [providers, fakeBackendProvider] : providers, + providers: environment.use_fake_backend + ? [providers, fakeBackendProvider] + : providers, }) -export class AppModule { -} +export class AppModule {} diff --git a/src/app/modules/config/config.module.ts b/src/app/modules/config/config.module.ts index 6b2b34e1..cd3ee9cb 100644 --- a/src/app/modules/config/config.module.ts +++ b/src/app/modules/config/config.module.ts @@ -21,12 +21,7 @@ import {ConfigProvider} from './config.provider'; * TODO */ @NgModule({ - imports: [ - StorageModule, - DataModule, - ], - providers: [ - ConfigProvider, - ], + imports: [StorageModule, DataModule], + providers: [ConfigProvider], }) export class ConfigModule {} diff --git a/src/app/modules/config/config.provider.spec.ts b/src/app/modules/config/config.provider.spec.ts index 972a291b..53200f8c 100644 --- a/src/app/modules/config/config.provider.spec.ts +++ b/src/app/modules/config/config.provider.spec.ts @@ -13,12 +13,22 @@ * this program. If not, see . */ import {TestBed} from '@angular/core/testing'; -import {SCIndexResponse, SCThingOriginType, SCThingType, SCSettingInputType} from '@openstapps/core'; +import { + SCIndexResponse, + SCThingOriginType, + SCThingType, + SCSettingInputType, +} from '@openstapps/core'; import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider'; import {StorageProvider} from '../storage/storage.provider'; import {ConfigProvider, STORAGE_KEY_CONFIG} from './config.provider'; -import {ConfigFetchError, ConfigInitError, SavedConfigNotAvailable, WrongConfigVersionInStorage,} from './errors'; -import {NGXLogger} from "ngx-logger"; +import { + ConfigFetchError, + ConfigInitError, + SavedConfigNotAvailable, + WrongConfigVersionInStorage, +} from './errors'; +import {NGXLogger} from 'ngx-logger'; import {dependencies} from '../../../../package.json'; describe('ConfigProvider', () => { @@ -26,22 +36,35 @@ describe('ConfigProvider', () => { let storageProviderSpy: jasmine.SpyObj; beforeEach(() => { - const storageProviderMethodSpy = jasmine.createSpyObj('StorageProvider', ['init', 'get', 'has', 'put']); - const webHttpClientMethodSpy = jasmine.createSpyObj('StAppsWebHttpClient', ['request']); - const ngxLogger: jasmine.SpyObj = jasmine.createSpyObj('NGXLogger', ['log', 'error', 'warn']); + const storageProviderMethodSpy = jasmine.createSpyObj('StorageProvider', [ + 'init', + 'get', + 'has', + 'put', + ]); + const webHttpClientMethodSpy = jasmine.createSpyObj('StAppsWebHttpClient', [ + 'request', + ]); + const ngxLogger: jasmine.SpyObj = jasmine.createSpyObj( + 'NGXLogger', + ['log', 'error', 'warn'], + ); TestBed.configureTestingModule({ imports: [], providers: [ ConfigProvider, { - provide: StorageProvider, useValue: storageProviderMethodSpy, + provide: StorageProvider, + useValue: storageProviderMethodSpy, }, { - provide: StAppsWebHttpClient, useValue: webHttpClientMethodSpy, + provide: StAppsWebHttpClient, + useValue: webHttpClientMethodSpy, }, { - provide: NGXLogger, useValue: ngxLogger, + provide: NGXLogger, + useValue: ngxLogger, }, ], }); @@ -51,25 +74,30 @@ describe('ConfigProvider', () => { }); it('should fetch app configuration', async () => { - spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse)); + spyOn(configProvider.client, 'handshake').and.returnValue( + Promise.resolve(sampleIndexResponse), + ); const result = await configProvider.fetch(); expect(result).toEqual(sampleIndexResponse); }); it('should throw error on fetch with error response', async () => { spyOn(configProvider.client, 'handshake').and.throwError(''); + // eslint-disable-next-line unicorn/error-message let error = new Error(''); try { await configProvider.fetch(); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new ConfigFetchError()); }); it('should init from remote and saved config not available', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(false)); - spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse)); + spyOn(configProvider.client, 'handshake').and.returnValue( + Promise.resolve(sampleIndexResponse), + ); try { await configProvider.init(); } catch (error) { @@ -79,34 +107,42 @@ describe('ConfigProvider', () => { expect(storageProviderSpy.get).toHaveBeenCalledTimes(0); expect(configProvider.client.handshake).toHaveBeenCalled(); expect(configProvider.initialised).toBe(true); - expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); + expect(await configProvider.getValue('name')).toEqual( + sampleIndexResponse.app.name, + ); }); it('should init from storage when remote fails', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(true)); - storageProviderSpy.get.and.returnValue(Promise.resolve(sampleIndexResponse)); + storageProviderSpy.get.and.returnValue( + Promise.resolve(sampleIndexResponse), + ); spyOn(configProvider.client, 'handshake').and.throwError(''); + // eslint-disable-next-line unicorn/error-message let error = new Error(''); try { await configProvider.init(); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new ConfigFetchError()); expect(storageProviderSpy.has).toHaveBeenCalled(); expect(storageProviderSpy.get).toHaveBeenCalled(); expect(configProvider.initialised).toBe(true); - expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); + expect(await configProvider.getValue('name')).toEqual( + sampleIndexResponse.app.name, + ); }); it('should throw error on failed initialisation', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(false)); spyOn(configProvider.client, 'handshake').and.throwError(''); + // eslint-disable-next-line unicorn/no-null let error = null; try { await configProvider.init(); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new ConfigInitError()); }); @@ -116,30 +152,37 @@ describe('ConfigProvider', () => { const wrongConfig = JSON.parse(JSON.stringify(sampleIndexResponse)); wrongConfig.backend.SCVersion = '0.1.0'; storageProviderSpy.get.and.returnValue(wrongConfig); - spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse)); + spyOn(configProvider.client, 'handshake').and.returnValue( + Promise.resolve(sampleIndexResponse), + ); + // eslint-disable-next-line unicorn/no-null let error = null; try { await configProvider.init(); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new WrongConfigVersionInStorage(scVersion, '0.1.0')); }); it('should throw error on saved app configuration not available', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(false)); + // eslint-disable-next-line unicorn/error-message let error = new Error(''); try { await configProvider.loadLocal(); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new SavedConfigNotAvailable()); }); it('should save app configuration', async () => { await configProvider.save(sampleIndexResponse); - expect(storageProviderSpy.put).toHaveBeenCalledWith(STORAGE_KEY_CONFIG, sampleIndexResponse); + expect(storageProviderSpy.put).toHaveBeenCalledWith( + STORAGE_KEY_CONFIG, + sampleIndexResponse, + ); }); it('should set app configuration', async () => { @@ -149,21 +192,31 @@ describe('ConfigProvider', () => { it('should return app configuration value', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(true)); - storageProviderSpy.get.and.returnValue(Promise.resolve(sampleIndexResponse)); - spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse)); + storageProviderSpy.get.and.returnValue( + Promise.resolve(sampleIndexResponse), + ); + spyOn(configProvider.client, 'handshake').and.returnValue( + Promise.resolve(sampleIndexResponse), + ); await configProvider.init(); - expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); + expect(await configProvider.getValue('name')).toEqual( + sampleIndexResponse.app.name, + ); }); it('should return app configuration value if only saved config is available and fetch fails', async () => { storageProviderSpy.has.and.returnValue(Promise.resolve(true)); - storageProviderSpy.get.and.returnValue(Promise.resolve(sampleIndexResponse)); + storageProviderSpy.get.and.returnValue( + Promise.resolve(sampleIndexResponse), + ); spyOn(configProvider.client, 'handshake').and.throwError(''); - expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); + expect(await configProvider.getValue('name')).toEqual( + sampleIndexResponse.app.name, + ); }); }); -const scVersion = dependencies["@openstapps/core"]; +const scVersion = dependencies['@openstapps/core']; const sampleIndexResponse: SCIndexResponse = { app: { @@ -192,7 +245,6 @@ const sampleIndexResponse: SCIndexResponse = { }, }, }, - ], name: 'main', translations: { @@ -235,11 +287,7 @@ const sampleIndexResponse: SCIndexResponse = { backend: { SCVersion: scVersion, externalRequestTimeout: 5000, - hiddenTypes: [ - SCThingType.DateSeries, - SCThingType.Diff, - SCThingType.Floor, - ], + hiddenTypes: [SCThingType.DateSeries, SCThingType.Diff, SCThingType.Floor], mappingIgnoredTags: [], maxMultiSearchRouteQueries: 5, maxRequestBodySize: 512 * 1024, @@ -299,9 +347,7 @@ const sampleIndexResponse: SCIndexResponse = { }, { fieldName: 'offers', - onlyOnTypes: [ - SCThingType.Dish, - ], + onlyOnTypes: [SCThingType.Dish], sortTypes: ['price'], }, ], diff --git a/src/app/modules/config/config.provider.ts b/src/app/modules/config/config.provider.ts index fdd7793c..03f5b5f6 100644 --- a/src/app/modules/config/config.provider.ts +++ b/src/app/modules/config/config.provider.ts @@ -31,7 +31,7 @@ import { /** * Key to store config in storage module * - * @TODO: Issue #41 centralise storage keys + * TODO: Issue #41 centralise storage keys */ export const STORAGE_KEY_CONFIG = 'stapps.config'; @@ -44,18 +44,22 @@ export class ConfigProvider { * Api client */ client: Client; + /** * App configuration as IndexResponse */ config: SCIndexResponse; + /** * First session indicator */ firstSession = true; + /** * Initialised status flag of config provider */ initialised = false; + /** * Version of the @openstapps/core package that app is using */ @@ -68,10 +72,16 @@ export class ConfigProvider { * @param swHttpClient Api client * @param logger An angular logger */ - constructor(private readonly storageProvider: StorageProvider, - swHttpClient: StAppsWebHttpClient, - private readonly logger: NGXLogger) { - this.client = new Client(swHttpClient, environment.backend_url, environment.backend_version); + constructor( + private readonly storageProvider: StorageProvider, + swHttpClient: StAppsWebHttpClient, + private readonly logger: NGXLogger, + ) { + this.client = new Client( + swHttpClient, + environment.backend_url, + environment.backend_version, + ); } /** @@ -80,7 +90,7 @@ export class ConfigProvider { async fetch(): Promise { try { return await this.client.handshake(this.scVersion); - } catch (error) { + } catch { throw new ConfigFetchError(); } } @@ -124,7 +134,10 @@ export class ConfigProvider { this.initialised = true; this.logger.log(`initialised configuration from storage`); if (this.config.backend.SCVersion !== this.scVersion) { - loadError = new WrongConfigVersionInStorage(this.scVersion, this.config.backend.SCVersion); + loadError = new WrongConfigVersionInStorage( + this.scVersion, + this.config.backend.SCVersion, + ); this.logger.warn(loadError); } } catch (error) { diff --git a/src/app/modules/config/errors.ts b/src/app/modules/config/errors.ts index 98fb4bad..9cf057df 100644 --- a/src/app/modules/config/errors.ts +++ b/src/app/modules/config/errors.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {AppError} from './../../_helpers/errors'; +import {AppError} from '../../_helpers/errors'; /** * Error that is thrown when fetching from backend fails @@ -38,7 +38,10 @@ export class ConfigInitError extends AppError { */ export class ConfigValueNotAvailable extends AppError { constructor(valueKey: string) { - super('ConfigValueNotAvailable', `No attribute "${valueKey}" in config available!`); + super( + 'ConfigValueNotAvailable', + `No attribute "${valueKey}" in config available!`, + ); } } @@ -56,7 +59,10 @@ export class SavedConfigNotAvailable extends AppError { */ export class WrongConfigVersionInStorage extends AppError { constructor(correctVersion: string, savedVersion: string) { - super('WrongConfigVersionInStorage', `The saved configs backend version ${savedVersion} ` + - `does not equal the configured backend version ${correctVersion} of the app.`); + super( + 'WrongConfigVersionInStorage', + `The saved configs backend version ${savedVersion} ` + + `does not equal the configured backend version ${correctVersion} of the app.`, + ); } } diff --git a/src/app/modules/data/chips/action-chip-list.component.ts b/src/app/modules/data/chips/action-chip-list.component.ts index 1903cd62..0eafa4bb 100644 --- a/src/app/modules/data/chips/action-chip-list.component.ts +++ b/src/app/modules/data/chips/action-chip-list.component.ts @@ -28,9 +28,11 @@ export class ActionChipListComponent { * If chips are applicable */ applicable: Record boolean> = { - 'locate': () => this.item.hasOwnProperty('inPlace'), - 'event': () => this.item.type === SCThingType.AcademicEvent || - (this.item.type === SCThingType.DateSeries && (this.item as SCDateSeries).dates.length !== 0), + locate: () => this.item.hasOwnProperty('inPlace'), + event: () => + this.item.type === SCThingType.AcademicEvent || + (this.item.type === SCThingType.DateSeries && + (this.item as SCDateSeries).dates.length > 0), }; /** diff --git a/src/app/modules/data/chips/action-chip-list.html b/src/app/modules/data/chips/action-chip-list.html index 5680b7fe..3c81cd12 100644 --- a/src/app/modules/data/chips/action-chip-list.html +++ b/src/app/modules/data/chips/action-chip-list.html @@ -1,4 +1,10 @@
- - + +
diff --git a/src/app/modules/data/chips/add-event-popover.component.ts b/src/app/modules/data/chips/add-event-popover.component.ts index 716e6928..3b4cb3f0 100644 --- a/src/app/modules/data/chips/add-event-popover.component.ts +++ b/src/app/modules/data/chips/add-event-popover.component.ts @@ -28,9 +28,8 @@ enum Selection { * * The generic is to preserve type safety of how deep the tree goes. */ -// tslint:disable-next-line:no-any +// eslint-disable-next-line @typescript-eslint/no-explicit-any class TreeNode | SelectionValue> { - /** * Value of this node */ @@ -55,13 +54,25 @@ class TreeNode | SelectionValue> { * Accumulate values of children to set current value */ private accumulateApplyValues() { - const selections: number[] = - this.children.map(it => it instanceof TreeNode ? - (it.checked ? Selection.ON : (it.indeterminate ? Selection.PARTIAL : Selection.OFF)) : - (it as SelectionValue).selected ? Selection.ON : Selection.OFF); + const selections: number[] = this.children.map( + it => + /* eslint-disable unicorn/no-nested-ternary */ + it instanceof TreeNode + ? it.checked + ? Selection.ON + : it.indeterminate + ? Selection.PARTIAL + : Selection.OFF + : (it as SelectionValue).selected + ? Selection.ON + : Selection.OFF, + /* eslint-enable unicorn/no-nested-ternary */ + ); this.checked = every(selections, it => it === Selection.ON); - this.indeterminate = this.checked ? false : some(selections, it => it > Selection.OFF); + this.indeterminate = this.checked + ? false + : some(selections, it => it > Selection.OFF); } /** @@ -72,7 +83,7 @@ class TreeNode | SelectionValue> { if (child instanceof TreeNode) { child.checked = this.checked; child.indeterminate = false; - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any (child as TreeNode).applyValueDownwards(); } else { (child as SelectionValue).selected = this.checked; @@ -159,18 +170,23 @@ export class AddEventPopoverComponent implements OnInit { */ selection: TreeNode>; - constructor(readonly ref: ChangeDetectorRef) { - } + constructor(readonly ref: ChangeDetectorRef) {} /** * Init */ ngOnInit() { - this.selection = - new TreeNode(values(groupBy(sortBy(this.items.map(item => ({ - selected: false, - item: item, - })), it => it.item.frequency), it => it.item.frequency)) - .map(item => new TreeNode(item, this.ref)), this.ref); + this.selection = new TreeNode( + values( + groupBy( + sortBy( + this.items.map(item => ({selected: false, item: item})), + it => it.item.frequency, + ), + it => it.item.frequency, + ), + ).map(item => new TreeNode(item, this.ref)), + this.ref, + ); } } diff --git a/src/app/modules/data/chips/add-event-popover.html b/src/app/modules/data/chips/add-event-popover.html index 9c689989..edea1a30 100644 --- a/src/app/modules/data/chips/add-event-popover.html +++ b/src/app/modules/data/chips/add-event-popover.html @@ -1,39 +1,47 @@ - - {{'data.chips.add_events.popover.ALL' | translate}} - + + {{ + 'data.chips.add_events.popover.ALL' | translate + }} + - - - {{('frequency' | thingTranslate: frequency.children[0].item) | titlecase}} - + + + {{ + 'frequency' | thingTranslate: frequency.children[0].item | titlecase + }} + - - - {{date.item.duration | amDuration: 'hours'}} - {{'data.chips.add_events.popover.AT' | translate}} - {{date.item.dates[0] | amDateFormat: 'HH:mm ddd'}} - {{'data.chips.add_events.popover.UNTIL' | translate}} - {{last(date.item.dates) | amDateFormat: 'll'}} + + + {{ date.item.duration | amDuration: 'hours' }} + {{ 'data.chips.add_events.popover.AT' | translate }} + {{ date.item.dates[0] | amDateFormat: 'HH:mm ddd' }} + {{ 'data.chips.add_events.popover.UNTIL' | translate }} + {{ last(date.item.dates) | amDateFormat: 'll' }} - {{date.item.duration | amDuration: 'hours'}} - {{'data.chips.add_events.popover.AT' | translate}} - {{last(date.item.dates) | amDateFormat: 'll, HH:mm'}} + {{ date.item.duration | amDuration: 'hours' }} + {{ 'data.chips.add_events.popover.AT' | translate }} + {{ last(date.item.dates) | amDateFormat: 'll, HH:mm' }} - - + diff --git a/src/app/modules/data/chips/data/add-event-action-chip.component.ts b/src/app/modules/data/chips/data/add-event-action-chip.component.ts index ab602bce..c00a0b7d 100644 --- a/src/app/modules/data/chips/data/add-event-action-chip.component.ts +++ b/src/app/modules/data/chips/data/add-event-action-chip.component.ts @@ -1,4 +1,4 @@ -/* tslint:disable:prefer-function-over-method */ +/* eslint-disable class-methods-use-this */ /* * Copyright (C) 2021 StApps * This program is free software: you can redistribute it and/or modify it @@ -91,9 +91,10 @@ export class AddEventActionChipComponent implements OnInit { }, }; - constructor(readonly popoverController: PopoverController, - readonly dataProvider: DataProvider) { - } + constructor( + readonly popoverController: PopoverController, + readonly dataProvider: DataProvider, + ) {} /** * Apply state @@ -110,35 +111,42 @@ export class AddEventActionChipComponent implements OnInit { * Init */ ngOnInit() { - this.associatedDateSeries = this.item.type === SCThingType.DateSeries ? - Promise.resolve([this.item as SCDateSeries]) : - this.dataProvider.search({ - filter: { - arguments: { - filters: [ - { + this.associatedDateSeries = + this.item.type === SCThingType.DateSeries + ? Promise.resolve([this.item as SCDateSeries]) + : this.dataProvider + .search({ + filter: { arguments: { - field: 'type', - value: SCThingType.DateSeries, + filters: [ + { + arguments: { + field: 'type', + value: SCThingType.DateSeries, + }, + type: 'value', + }, + { + arguments: { + field: 'event.uid', + value: this.item.uid, + }, + type: 'value', + }, + ], + operation: 'and', }, - type: 'value', + type: 'boolean', }, - { - arguments: { - field: 'event.uid', - value: this.item.uid, - }, - type: 'value', - }, - ], - operation: 'and', - }, - type: 'boolean', - }, - }) - .then((it) => it.data as SCDateSeries[]); - this.associatedDateSeries.then((it) => this.applyState( - it.length < 1 ? AddEventStates.UNAVAILABLE : AddEventStates.REMOVED_ALL)); + }) + .then(it => it.data as SCDateSeries[]); + this.associatedDateSeries.then(it => + this.applyState( + it.length === 0 + ? AddEventStates.UNAVAILABLE + : AddEventStates.REMOVED_ALL, + ), + ); } /** @@ -159,7 +167,10 @@ export class AddEventActionChipComponent implements OnInit { await popover.present(); // TODO: replace dummy implementation await popover.onDidDismiss(); - this.applyState(this.state === AddEventStates.ADDED_ALL ? - AddEventStates.REMOVED_ALL : AddEventStates.ADDED_ALL); + this.applyState( + this.state === AddEventStates.ADDED_ALL + ? AddEventStates.REMOVED_ALL + : AddEventStates.ADDED_ALL, + ); } } diff --git a/src/app/modules/data/chips/data/add-event-action-chip.html b/src/app/modules/data/chips/data/add-event-action-chip.html index 77f4ead0..7ae5dca8 100644 --- a/src/app/modules/data/chips/data/add-event-action-chip.html +++ b/src/app/modules/data/chips/data/add-event-action-chip.html @@ -1,11 +1,14 @@ -
- - - {{label | translate}} +
+ + + {{ label | translate }}
- + diff --git a/src/app/modules/data/chips/data/locate-action-chip.component.ts b/src/app/modules/data/chips/data/locate-action-chip.component.ts index 41486a50..af4a260e 100644 --- a/src/app/modules/data/chips/data/locate-action-chip.component.ts +++ b/src/app/modules/data/chips/data/locate-action-chip.component.ts @@ -1,4 +1,4 @@ -/* tslint:disable:prefer-function-over-method */ +/* eslint-disable class-methods-use-this */ /* * Copyright (C) 2021 StApps * This program is free software: you can redistribute it and/or modify it @@ -36,4 +36,3 @@ export class LocateActionChipComponent { // TODO } } - diff --git a/src/app/modules/data/chips/data/locate-action-chip.html b/src/app/modules/data/chips/data/locate-action-chip.html index f2abd377..db59071c 100644 --- a/src/app/modules/data/chips/data/locate-action-chip.html +++ b/src/app/modules/data/chips/data/locate-action-chip.html @@ -1,7 +1,7 @@ - - - {{'Locate' | translate}} + + + {{ 'Locate' | translate }} - + diff --git a/src/app/modules/data/data-facets.provider.spec.ts b/src/app/modules/data/data-facets.provider.spec.ts index 57af3a5d..ef18a258 100644 --- a/src/app/modules/data/data-facets.provider.spec.ts +++ b/src/app/modules/data/data-facets.provider.spec.ts @@ -25,15 +25,26 @@ describe('DataProvider', () => { let dataFacetsProvider: DataFacetsProvider; const sampleFacets: SCFacet[] = [ { - buckets: [{key: 'education', count: 4}, {key: 'learn', count: 3}, {key: 'computer', count: 3}], + buckets: [ + {key: 'education', count: 4}, + {key: 'learn', count: 3}, + {key: 'computer', count: 3}, + ], field: 'categories', }, { - buckets: [{key: 'Major One', count: 1}, {key: 'Major Two', count: 2}, {key: 'Major Three' , count: 1}], + buckets: [ + {key: 'Major One', count: 1}, + {key: 'Major Two', count: 2}, + {key: 'Major Three', count: 1}, + ], field: 'majors', }, { - buckets: [{key: 'building', count: 3}, {key: 'room', count: 7}], + buckets: [ + {key: 'building', count: 3}, + {key: 'room', count: 7}, + ], field: 'type', }, ]; @@ -51,16 +62,21 @@ describe('DataProvider', () => { ...sampleThingsMap['academic event'], ]; - const sampleBuckets: SCFacetBucket[] = [{key: 'foo', count: 1}, {key: 'bar', count: 2}, {key: 'foo bar', count: 3}]; - const sampleBucketsMap: {[key: string]: number} = {foo: 1, bar: 2, 'foo bar': 3}; + const sampleBuckets: SCFacetBucket[] = [ + {key: 'foo', count: 1}, + {key: 'bar', count: 2}, + {key: 'foo bar', count: 3}, + ]; + const sampleBucketsMap: {[key: string]: number} = { + 'foo': 1, + 'bar': 2, + 'foo bar': 3, + }; beforeEach(() => { TestBed.configureTestingModule({ imports: [DataModule], - providers: [ - DataProvider, - StAppsWebHttpClient, - ], + providers: [DataProvider, StAppsWebHttpClient], }); dataFacetsProvider = TestBed.get(DataFacetsProvider); }); @@ -78,48 +94,76 @@ describe('DataProvider', () => { }); it('should convert buckets to buckets map', () => { - expect(dataFacetsProvider.bucketsToMap(sampleBuckets)).toEqual(sampleBucketsMap); + expect(dataFacetsProvider.bucketsToMap(sampleBuckets)).toEqual( + sampleBucketsMap, + ); }); it('should convert buckets map into buckets', () => { - expect(dataFacetsProvider.mapToBuckets(sampleBucketsMap)).toEqual(sampleBuckets); + expect(dataFacetsProvider.mapToBuckets(sampleBucketsMap)).toEqual( + sampleBuckets, + ); }); it('should convert facets into a facets map', () => { - expect(dataFacetsProvider.facetsToMap(sampleFacets)).toEqual(sampleFacetsMap); + expect(dataFacetsProvider.facetsToMap(sampleFacets)).toEqual( + sampleFacetsMap, + ); }); it('should convert facets map into facets', () => { - expect(dataFacetsProvider.mapToFacets(sampleFacetsMap)).toEqual(sampleFacets); + expect(dataFacetsProvider.mapToFacets(sampleFacetsMap)).toEqual( + sampleFacets, + ); }); it('should extract facets (and append them if needed) from the data', () => { const sampleCombinedFacets: SCFacet[] = [ { buckets: [ - {key: 'computer', count: 3}, {key: 'course', count: 1}, {key: 'education', count: 5}, - {key: 'learn', count: 3}, {key: 'library', count: 1}, {key: 'practicum', count: 1}, - ], + {key: 'computer', count: 3}, + {key: 'course', count: 1}, + {key: 'education', count: 5}, + {key: 'learn', count: 3}, + {key: 'library', count: 1}, + {key: 'practicum', count: 1}, + ], field: 'categories', }, { - buckets: [{key: 'Major One', count: 2}, {key: 'Major Two', count: 4}, {key: 'Major Three', count: 2}], + buckets: [ + {key: 'Major One', count: 2}, + {key: 'Major Two', count: 4}, + {key: 'Major Three', count: 2}, + ], field: 'majors', }, { - buckets: [{key: 'building', count: 4}, {key: 'academic event', count: 2}, {key: 'person', count: 2}, {key: 'room', count: 8}], + buckets: [ + {key: 'building', count: 4}, + {key: 'academic event', count: 2}, + {key: 'person', count: 2}, + {key: 'room', count: 8}, + ], field: 'type', }, ]; const checkEqual = (expected: SCFacet[], actual: SCFacet[]) => { const expectedMap = dataFacetsProvider.facetsToMap(expected); const actualMap = dataFacetsProvider.facetsToMap(actual); - Object.keys(actualMap).forEach((key) => { - Object.keys(actualMap[key]).forEach((subKey) => { + for (const key of Object.keys(actualMap)) { + for (const subKey of Object.keys(actualMap[key])) { expect(actualMap[key][subKey]).toBe(expectedMap[key][subKey]); - }); - }); + } + } }; - checkEqual(dataFacetsProvider.extractFacets(sampleItems, sampleAggregations, sampleFacets), sampleCombinedFacets); + checkEqual( + dataFacetsProvider.extractFacets( + sampleItems, + sampleAggregations, + sampleFacets, + ), + sampleCombinedFacets, + ); }); }); diff --git a/src/app/modules/data/data-facets.provider.ts b/src/app/modules/data/data-facets.provider.ts index cd31ffb5..0524a0dd 100644 --- a/src/app/modules/data/data-facets.provider.ts +++ b/src/app/modules/data/data-facets.provider.ts @@ -13,16 +13,20 @@ * this program. If not, see . */ import {Injectable} from '@angular/core'; -import {SCBackendAggregationConfiguration, SCFacet, SCFacetBucket, SCThing} from '@openstapps/core'; +import { + SCBackendAggregationConfiguration, + SCFacet, + SCFacetBucket, + SCThing, +} from '@openstapps/core'; /** * TODO */ @Injectable() export class DataFacetsProvider { - // tslint:disable-next-line:no-empty - constructor() { - } + // eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function + constructor() {} /** * Adds buckets to a map of buckets (e.g. if a buckets array is [{foo: 1}, {bar: 3}], @@ -32,15 +36,18 @@ export class DataFacetsProvider { * @param bucketsMap Buckets array transformed into a map * @param fields A field that should be added to buckets (its map) */ - // tslint:disable-next-line:prefer-function-over-method - addBuckets(bucketsMap: {[key: string]: number; }, fields: string[]): {[key: string]: number; } { - fields.forEach((field) => { + // eslint-disable-next-line class-methods-use-this + addBuckets( + bucketsMap: {[key: string]: number}, + fields: string[], + ): {[key: string]: number} { + for (const field of fields) { if (typeof bucketsMap[field] !== 'undefined') { bucketsMap[field] = bucketsMap[field] + 1; } else { bucketsMap[field] = 1; } - }); + } return bucketsMap; } @@ -50,12 +57,12 @@ export class DataFacetsProvider { * * @param buckets Buckets from a facet */ - // tslint:disable-next-line:prefer-function-over-method - bucketsToMap(buckets: SCFacetBucket[]): {[key: string]: number; } { - const bucketsMap: {[key: string]: number; } = {}; - buckets.forEach((bucket) => { + // eslint-disable-next-line class-methods-use-this + bucketsToMap(buckets: SCFacetBucket[]): {[key: string]: number} { + const bucketsMap: {[key: string]: number} = {}; + for (const bucket of buckets) { bucketsMap[bucket.key] = bucket.count; - }); + } return bucketsMap; } @@ -70,7 +77,8 @@ export class DataFacetsProvider { extractFacets( items: SCThing[], aggregations: SCBackendAggregationConfiguration[], - facets: SCFacet[] = []): SCFacet[] { + facets: SCFacet[] = [], + ): SCFacet[] { if (items.length === 0) { if (facets.length === 0) { return []; @@ -78,13 +86,16 @@ export class DataFacetsProvider { return facets; } - const combinedFacets: SCFacet[] = facets; - const combinedFacetsMap: {[key: string]: {[key: string]: number; }; } = this.facetsToMap(combinedFacets); - items.forEach((item) => { - aggregations.forEach((aggregation) => { - let fieldValues = item[aggregation.fieldName as keyof SCThing] as string | string[] | undefined; + const combinedFacetsMap: {[key: string]: {[key: string]: number}} = + this.facetsToMap(facets); + for (const item of items) { + for (const aggregation of aggregations) { + let fieldValues = item[aggregation.fieldName as keyof SCThing] as + | string + | string[] + | undefined; if (typeof fieldValues === 'undefined') { - return; + continue; } if (typeof fieldValues === 'string') { fieldValues = [fieldValues]; @@ -94,14 +105,14 @@ export class DataFacetsProvider { combinedFacetsMap[aggregation.fieldName] || {}, fieldValues, ); - } else if (aggregation.onlyOnTypes.indexOf(item.type) !== -1) { + } else if (aggregation.onlyOnTypes.includes(item.type)) { combinedFacetsMap[aggregation.fieldName] = this.addBuckets( combinedFacetsMap[aggregation.fieldName] || {}, fieldValues, ); } - }); - }); + } + } return this.mapToFacets(combinedFacetsMap); } @@ -111,11 +122,11 @@ export class DataFacetsProvider { * * @param facets Array of facets */ - facetsToMap(facets: SCFacet[]): {[key: string]: {[key: string]: number; }; } { - const facetsMap: {[key: string]: {[key: string]: number; }; } = {}; - facets.forEach((facet) => { + facetsToMap(facets: SCFacet[]): {[key: string]: {[key: string]: number}} { + const facetsMap: {[key: string]: {[key: string]: number}} = {}; + for (const facet of facets) { facetsMap[facet.field] = this.bucketsToMap(facet.buckets); - }); + } return facetsMap; } @@ -125,8 +136,8 @@ export class DataFacetsProvider { * * @param bucketsMap A map from a buckets array */ - // tslint:disable-next-line:prefer-function-over-method - mapToBuckets(bucketsMap: {[key: string]: number; }): SCFacetBucket[] { + // eslint-disable-next-line class-methods-use-this + mapToBuckets(bucketsMap: {[key: string]: number}): SCFacetBucket[] { const buckets: SCFacetBucket[] = []; for (const key in bucketsMap) { if (bucketsMap.hasOwnProperty(key)) { @@ -143,7 +154,7 @@ export class DataFacetsProvider { * * @param facetsMap A map from facets array */ - mapToFacets(facetsMap: {[key: string]: {[key: string]: number; }; }): SCFacet[] { + mapToFacets(facetsMap: {[key: string]: {[key: string]: number}}): SCFacet[] { const facets: SCFacet[] = []; for (const key in facetsMap) { if (facetsMap.hasOwnProperty(key)) { diff --git a/src/app/modules/data/data-icon.pipe.ts b/src/app/modules/data/data-icon.pipe.ts index 39ecdd52..31dcf895 100644 --- a/src/app/modules/data/data-icon.pipe.ts +++ b/src/app/modules/data/data-icon.pipe.ts @@ -25,7 +25,7 @@ export class DataIconPipe implements PipeTransform { /** * Mapping from data types to ionic icons to show */ - typeIconMap: {[type in SCThingType] : string; }; + typeIconMap: {[type in SCThingType]: string}; constructor() { this.typeIconMap = { @@ -57,9 +57,9 @@ export class DataIconPipe implements PipeTransform { }; } -/** - * Provide the icon name from the data type - */ + /** + * Provide the icon name from the data type + */ transform(type: SCThingType): string { return this.typeIconMap[type]; } diff --git a/src/app/modules/data/data-routing.module.ts b/src/app/modules/data/data-routing.module.ts index 16787232..217d6291 100644 --- a/src/app/modules/data/data-routing.module.ts +++ b/src/app/modules/data/data-routing.module.ts @@ -28,11 +28,7 @@ const dataRoutes: Routes = [ * Module defining routes for data module */ @NgModule({ - exports: [ - RouterModule, - ], - imports: [ - RouterModule.forChild(dataRoutes), - ], + exports: [RouterModule], + imports: [RouterModule.forChild(dataRoutes)], }) export class DataRoutingModule {} diff --git a/src/app/modules/data/data-routing.service.ts b/src/app/modules/data/data-routing.service.ts index 953b25be..951cd5b6 100644 --- a/src/app/modules/data/data-routing.service.ts +++ b/src/app/modules/data/data-routing.service.ts @@ -34,7 +34,7 @@ export class DataRoutingService { * @param thing The selected thing */ emitChildEvent(thing: SCThings) { - this.childSelectedEvent.next(thing); + this.childSelectedEvent.next(thing); } /** diff --git a/src/app/modules/data/data.module.ts b/src/app/modules/data/data.module.ts index 9fdc5647..ca107e49 100644 --- a/src/app/modules/data/data.module.ts +++ b/src/app/modules/data/data.module.ts @@ -36,112 +36,110 @@ import {DataProvider} from './data.provider'; import {DataDetailContentComponent} from './detail/data-detail-content.component'; import {DataDetailComponent} from './detail/data-detail.component'; import {AddressDetailComponent} from './elements/address-detail.component'; -import {LongInlineText} from './elements/long-inline-text.component'; +import {LongInlineTextComponent} from './elements/long-inline-text.component'; import {OffersDetailComponent} from './elements/offers-detail.component'; import {OffersInListComponent} from './elements/offers-in-list.component'; import {OriginDetailComponent} from './elements/origin-detail.component'; import {OriginInListComponent} from './elements/origin-in-list.component'; import {SimpleCardComponent} from './elements/simple-card.component'; -import {SkeletonListItem} from './elements/skeleton-list-item.component'; -import {SkeletonSegment} from './elements/skeleton-segment-button.component'; -import {SkeletonSimpleCard} from './elements/skeleton-simple-card.component'; -import {DataListItem} from './list/data-list-item.component'; +import {SkeletonListItemComponent} from './elements/skeleton-list-item.component'; +import {SkeletonSegmentComponent} from './elements/skeleton-segment-button.component'; +import {SkeletonSimpleCardComponent} from './elements/skeleton-simple-card.component'; +import {DataListItemComponent} from './list/data-list-item.component'; import {DataListComponent} from './list/data-list.component'; import {FoodDataListComponent} from './list/food-data-list.component'; import {SearchPageComponent} from './list/search-page.component'; import {StAppsWebHttpClient} from './stapps-web-http-client.provider'; import {ArticleDetailContentComponent} from './types/article/article-detail-content.component'; -import {ArticleListItem} from './types/article/article-list-item.component'; +import {ArticleListItemComponent} from './types/article/article-list-item.component'; import {CatalogDetailContentComponent} from './types/catalog/catalog-detail-content.component'; -import {CatalogListItem} from './types/catalog/catalog-list-item.component'; +import {CatalogListItemComponent} from './types/catalog/catalog-list-item.component'; import {DateSeriesDetailContentComponent} from './types/date-series/date-series-detail-content.component'; -import {DateSeriesListItem} from './types/date-series/date-series-list-item.component'; +import {DateSeriesListItemComponent} from './types/date-series/date-series-list-item.component'; import {DishDetailContentComponent} from './types/dish/dish-detail-content.component'; -import {DishListItem} from './types/dish/dish-list-item.component'; +import {DishListItemComponent} from './types/dish/dish-list-item.component'; import {EventDetailContentComponent} from './types/event/event-detail-content.component'; import {EventListItemComponent} from './types/event/event-list-item.component'; import {FavoriteDetailContentComponent} from './types/favorite/favorite-detail-content.component'; -import {FavoriteListItem} from './types/favorite/favorite-list-item.component'; +import {FavoriteListItemComponent} from './types/favorite/favorite-list-item.component'; import {MessageDetailContentComponent} from './types/message/message-detail-content.component'; -import {MessageListItem} from './types/message/message-list-item.component'; +import {MessageListItemComponent} from './types/message/message-list-item.component'; import {OrganizationDetailContentComponent} from './types/organization/organization-detail-content.component'; -import {OrganizationListItem} from './types/organization/organization-list-item.component'; +import {OrganizationListItemComponent} from './types/organization/organization-list-item.component'; import {PersonDetailContentComponent} from './types/person/person-detail-content.component'; -import {PersonListItem} from './types/person/person-list-item.component'; +import {PersonListItemComponent} from './types/person/person-list-item.component'; import {PlaceDetailContentComponent} from './types/place/place-detail-content.component'; -import {PlaceListItem} from './types/place/place-list-item.component'; +import {PlaceListItemComponent} from './types/place/place-list-item.component'; import {PlaceMensaDetailComponent} from './types/place/special/mensa/place-mensa-detail.component'; import {SemesterDetailContentComponent} from './types/semester/semester-detail-content.component'; -import {SemesterListItem} from './types/semester/semester-list-item.component'; +import {SemesterListItemComponent} from './types/semester/semester-list-item.component'; import {VideoDetailContentComponent} from './types/video/video-detail-content.component'; -import {VideoListItem} from './types/video/video-list-item.component'; +import {VideoListItemComponent} from './types/video/video-list-item.component'; /** * Module for handling data */ @NgModule({ declarations: [ + ActionChipListComponent, + AddEventActionChipComponent, AddEventPopoverComponent, - OffersDetailComponent, - OffersInListComponent, AddressDetailComponent, ArticleDetailContentComponent, - ArticleListItem, - SimpleCardComponent, - SkeletonSimpleCard, + ArticleListItemComponent, CatalogDetailContentComponent, - CatalogListItem, + CatalogListItemComponent, DataDetailComponent, DataDetailContentComponent, - FoodDataListComponent, + DataIconPipe, DataListComponent, - DataListItem, + DataListItemComponent, DateSeriesDetailContentComponent, - DateSeriesListItem, + DateSeriesListItemComponent, DishDetailContentComponent, - DishListItem, + DishListItemComponent, EventDetailContentComponent, EventListItemComponent, FavoriteDetailContentComponent, - FavoriteListItem, - LongInlineText, + FavoriteListItemComponent, + FoodDataListComponent, + LocateActionChipComponent, + LongInlineTextComponent, MessageDetailContentComponent, - MessageListItem, + MessageListItemComponent, + OffersDetailComponent, + OffersInListComponent, OrganizationDetailContentComponent, - OrganizationListItem, + OrganizationListItemComponent, OriginDetailComponent, OriginInListComponent, PersonDetailContentComponent, - PersonListItem, + PersonListItemComponent, PlaceDetailContentComponent, - PlaceListItem, + PlaceListItemComponent, PlaceMensaDetailComponent, SearchPageComponent, SemesterDetailContentComponent, - SemesterListItem, - SkeletonListItem, - SkeletonSegment, + SemesterListItemComponent, + SimpleCardComponent, + SkeletonListItemComponent, + SkeletonSegmentComponent, + SkeletonSimpleCardComponent, VideoDetailContentComponent, - VideoListItem, - DataIconPipe, - ActionChipListComponent, - AddEventActionChipComponent, - LocateActionChipComponent, - ], - entryComponents: [ - DataListComponent, + VideoListItemComponent, ], + entryComponents: [DataListComponent], imports: [ - IonicModule.forRoot(), CommonModule, - FormsModule, DataRoutingModule, + FormsModule, HttpClientModule, + IonicModule.forRoot(), MarkdownModule.forRoot(), MenuModule, MomentModule.forRoot({ relativeTimeThresholdOptions: { - 'm': 59, + m: 59, }, }), ScrollingModule, @@ -149,12 +147,6 @@ import {VideoListItem} from './types/video/video-list-item.component'; TranslateModule.forChild(), ThingTranslateModule.forChild(), ], - providers: [ - DataProvider, - DataFacetsProvider, - Network, - StAppsWebHttpClient, - ], + providers: [DataProvider, DataFacetsProvider, Network, StAppsWebHttpClient], }) -export class DataModule { -} +export class DataModule {} diff --git a/src/app/modules/data/data.provider.spec.ts b/src/app/modules/data/data.provider.spec.ts index 6f486fdd..96789608 100644 --- a/src/app/modules/data/data.provider.spec.ts +++ b/src/app/modules/data/data.provider.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion,@typescript-eslint/ban-ts-comment,@typescript-eslint/no-explicit-any */ /* * Copyright (C) 2018, 2019 StApps * This program is free software: you can redistribute it and/or modify it @@ -15,8 +16,17 @@ import {TestBed} from '@angular/core/testing'; import {Client} from '@openstapps/api/lib/client'; import { - SCDish, SCMessage, SCMultiSearchRequest, SCSaveableThing, SCSearchQuery, - SCSearchResponse, SCSearchValueFilter, SCThing, SCThingOriginType, SCThings, SCThingType, + SCDish, + SCMessage, + SCMultiSearchRequest, + SCSaveableThing, + SCSearchQuery, + SCSearchResponse, + SCSearchValueFilter, + SCThing, + SCThingOriginType, + SCThings, + SCThingType, } from '@openstapps/core'; import {sampleThingsMap} from '../../_helpers/data/sample-things'; import {StorageProvider} from '../storage/storage.provider'; @@ -66,15 +76,16 @@ describe('DataProvider', () => { type: SCThingType.Message, uid: sampleThing.uid, }; - const otherSampleThing: SCMessage = {...sampleThing, uid: 'message-456', name: 'bar'}; + const otherSampleThing: SCMessage = { + ...sampleThing, + uid: 'message-456', + name: 'bar', + }; beforeEach(async () => { TestBed.configureTestingModule({ imports: [DataModule], - providers: [ - DataProvider, - StAppsWebHttpClient, - ], + providers: [DataProvider, StAppsWebHttpClient], }); storageProvider = TestBed.get(StorageProvider); dataProvider = TestBed.get(DataProvider); @@ -128,26 +139,29 @@ describe('DataProvider', () => { }; dataProvider.backendQueriesLimit = 2; - spyOn(Client.prototype as any, 'multiSearch').and.callFake((req: SCMultiSearchRequest) => ({ - then: (callback: any) => { - let i = 0; - for (const key in req) { - if (req.hasOwnProperty(key)) { - i++; - // @ts-ignore - expect(requestCheck[key]).not.toBeNull(); - expect(requestCheck[key]).toEqual(req[key]); - // @ts-ignore - requestCheck[key] = null; - // @ts-ignore - req[key] = req[key].toUpperCase(); + spyOn(Client.prototype as any, 'multiSearch').and.callFake( + (request_: SCMultiSearchRequest) => ({ + then: (callback: any) => { + let i = 0; + for (const key in request_) { + if (request_.hasOwnProperty(key)) { + i++; + // @ts-ignore + expect(requestCheck[key]).not.toBeNull(); + expect(requestCheck[key]).toEqual(request_[key]); + // @ts-ignore + // eslint-disable-next-line unicorn/no-null + requestCheck[key] = null; + // @ts-ignore + request_[key] = request_[key].toUpperCase(); + } } - } - expect(i).toBeLessThanOrEqual(dataProvider.backendQueriesLimit); + expect(i).toBeLessThanOrEqual(dataProvider.backendQueriesLimit); - return callback(req); - }, - })); + return callback(request_); + }, + }), + ); const response = await dataProvider.multiSearch(request); expect(response).toEqual(responseShould); @@ -155,10 +169,12 @@ describe('DataProvider', () => { it('should put an data item into the local database (storage)', async () => { let providedThing: SCSaveableThing; - spyOn(storageProvider, 'put' as any).and.callFake((_id: any, thing: any) => { - providedThing = thing; - providedThing.origin.created = sampleSavable.origin.created; - }); + spyOn(storageProvider, 'put' as any).and.callFake( + (_id: any, thing: any) => { + providedThing = thing; + providedThing.origin.created = sampleSavable.origin.created; + }, + ); expect(storageProvider.put).not.toHaveBeenCalled(); expect(providedThing!).not.toBeDefined(); await dataProvider.put(sampleThing); @@ -170,9 +186,14 @@ describe('DataProvider', () => { await dataProvider.put(sampleThing); spyOn(storageProvider, 'get').and.callThrough(); expect(storageProvider.get).not.toHaveBeenCalled(); - const providedThing = await dataProvider.get(sampleThing.uid, DataScope.Local); + const providedThing = await dataProvider.get( + sampleThing.uid, + DataScope.Local, + ); providedThing.origin.created = sampleSavable.origin.created; - expect(storageProvider.get).toHaveBeenCalledWith(dataProvider.getDataKey(sampleThing.uid)); + expect(storageProvider.get).toHaveBeenCalledWith( + dataProvider.getDataKey(sampleThing.uid), + ); expect(providedThing).toEqual(sampleSavable); }); @@ -180,11 +201,16 @@ describe('DataProvider', () => { await dataProvider.put(sampleThing); await dataProvider.put(otherSampleThing); const result = await dataProvider.getAll(); - expect(Array.from(result.keys()).sort()).toEqual([ - dataProvider.getDataKey(sampleThing.uid), dataProvider.getDataKey(otherSampleThing.uid), + expect([...result.keys()].sort()).toEqual([ + dataProvider.getDataKey(sampleThing.uid), + dataProvider.getDataKey(otherSampleThing.uid), ]); - expect(result.get(dataProvider.getDataKey(sampleThing.uid))!.data).toEqual(sampleThing); - expect(result.get(dataProvider.getDataKey(otherSampleThing.uid))!.data).toEqual(otherSampleThing); + expect(result.get(dataProvider.getDataKey(sampleThing.uid))!.data).toEqual( + sampleThing, + ); + expect( + result.get(dataProvider.getDataKey(otherSampleThing.uid))!.data, + ).toEqual(otherSampleThing); }); it('should provide single data from the backend', async () => { @@ -196,7 +222,10 @@ describe('DataProvider', () => { }; }); expect(Client.prototype.getThing).not.toHaveBeenCalled(); - const providedThing = await dataProvider.get(sampleThing.uid, DataScope.Remote); + const providedThing = await dataProvider.get( + sampleThing.uid, + DataScope.Remote, + ); expect(Client.prototype.getThing).toHaveBeenCalledWith(sampleThing.uid); expect(providedThing).toBe(sampleThing); }); @@ -226,7 +255,9 @@ describe('DataProvider', () => { await dataProvider.put(sampleThing); expect(await storageProvider.length()).toBe(1); await dataProvider.delete(sampleThing.uid); - expect(storageProvider.delete).toHaveBeenCalledWith(dataProvider.getDataKey(sampleThing.uid)); + expect(storageProvider.delete).toHaveBeenCalledWith( + dataProvider.getDataKey(sampleThing.uid), + ); expect(await storageProvider.length()).toBe(0); }); @@ -242,7 +273,7 @@ describe('DataProvider', () => { dataProvider.getDataKey(otherSampleThing.uid), ); const result = await storageProvider.getAll(); - expect(Array.from(result.keys())).toEqual(['some-uid']); + expect([...result.keys()]).toEqual(['some-uid']); }); it('should properly check if a data item has already been saved', async () => { diff --git a/src/app/modules/data/data.provider.ts b/src/app/modules/data/data.provider.ts index bd7a8d18..96aa5c65 100644 --- a/src/app/modules/data/data.provider.ts +++ b/src/app/modules/data/data.provider.ts @@ -15,7 +15,8 @@ import {Injectable} from '@angular/core'; import {Client} from '@openstapps/api/lib/client'; import { - SCMultiSearchRequest, SCMultiSearchResponse, + SCMultiSearchRequest, + SCMultiSearchResponse, SCSearchRequest, SCSearchResponse, SCThingOriginType, @@ -43,7 +44,6 @@ export enum DataScope { providedIn: 'root', }) export class DataProvider { - /** * TODO */ @@ -57,26 +57,32 @@ export class DataProvider { set storagePrefix(storagePrefix) { this._storagePrefix = storagePrefix; } + /** * TODO */ private _storagePrefix = 'stapps.data'; + /** * Version of the app (used for the header in communication with the backend) */ appVersion = environment.backend_version; + /** * Maximum number of sub-queries in a multi-query allowed by the backend */ backendQueriesLimit = 5; + /** * TODO */ backendUrl = environment.backend_url; + /** * TODO */ client: Client; + /** * TODO */ @@ -88,8 +94,15 @@ export class DataProvider { * @param stAppsWebHttpClient TODO * @param storageProvider TODO */ - constructor(stAppsWebHttpClient: StAppsWebHttpClient, storageProvider: StorageProvider) { - this.client = new Client(stAppsWebHttpClient, this.backendUrl, this.appVersion); + constructor( + stAppsWebHttpClient: StAppsWebHttpClient, + storageProvider: StorageProvider, + ) { + this.client = new Client( + stAppsWebHttpClient, + this.backendUrl, + this.appVersion, + ); this.storageProvider = storageProvider; } @@ -106,7 +119,7 @@ export class DataProvider { * Delete all the previously saved data items */ async deleteAll(): Promise { - const keys = Array.from((await this.getAll()).keys()); + const keys = [...(await this.getAll()).keys()]; return this.storageProvider.delete(...keys); } @@ -114,15 +127,23 @@ export class DataProvider { /** * Provides a savable thing from the local database using the provided UID */ - async get(uid: string, scope: DataScope.Local): Promise>; + async get( + uid: string, + scope: DataScope.Local, + ): Promise>; /** * Provides a thing from the backend */ - async get(uid: string, scope: DataScope.Remote): Promise>; + async get( + uid: string, + scope: DataScope.Remote, + ): Promise>; /** * Provides a thing from both local database and backend */ - async get(uid: string): Promise>>; + async get( + uid: string, + ): Promise>>; /** * Provides a thing from the local database only, backend only or both, depending on the scope @@ -130,26 +151,36 @@ export class DataProvider { * @param uid Unique identifier of a thing * @param scope From where data should be provided */ - async get(uid: string, scope?: DataScope): - Promise | Map>> { - if (scope === DataScope.Local) { - return this.storageProvider.get>(this.getDataKey(uid)); - } - if (scope === DataScope.Remote) { - return this.client.getThing(uid); - } - const map: Map> = new Map(); - map.set(DataScope.Local, await this.get(uid, DataScope.Local)); - map.set(DataScope.Remote, await this.get(uid, DataScope.Remote)); - - return map; + async get( + uid: string, + scope?: DataScope, + ): Promise< + | SCThings + | SCSaveableThing + | Map> + > { + if (scope === DataScope.Local) { + return this.storageProvider.get>( + this.getDataKey(uid), + ); } + if (scope === DataScope.Remote) { + return this.client.getThing(uid); + } + const map: Map> = new Map(); + map.set(DataScope.Local, await this.get(uid, DataScope.Local)); + map.set(DataScope.Remote, await this.get(uid, DataScope.Remote)); + + return map; + } /** * Provides all things saved in the local database */ async getAll(): Promise>> { - return this.storageProvider.search>(this.storagePrefix); + return this.storageProvider.search>( + this.storagePrefix, + ); } /** @@ -175,11 +206,18 @@ export class DataProvider { * * @param query - query to send to the backend (auto-splits according to the backend limit) */ - async multiSearch(query: SCMultiSearchRequest): Promise { + async multiSearch( + query: SCMultiSearchRequest, + ): Promise { // partition object into chunks, process those requests in parallel, then merge their responses again - return Object.assign({}, ...(await Promise.all(chunk(toPairs(query), this.backendQueriesLimit) - .map((request) => this.client.multiSearch(fromPairs(request))), - ))); + return Object.assign( + {}, + ...(await Promise.all( + chunk(toPairs(query), this.backendQueriesLimit).map(request => + this.client.multiSearch(fromPairs(request)), + ), + )), + ); } /** @@ -188,7 +226,10 @@ export class DataProvider { * @param item Data item that needs to be saved * @param [type] Savable type (e.g. 'favorite'); if nothing is provided then type of the thing is used */ - async put(item: SCThings, type?: SCThingType): Promise> { + async put( + item: SCThings, + type?: SCThingType, + ): Promise> { const savableItem: SCSaveableThing = { data: item, name: item.name, @@ -196,12 +237,15 @@ export class DataProvider { created: new Date().toISOString(), type: SCThingOriginType.User, }, - type: (typeof type === 'undefined') ? item.type : type, + type: typeof type === 'undefined' ? item.type : type, uid: item.uid, }; // @TODO: Implementation for saving item into the backend (user's account) - return ( this.storageProvider.put>(this.getDataKey(item.uid), savableItem)); + return this.storageProvider.put>( + this.getDataKey(item.uid), + savableItem, + ); } /** @@ -210,6 +254,6 @@ export class DataProvider { * @param query - query to send to the backend */ async search(query: SCSearchRequest): Promise { - return (this.client.search(query)); + return this.client.search(query); } } diff --git a/src/app/modules/data/detail/data-detail-content.component.ts b/src/app/modules/data/detail/data-detail-content.component.ts index 96e1c864..6dc7d06f 100644 --- a/src/app/modules/data/detail/data-detail-content.component.ts +++ b/src/app/modules/data/detail/data-detail-content.component.ts @@ -27,5 +27,4 @@ export class DataDetailContentComponent { * TODO */ @Input() item: SCThings; - } diff --git a/src/app/modules/data/detail/data-detail-content.html b/src/app/modules/data/detail/data-detail-content.html index 8d2815bb..78e0ac98 100644 --- a/src/app/modules/data/detail/data-detail-content.html +++ b/src/app/modules/data/detail/data-detail-content.html @@ -1,19 +1,68 @@ - +
- - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
diff --git a/src/app/modules/data/detail/data-detail.component.spec.ts b/src/app/modules/data/detail/data-detail.component.spec.ts index 182b062f..c9945323 100644 --- a/src/app/modules/data/detail/data-detail.component.spec.ts +++ b/src/app/modules/data/detail/data-detail.component.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any */ /* * Copyright (C) 2018, 2019 StApps * This program is free software: you can redistribute it and/or modify it @@ -16,7 +17,11 @@ import {CUSTOM_ELEMENTS_SCHEMA, DebugElement} from '@angular/core'; import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ActivatedRoute, RouterModule} from '@angular/router'; import {IonRefresher, IonTitle} from '@ionic/angular'; -import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core'; +import { + TranslateLoader, + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import {sampleThingsMap} from '../../../_helpers/data/sample-things'; import {DataRoutingModule} from '../data-routing.module'; import {DataModule} from '../data.module'; @@ -59,21 +64,26 @@ describe('DataDetailComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [RouterModule.forRoot([]), DataRoutingModule, DataModule, - TranslateModule.forRoot({ - loader: {provide: TranslateLoader, useClass: TranslateFakeLoader}, - })], + imports: [ + RouterModule.forRoot([]), + DataRoutingModule, + DataModule, + TranslateModule.forRoot({ + loader: {provide: TranslateLoader, useClass: TranslateFakeLoader}, + }), + ], providers: [{provide: ActivatedRoute, useValue: fakeActivatedRoute}], schemas: [CUSTOM_ELEMENTS_SCHEMA], - }) - .compileComponents(); + }).compileComponents(); })); beforeEach(async () => { dataProvider = TestBed.get(DataProvider); translateService = TestBed.get(TranslateService); refresher = jasmine.createSpyObj('refresher', ['complete']); - spyOn(dataProvider, 'get' as any).and.returnValue(Promise.resolve(sampleThing)); + spyOn(dataProvider, 'get' as any).and.returnValue( + Promise.resolve(sampleThing), + ); spyOn(DataDetailComponent.prototype, 'getItem').and.callThrough(); fixture = await TestBed.createComponent(DataDetailComponent); comp = fixture.componentInstance; @@ -83,28 +93,33 @@ describe('DataDetailComponent', () => { await dataProvider.deleteAll(); }); - it('should create component', () => - expect(comp).toBeDefined(), - ); + it('should create component', () => expect(comp).toBeDefined()); it('should have appropriate title', async () => { const title: DebugElement | null = detailPage.query(By.directive(IonTitle)); + // eslint-disable-next-line unicorn/no-null expect(title).not.toBe(null); expect(title!.nativeElement.textContent).toBe('Foo'); }); it('should get a data item', () => { comp.getItem(sampleThing.uid); - expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(sampleThing.uid); + expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith( + sampleThing.uid, + ); }); it('should get a data item when component is accessed', async () => { - expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(sampleThing.uid); + expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith( + sampleThing.uid, + ); }); it('should update the data item when refresh is called', async () => { await comp.refresh(refresher); - expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(sampleThing.uid); + expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith( + sampleThing.uid, + ); expect(refresher.complete).toHaveBeenCalled(); }); }); diff --git a/src/app/modules/data/detail/data-detail.component.ts b/src/app/modules/data/detail/data-detail.component.ts index 8772d571..bd527f6b 100644 --- a/src/app/modules/data/detail/data-detail.component.ts +++ b/src/app/modules/data/detail/data-detail.component.ts @@ -17,7 +17,12 @@ import {ActivatedRoute} from '@angular/router'; import {Network} from '@ionic-native/network/ngx'; import {IonRefresher} from '@ionic/angular'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; -import {SCLanguageCode, SCSaveableThing, SCThings, SCUuid} from '@openstapps/core'; +import { + SCLanguageCode, + SCSaveableThing, + SCThings, + SCUuid, +} from '@openstapps/core'; import {DataProvider, DataScope} from '../data.provider'; /** @@ -44,7 +49,9 @@ export class DataDetailComponent implements OnInit { /** * Type guard for SCSavableThing */ - static isSCSavableThing(thing: SCThings | SCSaveableThing): thing is SCSaveableThing { + static isSCSavableThing( + thing: SCThings | SCSaveableThing, + ): thing is SCSaveableThing { return typeof (thing as SCSaveableThing).data !== 'undefined'; } @@ -55,10 +62,12 @@ export class DataDetailComponent implements OnInit { * @param network the network provider * @param translateService the translation service */ - constructor(private readonly route: ActivatedRoute, - private readonly dataProvider: DataProvider, - private readonly network: Network, - translateService: TranslateService) { + constructor( + private readonly route: ActivatedRoute, + private readonly dataProvider: DataProvider, + private readonly network: Network, + translateService: TranslateService, + ) { this.language = translateService.currentLang as SCLanguageCode; translateService.onLangChange.subscribe((event: LangChangeEvent) => { this.language = event.lang as SCLanguageCode; @@ -74,7 +83,8 @@ export class DataDetailComponent implements OnInit { try { const item = await this.dataProvider.get(uid, DataScope.Remote); this.item = DataDetailComponent.isSCSavableThing(item) ? item.data : item; - } catch (_) { + } catch { + // eslint-disable-next-line unicorn/no-null this.item = null; } } @@ -99,7 +109,9 @@ export class DataDetailComponent implements OnInit { * @param refresher Refresher component that triggers the update */ async refresh(refresher: IonRefresher) { - await this.getItem(this.item?.uid ?? this.route.snapshot.paramMap.get('uid') ?? ''); + await this.getItem( + this.item?.uid ?? this.route.snapshot.paramMap.get('uid') ?? '', + ); await refresher.complete(); } } diff --git a/src/app/modules/data/detail/data-detail.html b/src/app/modules/data/detail/data-detail.html index a07bf679..b680ae6a 100644 --- a/src/app/modules/data/detail/data-detail.html +++ b/src/app/modules/data/detail/data-detail.html @@ -1,23 +1,25 @@ - - - - - {{'data.detail.TITLE' | translate}} + + + + + {{ 'data.detail.TITLE' | translate }} - +
- -
- - + +
+ {{ 'data.detail.COULD_NOT_CONNECT' | translate }} @@ -25,8 +27,7 @@
- - + {{ 'data.detail.NOT_FOUND' | translate }} @@ -39,14 +40,17 @@ - +
-

{{item.name}}

- {{item.type}} +

{{ item.name }}

+ {{ item.type }}
diff --git a/src/app/modules/data/elements/address-detail.html b/src/app/modules/data/elements/address-detail.html index 4345ae12..4c60ad3e 100644 --- a/src/app/modules/data/elements/address-detail.html +++ b/src/app/modules/data/elements/address-detail.html @@ -1,41 +1,57 @@ - {{'data.detail.address.TITLE' | translate | titlecase}} + {{ + 'data.detail.address.TITLE' | translate | titlecase + }} - {{'data.detail.address.STREET' | translate | titlecase}}: + {{ 'data.detail.address.STREET' | translate | titlecase }}: - {{address.streetAddress}} + {{ address.streetAddress }} - {{'data.detail.address.POSTCODE' | translate | titlecase}}: + {{ + 'data.detail.address.POSTCODE' | translate | titlecase + }}: - {{address.postalCode}} + {{ address.postalCode }} - {{'data.detail.address.CITY' | translate | titlecase}}: + {{ 'data.detail.address.CITY' | translate | titlecase }}: - {{address.addressLocality}} + {{ address.addressLocality }} - {{'data.detail.address.REGION' | translate | titlecase}}: + {{ 'data.detail.address.REGION' | translate | titlecase }}: - {{address.addressRegion}} + {{ address.addressRegion }} - {{'data.detail.address.COUNTRY' | translate | titlecase}}: + {{ 'data.detail.address.COUNTRY' | translate | titlecase }}: - {{address.addressCountry}} + {{ address.addressCountry }} - {{'data.detail.address.POST_OFFICE_BOX' | translate | titlecase}} + {{ + 'data.detail.address.POST_OFFICE_BOX' | translate | titlecase + }} - {{address.postOfficeBoxNumber}} + {{ address.postOfficeBoxNumber }} diff --git a/src/app/modules/data/elements/long-inline-text.component.ts b/src/app/modules/data/elements/long-inline-text.component.ts index 9314b269..41ee3434 100644 --- a/src/app/modules/data/elements/long-inline-text.component.ts +++ b/src/app/modules/data/elements/long-inline-text.component.ts @@ -21,11 +21,12 @@ import {Component, Input} from '@angular/core'; selector: 'stapps-long-inline-text', templateUrl: 'long-inline-text.html', }) -export class LongInlineText { +export class LongInlineTextComponent { /** * TODO */ @Input() size: number; + /** * TODO */ diff --git a/src/app/modules/data/elements/long-inline-text.html b/src/app/modules/data/elements/long-inline-text.html index e51f40eb..089f104c 100644 --- a/src/app/modules/data/elements/long-inline-text.html +++ b/src/app/modules/data/elements/long-inline-text.html @@ -1 +1,3 @@ -{{text | slice:0:size}}... +{{ text | slice: 0:size }}... diff --git a/src/app/modules/data/elements/offers-detail.component.ts b/src/app/modules/data/elements/offers-detail.component.ts index 94fb390e..ecd8ef03 100644 --- a/src/app/modules/data/elements/offers-detail.component.ts +++ b/src/app/modules/data/elements/offers-detail.component.ts @@ -13,7 +13,10 @@ * this program. If not, see . */ import {Component, Input} from '@angular/core'; -import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core'; +import { + SCAcademicPriceGroup, + SCThingThatCanBeOfferedOffer, +} from '@openstapps/core'; /** * TODO @@ -27,6 +30,7 @@ export class OffersDetailComponent { * TODO */ objectKeys = Object.keys; + /** * TODO */ diff --git a/src/app/modules/data/elements/offers-detail.html b/src/app/modules/data/elements/offers-detail.html index 1c1cc213..eda8f0cf 100644 --- a/src/app/modules/data/elements/offers-detail.html +++ b/src/app/modules/data/elements/offers-detail.html @@ -1,19 +1,40 @@ - {{'data.detail.offers.TITLE' | translate | titlecase}} + {{ + 'data.detail.offers.TITLE' | translate | titlecase + }}

- {{'name' | thingTranslate: offer.inPlace}},  - - {{offer.availabilityStarts | amDateFormat:'ll'}} + {{ + 'name' | thingTranslate: offer.inPlace + }},  + + + {{ + (offer.availabilityRange.gt + ? offer.availabilityRange.gt + : offer.availabilityRange.gte + ) | amDateFormat: 'll' + }}

- {{group | titlecase}} + {{ group | titlecase }} -

{{offer.prices[group] | currency:'EUR':'symbol':undefined:'de'}}

+

+ {{ + offer.prices[group] | currency: 'EUR':'symbol':undefined:'de' + }} +

diff --git a/src/app/modules/data/elements/offers-in-list.component.ts b/src/app/modules/data/elements/offers-in-list.component.ts index 38dbe4eb..da2ac50e 100644 --- a/src/app/modules/data/elements/offers-in-list.component.ts +++ b/src/app/modules/data/elements/offers-in-list.component.ts @@ -13,7 +13,10 @@ * this program. If not, see . */ import {Component, Input} from '@angular/core'; -import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core'; +import { + SCAcademicPriceGroup, + SCThingThatCanBeOfferedOffer, +} from '@openstapps/core'; /** * TODO diff --git a/src/app/modules/data/elements/offers-in-list.html b/src/app/modules/data/elements/offers-in-list.html index 0c5a0e9a..96c7e8f3 100644 --- a/src/app/modules/data/elements/offers-in-list.html +++ b/src/app/modules/data/elements/offers-in-list.html @@ -1,6 +1,9 @@
-

{{offers[0].prices.default | currency:'EUR':'symbol':undefined:'de'}}

+

+ {{ offers[0].prices.default | currency: 'EUR':'symbol':undefined:'de' }} +

- {{offers[0].inPlace.name}}... + {{ offers[0].inPlace.name + }}...

diff --git a/src/app/modules/data/elements/origin-detail.html b/src/app/modules/data/elements/origin-detail.html index 09d01f89..4c73e1e4 100644 --- a/src/app/modules/data/elements/origin-detail.html +++ b/src/app/modules/data/elements/origin-detail.html @@ -1,27 +1,61 @@ - {{'data.types.origin.TITLE' | translate | titlecase}}: {{'data.types.origin.USER' | translate | titlecase}} + {{ 'data.types.origin.TITLE' | translate | titlecase }}: + {{ 'data.types.origin.USER' | translate | titlecase }} -

{{'data.types.origin.detail.CREATED' | translate | titlecase}}: {{origin.created | amDateFormat:'ll'}}

-

{{'data.types.origin.detail.UPDATED' | translate | titlecase}}: {{origin.updated | amDateFormat:'ll'}}

-

{{'data.types.origin.detail.MODIFIED' | translate | titlecase}}: {{origin.modified | amDateFormat:'ll'}}

-

{{'data.types.origin.detail.MAINTAINER' | translate }}: {{origin.name}}

+

+ {{ 'data.types.origin.detail.CREATED' | translate | titlecase }}: + {{ origin.created | amDateFormat: 'll' }} +

+

+ {{ 'data.types.origin.detail.UPDATED' | translate | titlecase }}: + {{ origin.updated | amDateFormat: 'll' }} +

+

+ {{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}: + {{ origin.modified | amDateFormat: 'll' }} +

+

+ {{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }} +

- {{'data.types.origin.detail.MAINTAINER' | translate }}: {{origin.maintainer.name}} + {{ 'data.types.origin.detail.MAINTAINER' | translate }}: + {{ + origin.maintainer.name + }}

- {{'data.types.origin.TITLE' | translate | titlecase}}: {{'data.types.origin.REMOTE' | translate | titlecase}} + {{ 'data.types.origin.TITLE' | translate | titlecase }}: + {{ 'data.types.origin.REMOTE' | translate | titlecase }} -

{{'data.types.origin.detail.INDEXED' | translate | titlecase}}: {{origin.indexed | amDateFormat:'ll'}}

-

{{'data.types.origin.detail.MODIFIED' | translate | titlecase}}: {{origin.modified | amDateFormat:'ll'}}

-

{{'data.types.origin.detail.MAINTAINER' | translate }}: {{origin.name}}

+

+ {{ 'data.types.origin.detail.INDEXED' | translate | titlecase }}: + {{ origin.indexed | amDateFormat: 'll' }} +

+

+ {{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}: + {{ origin.modified | amDateFormat: 'll' }} +

+

+ {{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }} +

- {{'data.types.origin.detail.MAINTAINER' | translate | titlecase}}: {{origin.maintainer.name}} + {{ 'data.types.origin.detail.MAINTAINER' | translate | titlecase }}: + {{ + origin.maintainer.name + }}

- {{'data.types.origin.detail.RESPONSIBLE' | translate | titlecase}}: {{origin.responsibleEntity.name}} + {{ 'data.types.origin.detail.RESPONSIBLE' | translate | titlecase }}: + {{ + origin.responsibleEntity.name + }}

diff --git a/src/app/modules/data/elements/origin-in-list.html b/src/app/modules/data/elements/origin-in-list.html index 4dd7fc10..6c406b4d 100644 --- a/src/app/modules/data/elements/origin-in-list.html +++ b/src/app/modules/data/elements/origin-in-list.html @@ -1,7 +1,7 @@
-

{{origin.created | amDateFormat:'ll'}}

+

{{ origin.created | amDateFormat: 'll' }}

-

{{origin.indexed | amDateFormat:'ll'}}

+

{{ origin.indexed | amDateFormat: 'll' }}

diff --git a/src/app/modules/data/elements/simple-card.component.ts b/src/app/modules/data/elements/simple-card.component.ts index 7cbd3056..57084006 100644 --- a/src/app/modules/data/elements/simple-card.component.ts +++ b/src/app/modules/data/elements/simple-card.component.ts @@ -27,29 +27,34 @@ export class SimpleCardComponent { * TODO */ areThings = false; + /** * TODO */ @Input() content: string | string[] | SCThing[]; + /** * TODO */ @Input() isMarkdown = false; + /** * TODO */ @Input() title: string; + /** * TODO */ - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this isString(data: unknown): data is string { return typeof data === 'string'; } + /** * TODO */ - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this isThing(something: unknown): something is SCThing { return isThing(something); } diff --git a/src/app/modules/data/elements/simple-card.html b/src/app/modules/data/elements/simple-card.html index 06e01fa8..49889ff6 100644 --- a/src/app/modules/data/elements/simple-card.html +++ b/src/app/modules/data/elements/simple-card.html @@ -1,26 +1,29 @@ - {{title}} + {{ title }} - + -

{{content}}

+

{{ content }}

- + - -

{{'name' | thingTranslate: thing}}

+
+

{{ 'name' | thingTranslate: thing }}

-

{{text}}

+

{{ text }}

diff --git a/src/app/modules/data/elements/skeleton-list-item.component.ts b/src/app/modules/data/elements/skeleton-list-item.component.ts index 8647283c..0fb5dbff 100644 --- a/src/app/modules/data/elements/skeleton-list-item.component.ts +++ b/src/app/modules/data/elements/skeleton-list-item.component.ts @@ -22,5 +22,4 @@ import {Component} from '@angular/core'; templateUrl: 'skeleton-list-item.html', styleUrls: ['skeleton-list-item.scss'], }) -export class SkeletonListItem { -} +export class SkeletonListItemComponent {} diff --git a/src/app/modules/data/elements/skeleton-list-item.html b/src/app/modules/data/elements/skeleton-list-item.html index 80593d77..a205b15d 100644 --- a/src/app/modules/data/elements/skeleton-list-item.html +++ b/src/app/modules/data/elements/skeleton-list-item.html @@ -1,18 +1,18 @@ - + -

- +

+

- +

- +
diff --git a/src/app/modules/data/elements/skeleton-segment-button.component.ts b/src/app/modules/data/elements/skeleton-segment-button.component.ts index dae4a0df..4d747806 100644 --- a/src/app/modules/data/elements/skeleton-segment-button.component.ts +++ b/src/app/modules/data/elements/skeleton-segment-button.component.ts @@ -21,5 +21,4 @@ import {Component} from '@angular/core'; selector: 'stapps-skeleton-segment-button', templateUrl: 'skeleton-segment-button.html', }) -export class SkeletonSegment { -} +export class SkeletonSegmentComponent {} diff --git a/src/app/modules/data/elements/skeleton-segment-button.html b/src/app/modules/data/elements/skeleton-segment-button.html index ad9cad92..edf95f6b 100644 --- a/src/app/modules/data/elements/skeleton-segment-button.html +++ b/src/app/modules/data/elements/skeleton-segment-button.html @@ -1,4 +1,3 @@ - + - diff --git a/src/app/modules/data/elements/skeleton-simple-card.component.ts b/src/app/modules/data/elements/skeleton-simple-card.component.ts index 71c0beb5..3c00da6a 100644 --- a/src/app/modules/data/elements/skeleton-simple-card.component.ts +++ b/src/app/modules/data/elements/skeleton-simple-card.component.ts @@ -21,5 +21,4 @@ import {Component} from '@angular/core'; selector: 'stapps-skeleton-simple-card', templateUrl: 'skeleton-simple-card.html', }) -export class SkeletonSimpleCard { -} +export class SkeletonSimpleCardComponent {} diff --git a/src/app/modules/data/elements/skeleton-simple-card.html b/src/app/modules/data/elements/skeleton-simple-card.html index a8f317c1..2e51180b 100644 --- a/src/app/modules/data/elements/skeleton-simple-card.html +++ b/src/app/modules/data/elements/skeleton-simple-card.html @@ -3,6 +3,6 @@ -

+

diff --git a/src/app/modules/data/list/data-list-item.component.ts b/src/app/modules/data/list/data-list-item.component.ts index 9bcfa883..9966f69e 100644 --- a/src/app/modules/data/list/data-list-item.component.ts +++ b/src/app/modules/data/list/data-list-item.component.ts @@ -24,7 +24,7 @@ import {DataRoutingService} from '../data-routing.service'; styleUrls: ['data-list-item.scss'], templateUrl: 'data-list-item.html', }) -export class DataListItem { +export class DataListItemComponent { /** * Whether or not the list item should show a thumbnail */ diff --git a/src/app/modules/data/list/data-list-item.html b/src/app/modules/data/list/data-list-item.html index 19ad4088..1dae60a2 100644 --- a/src/app/modules/data/list/data-list-item.html +++ b/src/app/modules/data/list/data-list-item.html @@ -1,36 +1,90 @@ - -
- - + +
+ + - +
- - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

- {{'name' | thingTranslate: item}} + {{ 'name' | thingTranslate: item }}

-

- +

+

- +
diff --git a/src/app/modules/data/list/data-list.component.spec.ts b/src/app/modules/data/list/data-list.component.spec.ts index 9f4ec078..db9f8b74 100644 --- a/src/app/modules/data/list/data-list.component.spec.ts +++ b/src/app/modules/data/list/data-list.component.spec.ts @@ -9,12 +9,9 @@ describe('DataListComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ DataListComponent ], - imports: [ - TranslateModule.forRoot(), - ] - }) - .compileComponents(); + declarations: [DataListComponent], + imports: [TranslateModule.forRoot()], + }).compileComponents(); })); beforeEach(() => { diff --git a/src/app/modules/data/list/data-list.component.ts b/src/app/modules/data/list/data-list.component.ts index fdf3242a..9b7de7c5 100644 --- a/src/app/modules/data/list/data-list.component.ts +++ b/src/app/modules/data/list/data-list.component.ts @@ -19,6 +19,7 @@ import { HostListener, Input, OnChanges, + OnDestroy, OnInit, Output, SimpleChanges, @@ -36,41 +37,48 @@ import {BehaviorSubject, Observable, Subscription} from 'rxjs'; templateUrl: 'data-list.html', styleUrls: ['data-list.scss'], }) - -export class DataListComponent implements OnChanges, OnInit { +export class DataListComponent implements OnChanges, OnInit, OnDestroy { /** * Amount of list items left to show (in percent) that should trigger a data reload */ private readonly reloadThreshold = 0.2; + /** * All SCThings to display */ @Input() items?: SCThings[]; + /** * Stream of SCThings for virtual scroll to consume */ itemStream = new BehaviorSubject([]); + /** * Output binding to trigger pagination fetch */ + // eslint-disable-next-line @angular-eslint/no-output-rename @Output('loadmore') loadMore = new EventEmitter(); + /** * Emits when scroll view should reset to top */ @Input() resetToTop?: Observable; + /** * Indicates whether or not the list is to display SCThings of a single type */ @Input() singleType = false; + /** * Items that display the skeleton list */ skeletonItems: number[]; + /** * Array of all subscriptions to Observables */ subscriptions: Subscription[] = []; - // tslint:disable-next-line: completed-docs + @ViewChild(CdkVirtualScrollViewport) viewPort: CdkVirtualScrollViewport; /** @@ -79,38 +87,39 @@ export class DataListComponent implements OnChanges, OnInit { @HostListener('window.resize', ['$event']) calcSkeletonItems() { const itemHeight = 122; - this.skeletonItems = new Array(ceil(window.innerHeight / itemHeight)); + this.skeletonItems = Array.from({ + length: ceil(window.innerHeight / itemHeight), + }); } /** * Uniquely identifies item at a certain list index */ - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this identifyItem(_index: number, item: SCThings) { return item.uid; } - // tslint:disable-next-line: completed-docs ngOnChanges(changes: SimpleChanges): void { if (Array.isArray(this.items) && typeof changes.items !== 'undefined') { this.itemStream.next(this.items); } } - // tslint:disable-next-line: completed-docs ngOnDestroy(): void { for (const subscription of this.subscriptions) { subscription.unsubscribe(); } } - // tslint:disable-next-line: completed-docs ngOnInit(): void { this.calcSkeletonItems(); if (typeof this.resetToTop !== 'undefined') { - this.subscriptions.push(this.resetToTop.subscribe(() => { - this.viewPort.scrollToIndex(0); - })); + this.subscriptions.push( + this.resetToTop.subscribe(() => { + this.viewPort.scrollToIndex(0); + }), + ); } } @@ -125,7 +134,10 @@ export class DataListComponent implements OnChanges, OnInit { * Function to call whenever scroll view visible range changed */ scrolled(_index: number) { - if ((this.items?.length ?? 0) - this.viewPort.getRenderedRange().end <= (this.items?.length ?? 0) * this.reloadThreshold) { + if ( + (this.items?.length ?? 0) - this.viewPort.getRenderedRange().end <= + (this.items?.length ?? 0) * this.reloadThreshold + ) { this.notifyLoadMore(); } } diff --git a/src/app/modules/data/list/data-list.html b/src/app/modules/data/list/data-list.html index c949bee9..55510277 100644 --- a/src/app/modules/data/list/data-list.html +++ b/src/app/modules/data/list/data-list.html @@ -1,17 +1,27 @@ - + - + -
- - {{'search.nothing_found' | translate | titlecase}} +
+ + {{ 'search.nothing_found' | translate | titlecase }}
- - + + diff --git a/src/app/modules/data/list/food-data-list.component.ts b/src/app/modules/data/list/food-data-list.component.ts index 27cc3139..7b07dd94 100644 --- a/src/app/modules/data/list/food-data-list.component.ts +++ b/src/app/modules/data/list/food-data-list.component.ts @@ -37,11 +37,11 @@ export class FoodDataListComponent extends SearchPageComponent { type: 'value', }, { - arguments: { - field: 'categories', - value: 'student canteen', - }, - type: 'value', + arguments: { + field: 'categories', + value: 'student canteen', + }, + type: 'value', }, { arguments: { diff --git a/src/app/modules/data/list/search-page.component.ts b/src/app/modules/data/list/search-page.component.ts index a43d3ff6..100bf20b 100644 --- a/src/app/modules/data/list/search-page.component.ts +++ b/src/app/modules/data/list/search-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {AlertController} from '@ionic/angular'; import { @@ -38,51 +38,62 @@ import {DataProvider} from '../data.provider'; templateUrl: 'search-page.html', providers: [ContextMenuService], }) -export class SearchPageComponent implements OnInit { +export class SearchPageComponent implements OnInit, OnDestroy { /** * Api query filter */ filterQuery: SCSearchFilter | undefined; + /** * Filters the search should be initialized with */ @Input() forcedFilter?: SCSearchFilter; + /** * Thing counter to start query the next page from */ from = 0; + /** * Container for queried things */ items: Promise; + /** * Page size of queries */ pageSize = 30; + /** * Search value from search bar */ queryText: string; + /** * Emits when there is a change in the query (search, sort or filter changed) */ queryChanged = new Subject(); + /** * Subject to handle search text changes */ queryTextChanged = new Subject(); + /** * Time to wait for search query if search text is changing */ searchQueryDueTime = 1000; + /** * Search response only ever contains a single SCThingType */ singleTypeResponse = false; + /** * Api query sorting */ sortQuery: SCSearchSort | undefined; + /** * Array of all subscriptions to Observables */ @@ -110,21 +121,23 @@ export class SearchPageComponent implements OnInit { ) { this.initialize(); - combineLatest( - [this.queryTextChanged.pipe(debounceTime(this.searchQueryDueTime), + combineLatest([ + this.queryTextChanged.pipe( + debounceTime(this.searchQueryDueTime), distinctUntilChanged(), startWith(this.queryText), ), - this.contextMenuService.filterQueryChanged$.pipe(startWith(this.filterQuery)), + this.contextMenuService.filterQueryChanged$.pipe( + startWith(this.filterQuery), + ), this.contextMenuService.sortQueryChanged$.pipe(startWith(this.sortQuery)), - ]) - .subscribe(async (query) => { - this.queryText = query[0]; - this.filterQuery = query[1]; - this.sortQuery = query[2]; - this.from = 0; - await this.fetchAndUpdateItems(); - this.queryChanged.next(); + ]).subscribe(async query => { + this.queryText = query[0]; + this.filterQuery = query[1]; + this.sortQuery = query[2]; + this.from = 0; + await this.fetchAndUpdateItems(); + this.queryChanged.next(); }); this.fetchAndUpdateItems(); @@ -132,19 +145,21 @@ export class SearchPageComponent implements OnInit { /** * Subscribe to 'settings.changed' events */ - this.subscriptions.push(this.settingsProvider.settingsActionChanged$.subscribe(({type, payload}) => { - if (type === 'stapps.settings.changed') { - const {category, name, value} = payload!; - this.logger.log(`received event "settings.changed" with category: + this.subscriptions.push( + this.settingsProvider.settingsActionChanged$.subscribe( + ({type, payload}) => { + if (type === 'stapps.settings.changed') { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const {category, name, value} = payload!; + this.logger.log(`received event "settings.changed" with category: ${category}, name: ${name}, value: ${JSON.stringify(value)}`); - } - }, - )); - - this.subscriptions.push(this.dataRoutingService.itemSelectListener() - .subscribe((item) => { + } + }, + ), + this.dataRoutingService.itemSelectListener().subscribe(item => { void this.router.navigate(['data-detail', item.uid]); - })); + }), + ); } /** @@ -185,13 +200,15 @@ export class SearchPageComponent implements OnInit { }; } - return this.dataProvider.search(searchOptions) - .then(async (result) => { - this.singleTypeResponse = result.facets.find(facet => facet.field === 'type')?.buckets.length === 1; + return this.dataProvider.search(searchOptions).then( + async result => { + this.singleTypeResponse = + result.facets.find(facet => facet.field === 'type')?.buckets + .length === 1; if (append) { let items = await this.items; // append results - items = items.concat(result.data); + items = [...items, ...result.data]; this.items = (async () => items)(); } else { // override items with results @@ -201,21 +218,23 @@ export class SearchPageComponent implements OnInit { return result.data; })(); } - }, async (err) => { + }, + async error => { const alert: HTMLIonAlertElement = await this.alertController.create({ buttons: ['Dismiss'], header: 'Error', - subHeader: err.message, + subHeader: error.message, }); await alert.present(); - }); + }, + ); } /** * Set starting values (e.g. forced filter, which can be set in components inheriting this one) */ - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this initialize() { // nothing to do here } @@ -223,7 +242,7 @@ export class SearchPageComponent implements OnInit { /** * Loads next page of things */ - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any async loadMore(): Promise { this.from += this.pageSize; await this.fetchAndUpdateItems(true); diff --git a/src/app/modules/data/list/search-page.html b/src/app/modules/data/list/search-page.html index e82978ea..d83c8653 100644 --- a/src/app/modules/data/list/search-page.html +++ b/src/app/modules/data/list/search-page.html @@ -10,10 +10,19 @@ - + - + diff --git a/src/app/modules/data/stapps-web-http-client.provider.ts b/src/app/modules/data/stapps-web-http-client.provider.ts index 932f52b2..14907733 100644 --- a/src/app/modules/data/stapps-web-http-client.provider.ts +++ b/src/app/modules/data/stapps-web-http-client.provider.ts @@ -14,7 +14,10 @@ */ import {HttpClient, HttpResponse} from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {HttpClientInterface, HttpClientRequest} from '@openstapps/api/lib/http-client-interface'; +import { + HttpClientInterface, + HttpClientRequest, +} from '@openstapps/api/lib/http-client-interface'; /** * HttpClient that is based on the Angular HttpClient (@TODO: move it to provider or independent package) @@ -25,11 +28,11 @@ export class StAppsWebHttpClient implements HttpClientInterface { * * @param http TODO */ - constructor(private readonly http: HttpClient) { - } + constructor(private readonly http: HttpClient) {} /** * Make a request + * * @param requestConfig Configuration of the request */ async request( @@ -59,14 +62,21 @@ export class StAppsWebHttpClient implements HttpClientInterface { } try { - const response: HttpResponse = await this.http.request( - requestConfig.method || 'GET', requestConfig.url.toString(), options) + const response: HttpResponse = await this.http + .request( + requestConfig.method || 'GET', + requestConfig.url.toString(), + options, + ) .toPromise(); - // tslint:disable-next-line:prefer-object-spread - return Object.assign(response, {statusCode: response.status, body: response.body || {}}); - } catch (err) { - throw Error(err); + // eslint-disable-next-line prefer-object-spread + return Object.assign(response, { + statusCode: response.status, + body: response.body || {}, + }); + } catch (error) { + throw new Error(error); } } } diff --git a/src/app/modules/data/types/article/article-detail-content.html b/src/app/modules/data/types/article/article-detail-content.html index a3a14308..a8284829 100644 --- a/src/app/modules/data/types/article/article-detail-content.html +++ b/src/app/modules/data/types/article/article-detail-content.html @@ -1,6 +1,16 @@ - + - - + + diff --git a/src/app/modules/data/types/article/article-list-item.component.ts b/src/app/modules/data/types/article/article-list-item.component.ts index 20f2629a..96474731 100644 --- a/src/app/modules/data/types/article/article-list-item.component.ts +++ b/src/app/modules/data/types/article/article-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCArticle} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-article-list-item', templateUrl: 'article-list-item.html', }) - -export class ArticleListItem extends DataListItem { +export class ArticleListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCArticle; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/article/article-list-item.html b/src/app/modules/data/types/article/article-list-item.html index 4b9ec7bb..180d8694 100644 --- a/src/app/modules/data/types/article/article-list-item.html +++ b/src/app/modules/data/types/article/article-list-item.html @@ -1,12 +1,15 @@ -

{{'name' | thingTranslate: item}}

+

{{ 'name' | thingTranslate: item }}

- +

- {{'type' | thingTranslate: item}} + {{ 'type' | thingTranslate: item }}
diff --git a/src/app/modules/data/types/catalog/catalog-detail-content.html b/src/app/modules/data/types/catalog/catalog-detail-content.html index ce0708a5..4d96e06b 100644 --- a/src/app/modules/data/types/catalog/catalog-detail-content.html +++ b/src/app/modules/data/types/catalog/catalog-detail-content.html @@ -1,2 +1,5 @@ - + diff --git a/src/app/modules/data/types/catalog/catalog-list-item.component.ts b/src/app/modules/data/types/catalog/catalog-list-item.component.ts index 90dc552a..1c132666 100644 --- a/src/app/modules/data/types/catalog/catalog-list-item.component.ts +++ b/src/app/modules/data/types/catalog/catalog-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCCatalog} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-catalog-list-item', templateUrl: 'catalog-list-item.html', }) - -export class CatalogListItem extends DataListItem { +export class CatalogListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCCatalog; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/catalog/catalog-list-item.html b/src/app/modules/data/types/catalog/catalog-list-item.html index 80bd340a..299ba58b 100644 --- a/src/app/modules/data/types/catalog/catalog-list-item.html +++ b/src/app/modules/data/types/catalog/catalog-list-item.html @@ -2,11 +2,14 @@
-

{{'name' | thingTranslate: item}}

+

{{ 'name' | thingTranslate: item }}

- +

-

{{item.academicTerm.name}}

+

{{ item.academicTerm.name }}

diff --git a/src/app/modules/data/types/date-series/date-series-detail-content.html b/src/app/modules/data/types/date-series/date-series-detail-content.html index 9238af14..68025af5 100644 --- a/src/app/modules/data/types/date-series/date-series-detail-content.html +++ b/src/app/modules/data/types/date-series/date-series-detail-content.html @@ -1,12 +1,28 @@ - {{'inPlace' | propertyNameTranslate: item | titlecase}} + {{ 'inPlace' | propertyNameTranslate: item | titlecase }} - {{'name' | thingTranslate: item.inPlace}} - + + {{ + 'name' | thingTranslate: item.inPlace + }} + - - - + + + diff --git a/src/app/modules/data/types/date-series/date-series-list-item.component.ts b/src/app/modules/data/types/date-series/date-series-list-item.component.ts index d5a6beb1..6daf2bfa 100644 --- a/src/app/modules/data/types/date-series/date-series-list-item.component.ts +++ b/src/app/modules/data/types/date-series/date-series-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCDateSeries} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-date-series-list-item', templateUrl: 'date-series-list-item.html', }) - -export class DateSeriesListItem extends DataListItem { +export class DateSeriesListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCDateSeries; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/date-series/date-series-list-item.html b/src/app/modules/data/types/date-series/date-series-list-item.html index e598c8da..c0417ec6 100644 --- a/src/app/modules/data/types/date-series/date-series-list-item.html +++ b/src/app/modules/data/types/date-series/date-series-list-item.html @@ -2,19 +2,29 @@
-

{{'name' | thingTranslate: item}}

+

{{ 'name' | thingTranslate: item }}

- {{item.frequency}}, {{item.dates[0] | amDateFormat:'dddd'}} - ({{item.dates[0] | amDateFormat:'ll'}} - {{item.dates[item.dates.length - 1] | amDateFormat:'ll'}}) - + {{ item.frequency }}, {{ item.dates[0] | amDateFormat: 'dddd' }} + ({{ item.dates[0] | amDateFormat: 'll' }} - + {{ + item.dates[item.dates.length - 1] | amDateFormat: 'll' + }}) +

- {{'categories' | thingTranslate: item.event | join: ', '}} + {{ + 'categories' | thingTranslate: item.event | join: ', ' + }}
- +
diff --git a/src/app/modules/data/types/dish/dish-detail-content.html b/src/app/modules/data/types/dish/dish-detail-content.html index c7c5487d..ecf057fb 100644 --- a/src/app/modules/data/types/dish/dish-detail-content.html +++ b/src/app/modules/data/types/dish/dish-detail-content.html @@ -1,51 +1,79 @@ - + - {{ 'characteristics' | propertyNameTranslate: item | titlecase }} - + {{ + 'characteristics' | propertyNameTranslate: item | titlecase + }} +

-  {{characteristic.name}}   +  {{ characteristic.name }}  

- - + + - {{'data.types.dish.detail.AVG_NUTRITION_INFO' | translate }} + {{ + 'data.types.dish.detail.AVG_NUTRITION_INFO' | translate + }} - {{'data.types.dish.detail.CALORIES' | translate }}: + {{ 'data.types.dish.detail.CALORIES' | translate }}: - {{item.nutrition.calories | numberLocalized}} kcal + {{ item.nutrition.calories | numberLocalized }} kcal - {{'data.types.dish.detail.FAT_TOTAL' | translate }}: + {{ 'data.types.dish.detail.FAT_TOTAL' | translate }}: - {{item.nutrition.fatContent | numberLocalized}} g ({{'data.types.dish.detail.FAT_SATURATED' | translate }}: - {{item.nutrition.saturatedFatContent | numberLocalized}} g) + {{ item.nutrition.fatContent | numberLocalized }} g + ({{ 'data.types.dish.detail.FAT_SATURATED' | translate }}: + {{ item.nutrition.saturatedFatContent | numberLocalized }} g) - {{'data.types.dish.detail.CARBOHYDRATE' | translate }}: + {{ 'data.types.dish.detail.CARBOHYDRATE' | translate }}: - {{item.nutrition.carbohydrateContent | numberLocalized}} g ({{'data.types.dish.detail.SUGAR' | translate }}: - {{item.nutrition.sugarContent | numberLocalized}} g) + {{ item.nutrition.carbohydrateContent | numberLocalized }} g + ({{ 'data.types.dish.detail.SUGAR' | translate }}: + {{ item.nutrition.sugarContent | numberLocalized }} g) - {{'data.types.dish.detail.SALT' | translate }}: + {{ 'data.types.dish.detail.SALT' | translate }}: - {{item.nutrition.saltContent | numberLocalized}} g + {{ item.nutrition.saltContent | numberLocalized }} g - {{'data.types.dish.detail.PROTEIN' | translate }}: + {{ 'data.types.dish.detail.PROTEIN' | translate }}: - {{item.nutrition.proteinContent | numberLocalized}} g + {{ item.nutrition.proteinContent | numberLocalized }} g diff --git a/src/app/modules/data/types/dish/dish-list-item.component.ts b/src/app/modules/data/types/dish/dish-list-item.component.ts index 01933847..dd7650e4 100644 --- a/src/app/modules/data/types/dish/dish-list-item.component.ts +++ b/src/app/modules/data/types/dish/dish-list-item.component.ts @@ -14,8 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCDish} from '@openstapps/core'; -// import {SettingsProvider} from '../../../settings/settings.provider'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -24,15 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-dish-list-item', templateUrl: 'dish-list-item.html', }) - -export class DishListItem extends DataListItem { +export class DishListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCDish; - - // tslint:disable-next-line: completed-docs prefer-function-over-method - ngOnInit() { - // custom init - } } diff --git a/src/app/modules/data/types/dish/dish-list-item.html b/src/app/modules/data/types/dish/dish-list-item.html index e836f056..32512ed3 100644 --- a/src/app/modules/data/types/dish/dish-list-item.html +++ b/src/app/modules/data/types/dish/dish-list-item.html @@ -2,14 +2,17 @@
-

{{'name' | thingTranslate: item}}

-

{{'description' | thingTranslate: item}}

-

{{'categories' | thingTranslate: item | join: ', '}}

+

{{ 'name' | thingTranslate: item }}

+

{{ 'description' | thingTranslate: item }}

+

{{ 'categories' | thingTranslate: item | join: ', ' }}

- +
diff --git a/src/app/modules/data/types/event/event-detail-content.component.ts b/src/app/modules/data/types/event/event-detail-content.component.ts index b6c3c012..ac6c1243 100644 --- a/src/app/modules/data/types/event/event-detail-content.component.ts +++ b/src/app/modules/data/types/event/event-detail-content.component.ts @@ -13,7 +13,12 @@ * this program. If not, see . */ import {Component, Input} from '@angular/core'; -import {SCAcademicEvent, SCSportCourse, SCThing, SCTranslations} from '@openstapps/core'; +import { + SCAcademicEvent, + SCSportCourse, + SCThing, + SCTranslations, +} from '@openstapps/core'; import {SCThingTranslator} from '@openstapps/core'; /** @@ -28,18 +33,22 @@ export class EventDetailContentComponent { * TODO */ @Input() item: SCAcademicEvent | SCSportCourse; + /** * TODO */ @Input() language: keyof SCTranslations; + /** * TODO */ objectKeys = Object.keys; + /** * TODO */ translator: SCThingTranslator; + /** * TODO */ diff --git a/src/app/modules/data/types/event/event-detail-content.html b/src/app/modules/data/types/event/event-detail-content.html index 99fe4972..a1234846 100644 --- a/src/app/modules/data/types/event/event-detail-content.html +++ b/src/app/modules/data/types/event/event-detail-content.html @@ -1,14 +1,46 @@ - + - - - - + + + + - - - + + + diff --git a/src/app/modules/data/types/event/event-list-item.component.ts b/src/app/modules/data/types/event/event-list-item.component.ts index d301402b..77b7a8aa 100644 --- a/src/app/modules/data/types/event/event-list-item.component.ts +++ b/src/app/modules/data/types/event/event-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCAcademicEvent, SCSportCourse} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,17 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-event-list-item', templateUrl: 'event-list-item.html', }) -export class EventListItemComponent extends DataListItem { +export class EventListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCAcademicEvent | SCSportCourse; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/event/event-list-item.html b/src/app/modules/data/types/event/event-list-item.html index d2005f52..30b02e82 100644 --- a/src/app/modules/data/types/event/event-list-item.html +++ b/src/app/modules/data/types/event/event-list-item.html @@ -2,19 +2,19 @@
-

{{item.name}}

-

{{item.description}}

-

{{item.academicTerms[0].name}}

- {{item.type}} ({{item.categories.join(', ')}}) +

{{ item.name }}

+

{{ item.description }}

+

{{ item.academicTerms[0].name }}

+ {{ item.type }} ({{ item.categories.join(', ') }})
-

{{item.name}}

-

{{item.description}}

-

{{item.academicTerms[0].name}}

- {{item.type}} +

{{ item.name }}

+

{{ item.description }}

+

{{ item.academicTerms[0].name }}

+ {{ item.type }}
diff --git a/src/app/modules/data/types/favorite/favorite-list-item.component.ts b/src/app/modules/data/types/favorite/favorite-list-item.component.ts index 923d047b..defae2bc 100644 --- a/src/app/modules/data/types/favorite/favorite-list-item.component.ts +++ b/src/app/modules/data/types/favorite/favorite-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCFavorite} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-favorite-list-item', templateUrl: 'favorite-list-item.html', }) - -export class FavoriteListItem extends DataListItem { +export class FavoriteListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCFavorite; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/favorite/favorite-list-item.html b/src/app/modules/data/types/favorite/favorite-list-item.html index 389f0640..9e4f76bb 100644 --- a/src/app/modules/data/types/favorite/favorite-list-item.html +++ b/src/app/modules/data/types/favorite/favorite-list-item.html @@ -2,11 +2,21 @@
-

{{'name' | thingTranslate: item}}: {{'name' | thingTranslate: item.data}}

+

+ {{ 'name' | thingTranslate: item }}: + {{ 'name' | thingTranslate: item.data }} +

- +

- {{'type' | thingTranslate: item}} ({{'type' | thingTranslate: item.data}}) + {{ 'type' | thingTranslate: item }} ({{ + 'type' | thingTranslate: item.data + }})
diff --git a/src/app/modules/data/types/message/message-detail-content.html b/src/app/modules/data/types/message/message-detail-content.html index cc2cb40f..aff45627 100644 --- a/src/app/modules/data/types/message/message-detail-content.html +++ b/src/app/modules/data/types/message/message-detail-content.html @@ -1,5 +1,23 @@ - - - - - + + + + + diff --git a/src/app/modules/data/types/message/message-list-item.component.ts b/src/app/modules/data/types/message/message-list-item.component.ts index 6228885b..108c442b 100644 --- a/src/app/modules/data/types/message/message-list-item.component.ts +++ b/src/app/modules/data/types/message/message-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCMessage} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-message-list-item', templateUrl: 'message-list-item.html', }) - -export class MessageListItem extends DataListItem { +export class MessageListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCMessage; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/message/message-list-item.html b/src/app/modules/data/types/message/message-list-item.html index 792cd253..0132c6f1 100644 --- a/src/app/modules/data/types/message/message-list-item.html +++ b/src/app/modules/data/types/message/message-list-item.html @@ -2,11 +2,14 @@
-

{{'name' | thingTranslate: item}}

+

{{ 'name' | thingTranslate: item }}

- +

- {{'type' | thingTranslate: item}} + {{ 'type' | thingTranslate: item }}
diff --git a/src/app/modules/data/types/organization/organization-detail-content.html b/src/app/modules/data/types/organization/organization-detail-content.html index 0ab5e40d..0f8609c9 100644 --- a/src/app/modules/data/types/organization/organization-detail-content.html +++ b/src/app/modules/data/types/organization/organization-detail-content.html @@ -1,9 +1,15 @@ - {{'inPlace' | propertyNameTranslate: item | titlecase}} + {{ 'inPlace' | propertyNameTranslate: item | titlecase }} - {{'name' | thingTranslate: item.inPlace}} - + + {{ + 'name' | thingTranslate: item.inPlace + }} + diff --git a/src/app/modules/data/types/organization/organization-list-item.component.ts b/src/app/modules/data/types/organization/organization-list-item.component.ts index 7753c234..fdb35156 100644 --- a/src/app/modules/data/types/organization/organization-list-item.component.ts +++ b/src/app/modules/data/types/organization/organization-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCOrganization} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-organization-list-item', templateUrl: 'organization-list-item.html', }) - -export class OrganizationListItem extends DataListItem { +export class OrganizationListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCOrganization; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/organization/organization-list-item.html b/src/app/modules/data/types/organization/organization-list-item.html index eb52e942..3d93f4be 100644 --- a/src/app/modules/data/types/organization/organization-list-item.html +++ b/src/app/modules/data/types/organization/organization-list-item.html @@ -2,14 +2,17 @@
-

{{'name' | thingTranslate: item}}

-

{{'description' | thingTranslate: item}}

- {{'type' | thingTranslate: item}} +

{{ 'name' | thingTranslate: item }}

+

+ {{ 'description' | thingTranslate: item }} +

+ {{ 'type' | thingTranslate: item }}
- {{'name' | thingTranslate: item.inPlace}} + + {{ 'name' | thingTranslate: item.inPlace }}
diff --git a/src/app/modules/data/types/person/person-detail-content.html b/src/app/modules/data/types/person/person-detail-content.html index 424a2710..ecf5cc16 100644 --- a/src/app/modules/data/types/person/person-detail-content.html +++ b/src/app/modules/data/types/person/person-detail-content.html @@ -1,33 +1,88 @@ - {{'type' | thingTranslate: item.workLocations[0] | titlecase}} + {{ 'type' | thingTranslate: item.workLocations[0] | titlecase }} -

{{'telephone' | propertyNameTranslate: item.workLocations[0] | titlecase}}: {{item.workLocations[0].telephone}} +

+ {{ + 'telephone' + | propertyNameTranslate: item.workLocations[0] + | titlecase + }}: + {{ + item.workLocations[0].telephone + }}

-

{{'email' | propertyNameTranslate: item.workLocations[0] | titlecase}}: {{item.workLocations[0].email}}

-

{{'faxNumber' | propertyNameTranslate: item.workLocations[0] | titlecase}}: {{item.workLocations[0].faxNumber}}

-

{{'url' | propertyNameTranslate: item.workLocations[0] | titlecase}}: {{item.workLocations[0].url}} +

+ {{ + 'email' | propertyNameTranslate: item.workLocations[0] | titlecase + }}: + {{ + item.workLocations[0].email + }}

-

{{'areaServed' | propertyNameTranslate: item.workLocations[0] | titlecase}}: {{item.workLocations[0].areaServed.name}} +

+ {{ + 'faxNumber' + | propertyNameTranslate: item.workLocations[0] + | titlecase + }}: {{ item.workLocations[0].faxNumber }} +

+

+ {{ 'url' | propertyNameTranslate: item.workLocations[0] | titlecase }}: + {{ + item.workLocations[0].url + }} +

+

+ {{ + 'areaServed' + | propertyNameTranslate: item.workLocations[0] + | titlecase + }}: + {{ item.workLocations[0].areaServed.name }}

- + -

{{'telephone' | propertyNameTranslate: item.workLocation | titlecase}}: {{workLocation.telephone}} +

+ {{ + 'telephone' | propertyNameTranslate: item.workLocation | titlecase + }}: + {{ + workLocation.telephone + }}

-

{{'email' | propertyNameTranslate: item.workLocation | titlecase}}: {{workLocation.email}} +

+ {{ 'email' | propertyNameTranslate: item.workLocation | titlecase }}: + {{ + workLocation.email + }}

-

{{'faxNumber' | propertyNameTranslate: item.workLocation | titlecase}}: {{workLocation.faxNumber}}

-

{{'url' | propertyNameTranslate: item.workLocation | titlecase}}: {{workLocation.url}}

-

{{'areaServed' | propertyNameTranslate: item.workLocation | titlecase}}: {{workLocation.areaServed.name}} +

+ {{ + 'faxNumber' | propertyNameTranslate: item.workLocation | titlecase + }}: {{ workLocation.faxNumber }} +

+

+ {{ 'url' | propertyNameTranslate: item.workLocation | titlecase }}: + {{ workLocation.url }} +

+

+ {{ + 'areaServed' | propertyNameTranslate: item.workLocation | titlecase + }}: + {{ + workLocation.areaServed.name + }}

@@ -35,4 +90,8 @@
- + diff --git a/src/app/modules/data/types/person/person-list-item.component.ts b/src/app/modules/data/types/person/person-list-item.component.ts index ce08f258..f6d42fb1 100644 --- a/src/app/modules/data/types/person/person-list-item.component.ts +++ b/src/app/modules/data/types/person/person-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCPerson} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-person-list-item', templateUrl: 'person-list-item.html', }) - -export class PersonListItem extends DataListItem { +export class PersonListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCPerson; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/person/person-list-item.html b/src/app/modules/data/types/person/person-list-item.html index 86c3ae0a..55c4934f 100644 --- a/src/app/modules/data/types/person/person-list-item.html +++ b/src/app/modules/data/types/person/person-list-item.html @@ -2,13 +2,23 @@
-

{{'name' | thingTranslate: item}} , {{item.honorificPrefix}}

-

-  {{item.telephone}}  - -  {{item.email}} -

-

{{item.jobTitles.join(', ') | slice:0:50}}...

+

+ {{ 'name' | thingTranslate: item }} + , {{ item.honorificPrefix }} +

+

+ +  {{ + item.telephone + }}  +  {{ item.email }} + +

+

+ {{ item.jobTitles.join(', ') | slice: 0:50 + }}... +

diff --git a/src/app/modules/data/types/place/place-detail-content.component.ts b/src/app/modules/data/types/place/place-detail-content.component.ts index 78e58aac..9eb993d2 100644 --- a/src/app/modules/data/types/place/place-detail-content.component.ts +++ b/src/app/modules/data/types/place/place-detail-content.component.ts @@ -13,14 +13,20 @@ * this program. If not, see . */ import {Component, Input} from '@angular/core'; -import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom, SCThings} from '@openstapps/core'; +import { + SCBuilding, + SCFloor, + SCPointOfInterest, + SCRoom, + SCThings, +} from '@openstapps/core'; import {DataProvider} from '../../data.provider'; /** * TODO */ @Component({ - providers: [ DataProvider ], + providers: [DataProvider], selector: 'stapps-place-detail-content', templateUrl: 'place-detail-content.html', }) @@ -35,10 +41,8 @@ export class PlaceDetailContentComponent { * * @param item TODO */ - // tslint:disable-next-line:completed-docs prefer-function-over-method - hasCategories(item: SCThings): item is SCThings & { categories: string[]; } { - // tslint:disable-next-line:completed-docs - return typeof (item as { categories: string[]; }).categories !== 'undefined'; + hasCategories(item: SCThings): item is SCThings & {categories: string[]} { + return typeof (item as {categories: string[]}).categories !== 'undefined'; } /** @@ -46,9 +50,13 @@ export class PlaceDetailContentComponent { * * @param item TODO */ - isMensaThing(item: SCThings): boolean { - return this.hasCategories(item) && - ((item.categories as string[]).includes('canteen') || (item.categories as string[]).includes('cafe') - || (item.categories as string[]).includes('student canteen') || (item.categories as string[]).includes('restaurant')); + isMensaThing(item: SCThings): boolean { + return ( + this.hasCategories(item) && + ((item.categories as string[]).includes('canteen') || + (item.categories as string[]).includes('cafe') || + (item.categories as string[]).includes('student canteen') || + (item.categories as string[]).includes('restaurant')) + ); } } diff --git a/src/app/modules/data/types/place/place-detail-content.html b/src/app/modules/data/types/place/place-detail-content.html index 688f27f8..9c2e22fb 100644 --- a/src/app/modules/data/types/place/place-detail-content.html +++ b/src/app/modules/data/types/place/place-detail-content.html @@ -1,16 +1,33 @@ - + - - + + - + - {{'inPlace' | propertyNameTranslate: item | titlecase}} + {{ 'inPlace' | propertyNameTranslate: item | titlecase }} - {{'name' | thingTranslate: item.inPlace}} + + {{ + 'name' | thingTranslate: item.inPlace + }} - + diff --git a/src/app/modules/data/types/place/place-list-item.component.ts b/src/app/modules/data/types/place/place-list-item.component.ts index 813c0d1e..1ad87fca 100644 --- a/src/app/modules/data/types/place/place-list-item.component.ts +++ b/src/app/modules/data/types/place/place-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,18 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-place-list-item', templateUrl: 'place-list-item.html', }) - -export class PlaceListItem extends DataListItem { +export class PlaceListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/place/place-list-item.html b/src/app/modules/data/types/place/place-list-item.html index f7d6730d..17c91308 100644 --- a/src/app/modules/data/types/place/place-list-item.html +++ b/src/app/modules/data/types/place/place-list-item.html @@ -2,14 +2,17 @@
-

{{'name' | thingTranslate: item}}

-

{{'description' | thingTranslate: item}}

- {{'type' | thingTranslate: item}} +

{{ 'name' | thingTranslate: item }}

+

+ {{ 'description' | thingTranslate: item }} +

+ {{ 'type' | thingTranslate: item }}
- {{'name' | thingTranslate: item.inPlace}} + {{ 'name' | thingTranslate: item.inPlace }}
diff --git a/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts b/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts index fe6f42ac..241dbf0f 100644 --- a/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts +++ b/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts @@ -29,10 +29,10 @@ import {PlaceMensaService} from './place-mensa-service'; templateUrl: 'place-mensa.html', }) export class PlaceMensaDetailComponent implements AfterViewInit { - /** * Map of dishes for each day */ + // eslint-disable-next-line unicorn/no-null dishes: Promise> | null = null; /** @@ -67,6 +67,6 @@ export class PlaceMensaDetailComponent implements AfterViewInit { */ ngAfterViewInit() { this.dishes = this.mensaService.getAllDishes(this.item, this.displayRange); - this.dishes.then((result) => this.selectedDay = keys(result)[0]); + this.dishes.then(result => (this.selectedDay = keys(result)[0])); } } diff --git a/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts b/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts index e12440b9..552d0272 100644 --- a/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts +++ b/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts @@ -14,7 +14,13 @@ */ import {Injectable} from '@angular/core'; -import {SCDish, SCISO8601Date, SCMultiSearchRequest, SCPlace, SCThingType} from '@openstapps/core'; +import { + SCDish, + SCISO8601Date, + SCMultiSearchRequest, + SCPlace, + SCThingType, +} from '@openstapps/core'; import {keyBy, mapValues, range} from 'lodash-es'; import moment from 'moment'; import {DataProvider} from '../../../../data.provider'; @@ -26,21 +32,20 @@ import {DataProvider} from '../../../../data.provider'; providedIn: 'root', }) export class PlaceMensaService { - constructor(private dataProvider: DataProvider) { - } + constructor(private dataProvider: DataProvider) {} /** * Fetches all dishes for this building * * Splits dishes as such that each list contains all dishes that are available at that day. */ - async getAllDishes(place: SCPlace, days: number): Promise> { + async getAllDishes( + place: SCPlace, + days: number, + ): Promise> { const request: SCMultiSearchRequest = mapValues( - keyBy(range(days) - .map((i) => moment() - .add(i, 'days') - .toISOString()), - ), (date: SCISO8601Date) => ({ + keyBy(range(days).map(i => moment().add(i, 'days').toISOString())), + (date: SCISO8601Date) => ({ filter: { arguments: { filters: [ @@ -72,8 +77,12 @@ export class PlaceMensaService { type: 'boolean', }, size: 1000, - })); + }), + ); - return mapValues(await this.dataProvider.multiSearch(request), 'data') as Record; + return mapValues( + await this.dataProvider.multiSearch(request), + 'data', + ) as Record; } } diff --git a/src/app/modules/data/types/place/special/mensa/place-mensa.html b/src/app/modules/data/types/place/special/mensa/place-mensa.html index e2eec16d..01f3e9c1 100644 --- a/src/app/modules/data/types/place/special/mensa/place-mensa.html +++ b/src/app/modules/data/types/place/special/mensa/place-mensa.html @@ -1,24 +1,34 @@
- - {{date.key | amDateFormat:'dddd, L'}} + + {{ date.key | amDateFormat: 'dddd, L' }}
- +
- + - +
diff --git a/src/app/modules/data/types/semester/semester-detail-content.html b/src/app/modules/data/types/semester/semester-detail-content.html index 4fdc5ed8..9b7af549 100644 --- a/src/app/modules/data/types/semester/semester-detail-content.html +++ b/src/app/modules/data/types/semester/semester-detail-content.html @@ -1,3 +1,13 @@ - + diff --git a/src/app/modules/data/types/semester/semester-list-item.component.ts b/src/app/modules/data/types/semester/semester-list-item.component.ts index 86634cd3..8b5905ac 100644 --- a/src/app/modules/data/types/semester/semester-list-item.component.ts +++ b/src/app/modules/data/types/semester/semester-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCSemester} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,17 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-semester-list-item', templateUrl: 'semester-list-item.html', }) -export class SemesterListItem extends DataListItem { +export class SemesterListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCSemester; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/semester/semester-list-item.html b/src/app/modules/data/types/semester/semester-list-item.html index 308bedd5..eb2c0d52 100644 --- a/src/app/modules/data/types/semester/semester-list-item.html +++ b/src/app/modules/data/types/semester/semester-list-item.html @@ -2,12 +2,15 @@
-

{{'name' | thingTranslate: item}}

+

{{ 'name' | thingTranslate: item }}

- {{item.startDate | amDateFormat: 'll'}} - {{item.endDate | amDateFormat:'ll'}} + {{ item.startDate | amDateFormat: 'll' }} - + {{ item.endDate | amDateFormat: 'll' }}

- {{'type' | thingTranslate: item}} + {{ 'type' | thingTranslate: item }}
diff --git a/src/app/modules/data/types/video/video-detail-content.html b/src/app/modules/data/types/video/video-detail-content.html index 1e19edc4..1255dab8 100644 --- a/src/app/modules/data/types/video/video-detail-content.html +++ b/src/app/modules/data/types/video/video-detail-content.html @@ -1,6 +1,20 @@ - - - + + + - + diff --git a/src/app/modules/data/types/video/video-list-item.component.ts b/src/app/modules/data/types/video/video-list-item.component.ts index 270bfbe9..f0fe349e 100644 --- a/src/app/modules/data/types/video/video-list-item.component.ts +++ b/src/app/modules/data/types/video/video-list-item.component.ts @@ -14,7 +14,7 @@ */ import {Component, Input} from '@angular/core'; import {SCVideo} from '@openstapps/core'; -import {DataListItem} from '../../list/data-list-item.component'; +import {DataListItemComponent} from '../../list/data-list-item.component'; /** * TODO @@ -23,17 +23,9 @@ import {DataListItem} from '../../list/data-list-item.component'; selector: 'stapps-video-list-item', templateUrl: 'video-list-item.html', }) -export class VideoListItem extends DataListItem { +export class VideoListItemComponent extends DataListItemComponent { /** * TODO */ @Input() item: SCVideo; - - /** - * TODO - */ - // tslint:disable-next-line:prefer-function-over-method - ngOnInit() { - // TODO: translation - } } diff --git a/src/app/modules/data/types/video/video-list-item.html b/src/app/modules/data/types/video/video-list-item.html index 714ce432..863a039c 100644 --- a/src/app/modules/data/types/video/video-list-item.html +++ b/src/app/modules/data/types/video/video-list-item.html @@ -2,10 +2,18 @@
-

{{'name' | thingTranslate: item}}

-

-

{{'duration' | propertyNameTranslate: item | titlecase}}: {{item.duration | amDuration:'seconds'}}

- {{'type' | thingTranslate: item}} +

{{ 'name' | thingTranslate: item }}

+

+ +

+

+ {{ 'duration' | propertyNameTranslate: item | titlecase }}: + {{ item.duration | amDuration: 'seconds' }} +

+ {{ 'type' | thingTranslate: item }}
diff --git a/src/app/modules/menu/context/context-menu.component.spec.ts b/src/app/modules/menu/context/context-menu.component.spec.ts index b4a102ff..5b2ee714 100644 --- a/src/app/modules/menu/context/context-menu.component.spec.ts +++ b/src/app/modules/menu/context/context-menu.component.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion,@typescript-eslint/ban-ts-comment */ /* * Copyright (C) 2020 StApps * This program is free software: you can redistribute it and/or modify it @@ -12,16 +13,26 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {APP_BASE_HREF, CommonModule, Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; +import { + APP_BASE_HREF, + CommonModule, + Location, + LocationStrategy, + PathLocationStrategy, +} from '@angular/common'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FormsModule} from '@angular/forms'; -import {ChildrenOutletContexts, RouterModule, UrlSerializer} from '@angular/router'; +import { + ChildrenOutletContexts, + RouterModule, + UrlSerializer, +} from '@angular/router'; import {IonicModule} from '@ionic/angular'; -import {TranslateModule,} from '@ngx-translate/core'; +import {TranslateModule} from '@ngx-translate/core'; import {SCFacet, SCThingType} from '@openstapps/core'; import {ContextMenuComponent} from './context-menu.component'; import {SettingsModule} from '../../settings/settings.module'; -import {ContextMenuService} from '../context/context-menu.service'; +import {ContextMenuService} from './context-menu.service'; import {FilterContext, SortContext} from './context-type'; describe('ContextMenuComponent', async () => { @@ -29,7 +40,6 @@ describe('ContextMenuComponent', async () => { let instance: ContextMenuComponent; beforeEach(() => { - TestBed.configureTestingModule({ declarations: [ContextMenuComponent], providers: [ @@ -40,7 +50,6 @@ describe('ContextMenuComponent', async () => { {provide: LocationStrategy, useClass: PathLocationStrategy}, {provide: APP_BASE_HREF, useValue: '/'}, ], - // tslint:disable-next-line:object-literal-sort-keys imports: [ FormsModule, IonicModule.forRoot(), @@ -58,23 +67,30 @@ describe('ContextMenuComponent', async () => { it('should show items in sort context', () => { instance.sortOption = getSortContextType(); fixture.detectChanges(); - const sort: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-sort'); + const sort: HTMLElement = + fixture.debugElement.nativeElement.querySelector('.context-sort'); const sortItem = sort.querySelector('.sort-item'); - expect(sortItem!.querySelector('ion-label')!.textContent).toContain('relevance'); + expect(sortItem!.querySelector('ion-label')?.textContent).toContain( + 'relevance', + ); }); it('should show items in filter context', () => { instance.filterOption = getFilterContextType(); fixture.detectChanges(); - const filter: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-filter'); + const filter: HTMLElement = + fixture.debugElement.nativeElement.querySelector('.context-filter'); const filterItem = filter.querySelector('.filter-group'); - expect(filterItem!.querySelector('ion-list-header')!.textContent).toContain('Type'); + expect(filterItem!.querySelector('ion-list-header')!.textContent).toContain( + 'Type', + ); }); it('should set sort context value and reverse on click', () => { instance.sortOption = getSortContextType(); fixture.detectChanges(); - const sort: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-sort'); + const sort: HTMLElement = + fixture.debugElement.nativeElement.querySelector('.context-sort'); // @ts-ignore const sortItem: HTMLElement = sort.querySelectorAll('.sort-item')[1]; sortItem!.click(); @@ -93,18 +109,26 @@ describe('ContextMenuComponent', async () => { instance.filterOption = getFilterContextType(); fixture.detectChanges(); // get filter context div - const filter: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-filter'); + const filter: HTMLElement = + fixture.debugElement.nativeElement.querySelector('.context-filter'); // get all filter groups that represent a facet const filterGroups = filter.querySelectorAll('.filter-group'); expect(filterGroups.length).toEqual(facets.length); for (const facet of facets) { - let filterGroup = undefined; + let filterGroup; // get filter option for facets field - filterGroups.forEach((element) => { - if (element.querySelector('ion-list-header')!.textContent!.toString().toLowerCase().indexOf(facet.field) > -1) { + // eslint-disable-next-line unicorn/no-array-for-each + filterGroups.forEach(element => { + if ( + element + .querySelector('ion-list-header')! + .textContent!.toString() + .toLowerCase() + .includes(facet.field) + ) { filterGroup = element; return; } @@ -125,9 +149,13 @@ describe('ContextMenuComponent', async () => { let filterItem; for (let i = 0; i < filterItems.length; i++) { - if (filterItems.item(i) - .textContent!.toString().toLowerCase() - .indexOf(bucket.key.toLowerCase()) > 0) { + if ( + filterItems + .item(i) + .textContent!.toString() + .toLowerCase() + .indexOf(bucket.key.toLowerCase()) > 0 + ) { filterItem = filterItems.item(i); break; } @@ -139,23 +167,27 @@ describe('ContextMenuComponent', async () => { it('should reset filter', () => { instance.filterOption = getFilterContextType(); - instance.filterOption.options = [{ - field: 'type', - buckets: [ - {count: 10, key: 'date series', checked: true} - ] - }]; + instance.filterOption.options = [ + { + field: 'type', + buckets: [{count: 10, key: 'date series', checked: true}], + }, + ]; fixture.detectChanges(); // click reset button - const resetButton: HTMLElement = fixture.debugElement.nativeElement.querySelector('.resetFilterButton'); + const resetButton: HTMLElement = + fixture.debugElement.nativeElement.querySelector('.resetFilterButton'); resetButton.click(); expect(instance.filterOption.options[0].buckets[0].checked).toEqual(false); }); }); +/** + * + */ function getSortContextType(): SortContext { return { name: 'sort', @@ -178,97 +210,102 @@ function getSortContextType(): SortContext { reversible: true, value: 'type', }, - ] - } + ], + }; } +/** + * + */ function getFilterContextType(): FilterContext { return { name: 'filter', compact: false, - options: facetsMock.filter((facet) => facet.buckets.length > 0).map((facet) => { - return { - buckets: facet.buckets.map((bucket) => { - return { - count: bucket.count, - key: bucket.key, - checked: false, - } - }), - compact: false, - field: facet.field, - onlyOnType: facet.onlyOnType - } - }) - } + options: facetsMock + .filter(facet => facet.buckets.length > 0) + .map(facet => { + return { + buckets: facet.buckets.map(bucket => { + return { + count: bucket.count, + key: bucket.key, + checked: false, + }; + }), + compact: false, + field: facet.field, + onlyOnType: facet.onlyOnType, + }; + }), + }; } const facetsMock: SCFacet[] = [ { - 'buckets': [ + buckets: [ { - 'count': 60, - 'key': 'academic event', + count: 60, + key: 'academic event', }, { - 'count': 160, - 'key': 'message', + count: 160, + key: 'message', }, { - 'count': 151, - 'key': 'date series', + count: 151, + key: 'date series', }, { - 'count': 106, - 'key': 'dish', + count: 106, + key: 'dish', }, { - 'count': 20, - 'key': 'building', + count: 20, + key: 'building', }, ], - 'field': 'type', + field: 'type', }, { - 'buckets': [ + buckets: [ { - 'count': 12, - 'key': 'Max Mustermann', + count: 12, + key: 'Max Mustermann', }, { - 'count': 2, - 'key': 'Foo Bar', + count: 2, + key: 'Foo Bar', }, ], - 'field': 'performers', - 'onlyOnType': SCThingType.AcademicEvent, + field: 'performers', + onlyOnType: SCThingType.AcademicEvent, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'colloquium', + count: 5, + key: 'colloquium', }, { - 'count': 15, - 'key': 'course', + count: 15, + key: 'course', }, ], - 'field': 'categories', - 'onlyOnType': SCThingType.AcademicEvent, + field: 'categories', + onlyOnType: SCThingType.AcademicEvent, }, { - 'buckets': [ + buckets: [ { - 'count': 5, - 'key': 'employees', + count: 5, + key: 'employees', }, { - 'count': 15, - 'key': 'students', + count: 15, + key: 'students', }, ], - 'field': 'audiences', - 'onlyOnType': SCThingType.Message, + field: 'audiences', + onlyOnType: SCThingType.Message, }, ]; diff --git a/src/app/modules/menu/context/context-menu.component.ts b/src/app/modules/menu/context/context-menu.component.ts index 4e75a877..c66066d5 100644 --- a/src/app/modules/menu/context/context-menu.component.ts +++ b/src/app/modules/menu/context/context-menu.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, OnDestroy} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import { SCLanguage, @@ -37,8 +37,7 @@ import {FilterContext, SortContext, SortContextOption} from './context-type'; selector: 'stapps-context', templateUrl: 'context-menu.html', }) -export class ContextMenuComponent { - +export class ContextMenuComponent implements OnDestroy { /** * Amount of filter options shown on compact view */ @@ -74,24 +73,26 @@ export class ContextMenuComponent { */ translator: SCThingTranslator; - - constructor(private translateService: TranslateService, - private readonly contextMenuService: ContextMenuService) { - this.language = this.translateService.currentLang as keyof SCTranslations; + constructor( + private translateService: TranslateService, + private readonly contextMenuService: ContextMenuService, + ) { + this.language = this.translateService + .currentLang as keyof SCTranslations; this.translator = new SCThingTranslator(this.language); - this.subscriptions.push(this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { - this.language = event.lang as keyof SCTranslations; - this.translator = new SCThingTranslator(this.language); - })); - - this.subscriptions.push(this.contextMenuService.filterContextChanged$.subscribe((filterContext) => { - this.filterOption = filterContext; - })); - - this.subscriptions.push(this.contextMenuService.sortOptions.subscribe((sortContext) => { - this.sortOption = sortContext; - })); + this.subscriptions.push( + this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { + this.language = event.lang as keyof SCTranslations; + this.translator = new SCThingTranslator(this.language); + }), + this.contextMenuService.filterContextChanged$.subscribe(filterContext => { + this.filterOption = filterContext; + }), + this.contextMenuService.sortOptions.subscribe(sortContext => { + this.sortOption = sortContext; + }), + ); } /** @@ -99,21 +100,31 @@ export class ContextMenuComponent { */ filterChanged = () => { this.contextMenuService.contextFilterChanged(this.filterOption); - } + }; /** * Returns translated property name */ - getTranslatedPropertyName(property: string, onlyForType?: SCThingType): string { - return (this.translator - // tslint:disable-next-line:no-any - .translatedPropertyNames(onlyForType ?? SCThingType.AcademicEvent) as any)[property]; + getTranslatedPropertyName( + property: string, + onlyForType?: SCThingType, + ): string { + return ( + this.translator.translatedPropertyNames( + onlyForType ?? SCThingType.AcademicEvent, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) as any + )[property]; } /** * Returns translated property value */ - getTranslatedPropertyValue(onlyForType: SCThingType, field: string, key?: string): string | undefined { + getTranslatedPropertyValue( + onlyForType: SCThingType, + field: string, + key?: string, + ): string | undefined { return this.translator.translatedPropertyValue(onlyForType, field, key); } @@ -130,11 +141,13 @@ export class ContextMenuComponent { * Resets filter options */ resetFilter = (option: FilterContext) => { - option.options.forEach((filterFacet) => filterFacet.buckets.forEach((filterBucket) => { - filterBucket.checked = false; - })); + for (const filterFacet of option.options) + for (const filterBucket of filterFacet.buckets) { + filterBucket.checked = false; + } + this.contextMenuService.contextFilterChanged(this.filterOption); - } + }; /** * Updates selected sort option and updates listener @@ -151,5 +164,5 @@ export class ContextMenuComponent { } } this.contextMenuService.contextSortChanged(option); - } + }; } diff --git a/src/app/modules/menu/context/context-menu.html b/src/app/modules/menu/context/context-menu.html index 99cc52a2..c01545bf 100644 --- a/src/app/modules/menu/context/context-menu.html +++ b/src/app/modules/menu/context/context-menu.html @@ -1,28 +1,38 @@ -

{{'menu.context.title' | translate | titlecase}}

+

{{ 'menu.context.title' | translate | titlecase }}

-
+ - {{'menu.context.sort.title' | translate | titlecase}} + {{ + 'menu.context.sort.title' | translate | titlecase + }} - - {{'menu.context.sort.' + value.value | translate | titlecase}} + + {{ 'menu.context.sort.' + value.value | translate | titlecase }} - - + + - - + @@ -30,48 +40,99 @@
- {{'menu.context.filter.title' | translate | titlecase}} - + {{ + 'menu.context.filter.title' | translate | titlecase + }} + - -
+ +
- {{(facet.onlyOnType ? getTranslatedPropertyName(facet.field, facet.onlyOnType) : (getTranslatedPropertyName(facet.field))) | titlecase}} - {{facet.onlyOnType ? ' | ' + (getTranslatedPropertyValue(facet.onlyOnType, 'type') | titlecase) : ''}} + {{ + (facet.onlyOnType + ? getTranslatedPropertyName(facet.field, facet.onlyOnType) + : getTranslatedPropertyName(facet.field) + ) | titlecase + }} + {{ + facet.onlyOnType + ? ' | ' + + (getTranslatedPropertyValue(facet.onlyOnType, 'type') + | titlecase) + : '' + }}
+ *ngFor=" + let bucket of !facet.compact + ? facet.buckets.slice(0, compactFilterOptionCount) + : facet.buckets + " + > - ({{bucket.count}}) {{facet.field === 'type' ? (getTranslatedPropertyValue($any(bucket.key), 'type') | titlecase) : - getTranslatedPropertyValue(facet.onlyOnType, facet.field, bucket.key) | titlecase}} + ({{ bucket.count }}) + {{ + facet.field === 'type' + ? (getTranslatedPropertyValue($any(bucket.key), 'type') + | titlecase) + : (getTranslatedPropertyValue( + facet.onlyOnType, + facet.field, + bucket.key + ) | titlecase) + }} + [(ngModel)]="bucket.checked" + (ngModelChange)="filterChanged()" + [value]="{ + field: facet.field, + value: bucket.key, + onlyOnType: facet.onlyOnType + }" + > - - {{'menu.context.filter.showAll' | translate}} + + {{ 'menu.context.filter.showAll' | translate }}
- - {{'menu.context.filter.showAll' | translate}} + + {{ 'menu.context.filter.showAll' | translate }}
diff --git a/src/app/modules/menu/context/context-menu.service.spec.ts b/src/app/modules/menu/context/context-menu.service.spec.ts index d8a3c067..a1f50124 100644 --- a/src/app/modules/menu/context/context-menu.service.spec.ts +++ b/src/app/modules/menu/context/context-menu.service.spec.ts @@ -9,7 +9,7 @@ describe('ContextMenuService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [ContextMenuService] + providers: [ContextMenuService], }); service = TestBed.get(ContextMenuService); }); @@ -18,38 +18,38 @@ describe('ContextMenuService', () => { expect(service).toBeTruthy(); }); - it('should update filterOptions', (done) => { - service.filterContextChanged$.subscribe((result) => { + it('should update filterOptions', done => { + service.filterContextChanged$.subscribe(result => { expect(result).toBeDefined(); done(); }); service.updateContextFilter(facetsMock); }); - it('should update filterQuery', (done) => { + it('should update filterQuery', done => { service.filterContextChanged$.subscribe(() => { service.contextFilterChanged(filterContext); }); - service.filterQueryChanged$.subscribe((result) => { + service.filterQueryChanged$.subscribe(result => { expect(result).toBeDefined(); done(); }); service.updateContextFilter(facetsMock); }); - it('should update sortOptions', (done) => { - service.sortContextChanged$.subscribe((result) => { + it('should update sortOptions', done => { + service.sortContextChanged$.subscribe(result => { expect(result).toBeDefined(); done(); }); service.setContextSort(sortContext); }); - it('should update sortQuery', (done) => { + it('should update sortQuery', done => { service.sortContextChanged$.subscribe(() => { service.contextSortChanged(sortContext); }); - service.sortQueryChanged$.subscribe((result) => { + service.sortQueryChanged$.subscribe(result => { expect(result).toBeDefined(); done(); }); @@ -57,37 +57,37 @@ describe('ContextMenuService', () => { }); }); - -const facetsMock: SCFacet[] = - [{ - 'buckets': [ +const facetsMock: SCFacet[] = [ + { + buckets: [ { - 'count': 60, - 'key': 'academic event', + count: 60, + key: 'academic event', }, { - 'count': 160, - 'key': 'message', + count: 160, + key: 'message', }, { - 'count': 151, - 'key': 'date series', + count: 151, + key: 'date series', }, { - 'count': 106, - 'key': 'dish', + count: 106, + key: 'dish', }, { - 'count': 20, - 'key': 'building', + count: 20, + key: 'building', }, { - 'count': 20, - 'key': 'semester', + count: 20, + key: 'semester', }, ], - 'field': 'type', - }]; + field: 'type', + }, +]; const filterContext: FilterContext = { name: 'filter', @@ -97,8 +97,9 @@ const filterContext: FilterContext = { { checked: true, count: 60, - key: 'academic event' - }, { + key: 'academic event', + }, + { checked: false, count: 160, key: 'message', @@ -106,26 +107,28 @@ const filterContext: FilterContext = { { checked: false, count: 151, - key: 'date series' - }, { + key: 'date series', + }, + { checked: false, count: 106, - key: 'dish' + key: 'dish', }, { checked: false, count: 20, - key: 'building' + key: 'building', }, { checked: false, count: 20, - key: 'semester' - } + key: 'semester', + }, ], - field: 'type' - }] -} + field: 'type', + }, + ], +}; const sortContext: SortContext = { name: 'sort', @@ -145,4 +148,4 @@ const sortContext: SortContext = { value: 'type', }, ], -} +}; diff --git a/src/app/modules/menu/context/context-menu.service.ts b/src/app/modules/menu/context/context-menu.service.ts index cb2add3b..08f00a82 100644 --- a/src/app/modules/menu/context/context-menu.service.ts +++ b/src/app/modules/menu/context/context-menu.service.ts @@ -13,16 +13,20 @@ * this program. If not, see . */ import {Injectable} from '@angular/core'; -import {SCFacet, SCFacetBucket, SCSearchFilter, SCSearchSort} from '@openstapps/core'; +import {SCFacet, SCSearchFilter, SCSearchSort} from '@openstapps/core'; import {Subject} from 'rxjs'; -import {FilterBucket, FilterContext, FilterFacet, SortContext} from './context-type'; +import { + FilterBucket, + FilterContext, + FilterFacet, + SortContext, +} from './context-type'; /** * ContextMenuService provides bidirectional communication of context menu options and search queries */ @Injectable() export class ContextMenuService { - /** * Local filter context object */ @@ -31,13 +35,13 @@ export class ContextMenuService { /** * Container for the filter context */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering filterOptions = new Subject(); /** * Observable filterContext streams */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering filterContextChanged$ = this.filterOptions.asObservable(); /** @@ -48,19 +52,19 @@ export class ContextMenuService { /** * Observable filterContext streams */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering filterQueryChanged$ = this.filterQuery.asObservable(); /** * Container for the sort context */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering sortOptions = new Subject(); /** * Observable SortContext streams */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering sortContextChanged$ = this.sortOptions.asObservable(); /** @@ -71,30 +75,32 @@ export class ContextMenuService { /** * Observable SortContext streams */ - // tslint:disable-next-line:member-ordering + // eslint-disable-next-line @typescript-eslint/member-ordering sortQueryChanged$ = this.sortQuery.asObservable(); /** * Returns SCSearchFilter if filterContext value is set, undefined otherwise + * * @param filterContext FilterContext to build SCSearchFilter from */ - buildFilterQuery = (filterContext: FilterContext): SCSearchFilter | undefined => { + buildFilterQuery = ( + filterContext: FilterContext, + ): SCSearchFilter | undefined => { const filters: SCSearchFilter[] = []; - filterContext.options.forEach((filterFacet) => { + for (const filterFacet of filterContext.options) { const optionFilters: SCSearchFilter[] = []; - filterFacet.buckets.forEach((filterBucket) => { + for (const filterBucket of filterFacet.buckets) { if (filterBucket.checked) { - optionFilters.push( - { - arguments: { - field: filterFacet.field, - value: filterBucket.key, - }, - type: 'value', - }); + optionFilters.push({ + arguments: { + field: filterFacet.field, + value: filterBucket.key, + }, + type: 'value', + }); } - }); + } if (optionFilters.length > 0) { filters.push({ arguments: { @@ -104,7 +110,7 @@ export class ContextMenuService { type: 'boolean', }); } - }); + } if (filters.length > 0) { return { @@ -117,28 +123,31 @@ export class ContextMenuService { } return; - } + }; /** * Returns SCSearchSort if sorting value is set, undefined otherwise + * * @param sortContext SortContext to build SCSearchSort from */ buildSortQuery = (sortContext: SortContext): SCSearchSort | undefined => { - if (sortContext.value && sortContext.value.length > 0) { - if (sortContext.value === 'name' || sortContext.value === 'type') { - return { - arguments: { - field: sortContext.value, - position: 0, - }, - order: sortContext.reversed ? 'desc' : 'asc', - type: 'ducet', - }; - } + if ( + sortContext.value && + sortContext.value.length > 0 && + (sortContext.value === 'name' || sortContext.value === 'type') + ) { + return { + arguments: { + field: sortContext.value, + position: 0, + }, + order: sortContext.reversed ? 'desc' : 'asc', + type: 'ducet', + }; } return; - } + }; /** * Updates filter query from filterContext @@ -192,7 +201,10 @@ export class ContextMenuService { * Updates context filter with new facets. * It preserves the checked status of existing filter options */ - updateContextFilterOptions = (contextFilter: FilterContext, facets: SCFacet[]) => { + updateContextFilterOptions = ( + contextFilter: FilterContext, + facets: SCFacet[], + ) => { const newFilterOptions: FilterFacet[] = []; // iterate new facets @@ -206,19 +218,28 @@ export class ContextMenuService { newFilterOptions.push(newFilterFacet); // search existing filterOption - const filterOption = contextFilter.options.find((contextFacet: FilterFacet) => - contextFacet.field === facet.field && contextFacet.onlyOnType === facet.onlyOnType); - facet.buckets.forEach((bucket: SCFacetBucket) => { + const filterOption = contextFilter.options.find( + (contextFacet: FilterFacet) => + contextFacet.field === facet.field && + contextFacet.onlyOnType === facet.onlyOnType, + ); + for (const bucket of facet.buckets) { // search existing bucket to preserve checked status - const existingFilterBucket = filterOption ? filterOption.buckets - .find((contextBucket: FilterBucket) => contextBucket.key === bucket.key) : undefined; + const existingFilterBucket = filterOption + ? filterOption.buckets.find( + (contextBucket: FilterBucket) => + contextBucket.key === bucket.key, + ) + : undefined; const filterBucket: FilterBucket = { - checked: existingFilterBucket ? existingFilterBucket.checked : false, + checked: existingFilterBucket + ? existingFilterBucket.checked + : false, count: bucket.count, key: bucket.key, }; newFilterFacet.buckets.push(filterBucket); - }); + } } } @@ -227,5 +248,5 @@ export class ContextMenuService { this.contextFilter = contextFilter; this.filterOptions.next(contextFilter); - } + }; } diff --git a/src/app/modules/menu/context/context-type.ts b/src/app/modules/menu/context/context-type.ts index 2abe8021..9acfbcf2 100644 --- a/src/app/modules/menu/context/context-type.ts +++ b/src/app/modules/menu/context/context-type.ts @@ -14,8 +14,6 @@ */ import {SCFacet, SCFacetBucket} from '@openstapps/core'; -export type ContextType = FilterContext | SortContext; - /** * A sort context */ diff --git a/src/app/modules/menu/menu.module.ts b/src/app/modules/menu/menu.module.ts index 1d7ebbea..1118c4f9 100644 --- a/src/app/modules/menu/menu.module.ts +++ b/src/app/modules/menu/menu.module.ts @@ -27,24 +27,16 @@ import {NavigationComponent} from './navigation/navigation.component'; * Menu module */ @NgModule({ - declarations: [ - NavigationComponent, - ContextMenuComponent, - ], - exports: [ - NavigationComponent, - ContextMenuComponent, - ], + declarations: [NavigationComponent, ContextMenuComponent], + exports: [NavigationComponent, ContextMenuComponent], imports: [ + CommonModule, FormsModule, IonicModule.forRoot(), - TranslateModule.forChild(), - CommonModule, RouterModule, SettingsModule, + TranslateModule.forChild(), ], - providers: [ - ContextMenuService, - ], + providers: [ContextMenuService], }) export class MenuModule {} diff --git a/src/app/modules/menu/navigation/navigation.component.ts b/src/app/modules/menu/navigation/navigation.component.ts index 0a84fc82..f68df701 100644 --- a/src/app/modules/menu/navigation/navigation.component.ts +++ b/src/app/modules/menu/navigation/navigation.component.ts @@ -14,7 +14,12 @@ */ import {Component} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; -import {SCAppConfigurationMenuCategory, SCLanguage, SCThingTranslator, SCTranslations} from '@openstapps/core'; +import { + SCAppConfigurationMenuCategory, + SCLanguage, + SCThingTranslator, + SCTranslations, +} from '@openstapps/core'; import {NGXLogger} from 'ngx-logger'; import {ConfigProvider} from '../../config/config.provider'; @@ -30,7 +35,6 @@ import {ConfigProvider} from '../../config/config.provider'; templateUrl: 'navigation.html', }) export class NavigationComponent { - /** * Possible languages to be used for translation */ @@ -46,10 +50,12 @@ export class NavigationComponent { */ translator: SCThingTranslator; - constructor(private readonly configProvider: ConfigProvider, - public translateService: TranslateService, - private readonly logger: NGXLogger) { - this.loadMenuEntries(); + constructor( + private readonly configProvider: ConfigProvider, + public translateService: TranslateService, + private readonly logger: NGXLogger, + ) { + void this.loadMenuEntries(); translateService.onLangChange.subscribe((event: LangChangeEvent) => { this.language = event.lang as keyof SCTranslations; this.translator = new SCThingTranslator(this.language); @@ -62,11 +68,12 @@ export class NavigationComponent { */ async loadMenuEntries() { try { - this.menu = await this.configProvider.getValue('menus') as SCAppConfigurationMenuCategory[]; + this.menu = (await this.configProvider.getValue( + 'menus', + )) as SCAppConfigurationMenuCategory[]; } catch (error) { this.logger.error(`error from loading menu entries: ${error}`); } - } // openPage(page) { diff --git a/src/app/modules/menu/navigation/navigation.html b/src/app/modules/menu/navigation/navigation.html index 0aa10636..01a2986d 100644 --- a/src/app/modules/menu/navigation/navigation.html +++ b/src/app/modules/menu/navigation/navigation.html @@ -6,24 +6,23 @@ - + StApps - + - {{category.translations[language].name | titlecase}} + {{ category.translations[language].name | titlecase }} - {{item.translations[language].title | titlecase}} + {{ item.translations[language].title | titlecase }} diff --git a/src/app/modules/news/news.module.ts b/src/app/modules/news/news.module.ts index 62066ee3..ecfed80f 100644 --- a/src/app/modules/news/news.module.ts +++ b/src/app/modules/news/news.module.ts @@ -22,31 +22,27 @@ import {DataModule} from '../data/data.module'; import {SettingsProvider} from '../settings/settings.provider'; import {NewsItemComponent} from './page/news-item.component'; import {NewsPageComponent} from './page/news-page.component'; -import {SkeletonNewsItem} from './page/skeleton-news-item.component'; +import {SkeletonNewsItemComponent} from './page/skeleton-news-item.component'; -const newsRoutes: Routes = [ - {path: 'news', component: NewsPageComponent}, -]; +const newsRoutes: Routes = [{path: 'news', component: NewsPageComponent}]; /** * News Module */ @NgModule({ declarations: [ - NewsPageComponent, - SkeletonNewsItem, NewsItemComponent, + NewsPageComponent, + SkeletonNewsItemComponent, ], imports: [ - IonicModule.forRoot(), - TranslateModule.forChild(), - RouterModule.forChild(newsRoutes), CommonModule, - MomentModule, DataModule, + IonicModule.forRoot(), + MomentModule, + RouterModule.forChild(newsRoutes), + TranslateModule.forChild(), ], - providers: [ - SettingsProvider, - ], + providers: [SettingsProvider], }) export class NewsModule {} diff --git a/src/app/modules/news/news.provider.ts b/src/app/modules/news/news.provider.ts index 1c4caa35..5f3fa0d1 100644 --- a/src/app/modules/news/news.provider.ts +++ b/src/app/modules/news/news.provider.ts @@ -15,6 +15,7 @@ import {Injectable} from '@angular/core'; import {SCMessage} from '@openstapps/core'; import {DataProvider} from '../data/data.provider'; + /** * Service for providing news messages */ @@ -22,12 +23,12 @@ import {DataProvider} from '../data/data.provider'; providedIn: 'root', }) export class NewsProvider { - constructor(private dataProvider: DataProvider) { - } + constructor(private dataProvider: DataProvider) {} /** * Get news messages * TODO: make dates sortable on the backend side and then adjust this method + * * @param size How many messages/news to fetch * @param sort If sort by date needs to be performed */ @@ -47,8 +48,15 @@ export class NewsProvider { if (sort) { news.sort((a, b) => { - if (typeof a.datePublished !== 'undefined' && typeof b.datePublished !== 'undefined') { - return (a.datePublished > b.datePublished) ? -1 : ((a.datePublished < b.datePublished) ? 1 : 0); + if ( + typeof a.datePublished !== 'undefined' && + typeof b.datePublished !== 'undefined' + ) { + return a.datePublished > b.datePublished + ? -1 + : a.datePublished < b.datePublished + ? 1 + : 0; } return 0; diff --git a/src/app/modules/news/page/news-item.component.ts b/src/app/modules/news/page/news-item.component.ts index 432a6e09..90010b75 100644 --- a/src/app/modules/news/page/news-item.component.ts +++ b/src/app/modules/news/page/news-item.component.ts @@ -27,5 +27,4 @@ export class NewsItemComponent { * News (message) to show */ @Input() item: SCMessage; - } diff --git a/src/app/modules/news/page/news-item.html b/src/app/modules/news/page/news-item.html index 078abcbc..dcb2de4d 100644 --- a/src/app/modules/news/page/news-item.html +++ b/src/app/modules/news/page/news-item.html @@ -1,25 +1,41 @@ - - - - - - - + + + + + + + - + - {{item.datePublished | amDateFormat:'LLL'}} + {{ + item.datePublished | amDateFormat: 'LLL' + }} - {{item.name}} - {{item.name}} + {{ item.name }} + {{ item.name }} - {{item.messageBody}} + {{ item.messageBody }} diff --git a/src/app/modules/news/page/news-page.component.ts b/src/app/modules/news/page/news-page.component.ts index 6edcb9c7..cad46950 100644 --- a/src/app/modules/news/page/news-page.component.ts +++ b/src/app/modules/news/page/news-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, OnInit} from '@angular/core'; import {IonRefresher} from '@ionic/angular'; import {SCMessage} from '@openstapps/core'; import {NewsProvider} from '../news.provider'; @@ -23,20 +23,19 @@ import {NewsProvider} from '../news.provider'; selector: 'stapps-news-page', templateUrl: 'news-page.html', }) -export class NewsPageComponent { +export class NewsPageComponent implements OnInit { /** * News (messages) to show */ news: SCMessage[] = []; - constructor(private newsProvider: NewsProvider) { - } + constructor(private newsProvider: NewsProvider) {} /** * Fetch news from the backend */ async fetchNews() { - /* tslint:disable:no-magic-numbers */ + /* eslint-disable no-magic-numbers */ this.news = await this.newsProvider.getList(30, true); } @@ -55,7 +54,7 @@ export class NewsPageComponent { async refresh(refresher: IonRefresher) { try { await this.fetchNews(); - } catch (e) { + } catch { this.news = []; } finally { await refresher.complete(); diff --git a/src/app/modules/news/page/news-page.html b/src/app/modules/news/page/news-page.html index 38f71463..e92a79e0 100644 --- a/src/app/modules/news/page/news-page.html +++ b/src/app/modules/news/page/news-page.html @@ -5,14 +5,17 @@ - {{'news.title' | translate}} + {{ 'news.title' | translate }} - + diff --git a/src/app/modules/news/page/skeleton-news-item.component.ts b/src/app/modules/news/page/skeleton-news-item.component.ts index 9e325cbb..3f168138 100644 --- a/src/app/modules/news/page/skeleton-news-item.component.ts +++ b/src/app/modules/news/page/skeleton-news-item.component.ts @@ -21,5 +21,4 @@ import {Component} from '@angular/core'; selector: 'stapps-skeleton-news-item', templateUrl: 'skeleton-news-item.html', }) -export class SkeletonNewsItem { -} +export class SkeletonNewsItemComponent {} diff --git a/src/app/modules/news/page/skeleton-news-item.html b/src/app/modules/news/page/skeleton-news-item.html index fa2ad103..d3413067 100644 --- a/src/app/modules/news/page/skeleton-news-item.html +++ b/src/app/modules/news/page/skeleton-news-item.html @@ -1,12 +1,18 @@ - - - + + + -

-

-

+

+

+

diff --git a/src/app/modules/settings/item/settings-item.component.ts b/src/app/modules/settings/item/settings-item.component.ts index 00863f12..4fc14d3b 100644 --- a/src/app/modules/settings/item/settings-item.component.ts +++ b/src/app/modules/settings/item/settings-item.component.ts @@ -31,7 +31,6 @@ import {SettingsProvider} from '../settings.provider'; templateUrl: 'settings-item.html', }) export class SettingsItemComponent { - /** * If set the setting will be shown as compact view */ @@ -41,6 +40,7 @@ export class SettingsItemComponent { * Flag for workaround for selected 'select option' not updating translation */ isVisible = true; + /** * The setting to handle */ @@ -52,13 +52,15 @@ export class SettingsItemComponent { * @param translateService TranslateService * @param settingsProvider SettingProvider */ - constructor(private readonly alertCtrl: AlertController, - private readonly translateService: TranslateService, - private readonly settingsProvider: SettingsProvider) { + constructor( + private readonly alertCtrl: AlertController, + private readonly translateService: TranslateService, + private readonly settingsProvider: SettingsProvider, + ) { translateService.onLangChange.subscribe((_event: LangChangeEvent) => { this.isVisible = false; // TODO: Issue #53 check workaround for selected 'select option' not updating translation - setTimeout(() => this.isVisible = true); + setTimeout(() => (this.isVisible = true)); }); } @@ -81,8 +83,10 @@ export class SettingsItemComponent { * Handles value changes of the setting */ async settingChanged(): Promise { - if (typeof this.setting.value !== 'undefined' - && SettingsProvider.validateValue(this.setting, this.setting.value)) { + if ( + typeof this.setting.value !== 'undefined' && + SettingsProvider.validateValue(this.setting, this.setting.value) + ) { // handle general settings, with special actions switch (this.setting.name) { case 'language': @@ -90,23 +94,25 @@ export class SettingsItemComponent { break; default: } - await this.settingsProvider - .setSettingValue(this.setting.categories[0], - this.setting.name, - this.setting.value); + await this.settingsProvider.setSettingValue( + this.setting.categories[0], + this.setting.name, + this.setting.value, + ); } else { // reset setting - this.setting.value = - await this.settingsProvider - .getValue(this.setting.categories[0], this.setting.name) as (SCSettingValue | SCSettingValues); + this.setting.value = (await this.settingsProvider.getValue( + this.setting.categories[0], + this.setting.name, + )) as SCSettingValue | SCSettingValues; } } /** * Mapping of typeOf for Html usage */ - // tslint:disable-next-line:prefer-function-over-method - typeOf(val: unknown) { - return typeof (val); + // eslint-disable-next-line class-methods-use-this + typeOf(value: unknown) { + return typeof value; } } diff --git a/src/app/modules/settings/item/settings-item.html b/src/app/modules/settings/item/settings-item.html index afba4e7d..1bb980b3 100644 --- a/src/app/modules/settings/item/settings-item.html +++ b/src/app/modules/settings/item/settings-item.html @@ -1,37 +1,80 @@ - + {{ vals.name }} - + - {{ 'description' | thingTranslate: setting | titlecase }} + {{ + 'description' | thingTranslate: setting | titlecase + }} -
+
- + - + - + - + - - -
{{ ('values' | thingTranslate: setting)[i] | titlecase }}
+ + +
+ {{ ('values' | thingTranslate: setting)[i] | titlecase }} +
{{ val }}
@@ -39,9 +82,18 @@ - - -
{{ ('values' | thingTranslate: setting)[i] | titlecase }}
+ + +
+ {{ ('values' | thingTranslate: setting)[i] | titlecase }} +
{{ val }}
diff --git a/src/app/modules/settings/page/settings-page.component.ts b/src/app/modules/settings/page/settings-page.component.ts index e66128df..754c69c6 100644 --- a/src/app/modules/settings/page/settings-page.component.ts +++ b/src/app/modules/settings/page/settings-page.component.ts @@ -12,31 +12,35 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectorRef, Component} from '@angular/core'; +import {ChangeDetectorRef, Component, OnInit} from '@angular/core'; import {AlertController, ToastController} from '@ionic/angular'; import {TranslateService} from '@ngx-translate/core'; import {SCSettingMeta} from '@openstapps/core'; import {SettingsCache, SettingsProvider} from '../settings.provider'; - /** - * Settings page component - */ + +/** + * Settings page component + */ @Component({ selector: 'stapps-settings-page', templateUrl: 'settings-page.html', }) -export class SettingsPageComponent { +export class SettingsPageComponent implements OnInit { /** * Order of the categories */ categoriesOrder: string[]; + /** * Meta information about settings */ meta = SCSettingMeta; + /** * Mapping of Object.keys for Html usage */ objectKeys = Object.keys; + /** * Container to cache settings from provider */ @@ -50,11 +54,13 @@ export class SettingsPageComponent { * @param translateService TranslateService * @param changeDetectorRef ChangeDetectorRef */ - constructor(private readonly alertController: AlertController, - private readonly settingsProvider: SettingsProvider, - private readonly toastController: ToastController, - private readonly translateService: TranslateService, - private readonly changeDetectorRef: ChangeDetectorRef) { + constructor( + private readonly alertController: AlertController, + private readonly settingsProvider: SettingsProvider, + private readonly toastController: ToastController, + private readonly translateService: TranslateService, + private readonly changeDetectorRef: ChangeDetectorRef, + ) { this.settingsCache = {}; } @@ -92,13 +98,17 @@ export class SettingsPageComponent { * Presents an alert to the user to reset settings to default values */ async presentResetAlert() { - const cancelText = await this.translateService.get('settings.resetAlert.buttonCancel') + const cancelText = await this.translateService + .get('settings.resetAlert.buttonCancel') .toPromise(); - const yesText = await this.translateService.get('settings.resetAlert.buttonYes') + const yesText = await this.translateService + .get('settings.resetAlert.buttonYes') .toPromise(); - const title = await this.translateService.get('settings.resetAlert.title') + const title = await this.translateService + .get('settings.resetAlert.title') .toPromise(); - const message = await this.translateService.get('settings.resetAlert.message') + const message = await this.translateService + .get('settings.resetAlert.message') .toPromise(); const alert = await this.alertController.create({ @@ -117,7 +127,7 @@ export class SettingsPageComponent { header: title, message: message, }); - alert.present(); + await alert.present(); } /** @@ -129,15 +139,17 @@ export class SettingsPageComponent { await this.presentSettingsResetToast(); } - /** - * Shows alert to reset settings - */ + /** + * Shows alert to reset settings + */ async showResetAlert() { const alert = await this.alertController.create({ buttons: [ { role: 'cancel', - text: this.translateService.instant('settings.resetAlert.buttonCancel'), + text: this.translateService.instant( + 'settings.resetAlert.buttonCancel', + ), }, { handler: async () => { @@ -150,6 +162,6 @@ export class SettingsPageComponent { message: this.translateService.instant('settings.resetAlert.message'), }); - alert.present(); + await alert.present(); } } diff --git a/src/app/modules/settings/page/settings-page.html b/src/app/modules/settings/page/settings-page.html index c7b8ac04..e2f10366 100644 --- a/src/app/modules/settings/page/settings-page.html +++ b/src/app/modules/settings/page/settings-page.html @@ -4,21 +4,40 @@ - {{'settings.title' | translate | titlecase}} + {{ 'settings.title' | translate | titlecase }} - +
-
{{ 'categories[0]' | thingTranslate: settingsCache[categoryKey]?.settings[objectKeys(settingsCache[categoryKey]?.settings)[0]] | titlecase }}
+
+ {{ + 'categories[0]' + | thingTranslate + : settingsCache[categoryKey]?.settings[ + objectKeys(settingsCache[categoryKey]?.settings)[0] + ] + | titlecase + }} +
- +
- - {{'settings.resetSettings' | translate}} + + {{ 'settings.resetSettings' | translate }}
diff --git a/src/app/modules/settings/settings.module.ts b/src/app/modules/settings/settings.module.ts index e4397af2..3f955911 100644 --- a/src/app/modules/settings/settings.module.ts +++ b/src/app/modules/settings/settings.module.ts @@ -33,24 +33,16 @@ const settingsRoutes: Routes = [ * Settings Module */ @NgModule({ - declarations: [ - SettingsPageComponent, - SettingsItemComponent, - ], - exports: [ - SettingsItemComponent, - ], + declarations: [SettingsPageComponent, SettingsItemComponent], + exports: [SettingsItemComponent], imports: [ CommonModule, FormsModule, IonicModule.forRoot(), - TranslateModule.forChild(), - ThingTranslateModule.forChild(), RouterModule.forChild(settingsRoutes), + ThingTranslateModule.forChild(), + TranslateModule.forChild(), ], - providers: [ - ConfigProvider, - SettingsProvider, - ], + providers: [ConfigProvider, SettingsProvider], }) export class SettingsModule {} diff --git a/src/app/modules/settings/settings.provider.spec.ts b/src/app/modules/settings/settings.provider.spec.ts index 3fe1af8e..d7b391a1 100644 --- a/src/app/modules/settings/settings.provider.spec.ts +++ b/src/app/modules/settings/settings.provider.spec.ts @@ -13,10 +13,19 @@ * this program. If not, see . */ import {TestBed} from '@angular/core/testing'; -import {SCSetting, SCThingOriginType, SCThingType, SCSettingInputType} from '@openstapps/core'; +import { + SCSetting, + SCThingOriginType, + SCThingType, + SCSettingInputType, +} from '@openstapps/core'; import {ConfigProvider} from '../config/config.provider'; import {StorageProvider} from '../storage/storage.provider'; -import {SettingsProvider, SettingValuesContainer, STORAGE_KEY_SETTING_VALUES} from './settings.provider'; +import { + SettingsProvider, + SettingValuesContainer, + STORAGE_KEY_SETTING_VALUES, +} from './settings.provider'; describe('SettingsProvider', () => { let configProviderSpy: jasmine.SpyObj; @@ -24,50 +33,73 @@ describe('SettingsProvider', () => { let storageProviderSpy: jasmine.SpyObj; beforeEach(async () => { - const storageProviderMethodSpy = jasmine.createSpyObj('StorageProvider', ['init', 'get', 'has', 'put']); - const configProviderMethodSpy = jasmine.createSpyObj('ConfigProvider', ['getValue']); + const storageProviderMethodSpy = jasmine.createSpyObj('StorageProvider', [ + 'init', + 'get', + 'has', + 'put', + ]); + const configProviderMethodSpy = jasmine.createSpyObj('ConfigProvider', [ + 'getValue', + ]); TestBed.configureTestingModule({ imports: [], providers: [ SettingsProvider, { - provide: StorageProvider, useValue: storageProviderMethodSpy, + provide: StorageProvider, + useValue: storageProviderMethodSpy, }, { - provide: ConfigProvider, useValue: configProviderMethodSpy, + provide: ConfigProvider, + useValue: configProviderMethodSpy, }, ], }); configProviderSpy = TestBed.get(ConfigProvider); // set settings returned from config - configProviderSpy.getValue.and.returnValue(Promise.resolve(CONFIG_SETTINGS_MOCK)); + configProviderSpy.getValue.and.returnValue( + Promise.resolve(CONFIG_SETTINGS_MOCK), + ); settingsProvider = TestBed.get(SettingsProvider); storageProviderSpy = TestBed.get(StorageProvider); storageProviderMethodSpy.has.and.returnValue(false); }); it('should provide and get setting', async () => { - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); - const setting: SCSetting = await settingsProvider - .getSetting(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])), + ); + const setting: SCSetting = await settingsProvider.getSetting( + CONFIG_SETTINGS_MOCK[0].categories[0], + CONFIG_SETTINGS_MOCK[0].name, + ); await expect(setting.value).toBeDefined(); }); it('should provide and get settings value', async () => { - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); - const value = await settingsProvider - .getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])), + ); + const value = await settingsProvider.getValue( + CONFIG_SETTINGS_MOCK[0].categories[0], + CONFIG_SETTINGS_MOCK[0].name, + ); await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue); }); it('should get persisted setting value', async () => { // set return values of storage storageProviderSpy.has.and.returnValue(Promise.resolve(true)); - storageProviderSpy.get.and.returnValue(Promise.resolve(SETTING_VALUES_MOCK)); + storageProviderSpy.get.and.returnValue( + Promise.resolve(SETTING_VALUES_MOCK), + ); - const value = await settingsProvider - .getValue(CONFIG_SETTINGS_MOCK[3].categories[0], CONFIG_SETTINGS_MOCK[3].name); + const value = await settingsProvider.getValue( + CONFIG_SETTINGS_MOCK[3].categories[0], + CONFIG_SETTINGS_MOCK[3].name, + ); await expect(value).toEqual(SETTING_VALUES_MOCK.profile.group); }); @@ -75,74 +107,100 @@ describe('SettingsProvider', () => { // set return values of spy objects storageProviderSpy.has.and.returnValue(Promise.resolve(true)); storageProviderSpy.get.and.returnValue(Promise.resolve([])); - const value = await settingsProvider - .getValue(CONFIG_SETTINGS_MOCK[3].categories[0], CONFIG_SETTINGS_MOCK[3].name); + const value = await settingsProvider.getValue( + CONFIG_SETTINGS_MOCK[3].categories[0], + CONFIG_SETTINGS_MOCK[3].name, + ); await expect(value).toEqual(CONFIG_SETTINGS_MOCK[3].defaultValue); }); it('should keep persisted setting values from settings that are not contained in loaded config', async () => { - const settings = [ - CONFIG_SETTINGS_MOCK[4], - CONFIG_SETTINGS_MOCK[5], - ]; + const settings = [CONFIG_SETTINGS_MOCK[4], CONFIG_SETTINGS_MOCK[5]]; configProviderSpy.getValue.and.returnValue(Promise.resolve(settings)); storageProviderSpy.has.and.returnValue(Promise.resolve(true)); - storageProviderSpy.get.and.returnValue(Promise.resolve(SETTING_VALUES_MOCK)); + storageProviderSpy.get.and.returnValue( + Promise.resolve(SETTING_VALUES_MOCK), + ); await settingsProvider.init(); - await expect(storageProviderSpy.put).toHaveBeenCalledWith(STORAGE_KEY_SETTING_VALUES, SETTING_VALUES_MOCK); + await expect(storageProviderSpy.put).toHaveBeenCalledWith( + STORAGE_KEY_SETTING_VALUES, + SETTING_VALUES_MOCK, + ); }); it('should set value of a provided setting', async () => { - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[1]))); - await settingsProvider - .setSettingValue(CONFIG_SETTINGS_MOCK[1].categories[0], CONFIG_SETTINGS_MOCK[1].name, 'updated'); - const value = await settingsProvider - .getValue(CONFIG_SETTINGS_MOCK[1].categories[0], CONFIG_SETTINGS_MOCK[1].name); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[1])), + ); + await settingsProvider.setSettingValue( + CONFIG_SETTINGS_MOCK[1].categories[0], + CONFIG_SETTINGS_MOCK[1].name, + 'updated', + ); + const value = await settingsProvider.getValue( + CONFIG_SETTINGS_MOCK[1].categories[0], + CONFIG_SETTINGS_MOCK[1].name, + ); await expect(value).toEqual('updated'); }); it('should return copy of settingsCache', async () => { const category = CONFIG_SETTINGS_MOCK[0].categories[0]; const name = CONFIG_SETTINGS_MOCK[0].name; - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])), + ); const settings = await settingsProvider.getCache(); settings[category].settings[name].value = 'testValue'; // cached setting value should still be defaultValue - await expect((await settingsProvider.getValue(category, name))) - .toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue); + await expect(await settingsProvider.getValue(category, name)).toEqual( + CONFIG_SETTINGS_MOCK[0].defaultValue, + ); }); it('should call storage put on setSettingValue', async () => { - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); - await settingsProvider - .setSettingValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name, ''); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])), + ); + await settingsProvider.setSettingValue( + CONFIG_SETTINGS_MOCK[0].categories[0], + CONFIG_SETTINGS_MOCK[0].name, + '', + ); await expect(storageProviderSpy.put).toHaveBeenCalled(); }); it('should clear settings', async () => { await settingsProvider.reset(); - await expect(storageProviderSpy.put).toHaveBeenCalledWith(STORAGE_KEY_SETTING_VALUES, {}); + await expect(storageProviderSpy.put).toHaveBeenCalledWith( + STORAGE_KEY_SETTING_VALUES, + {}, + ); }); it('should reset settings', async () => { const category = CONFIG_SETTINGS_MOCK[0].categories[0]; const name = CONFIG_SETTINGS_MOCK[0].name; - await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); + await settingsProvider.provideSetting( + JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])), + ); await settingsProvider.setSettingValue(category, name, 'guest'); await settingsProvider.resetDefault(); - const value = await settingsProvider - .getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name); + const value = await settingsProvider.getValue( + CONFIG_SETTINGS_MOCK[0].categories[0], + CONFIG_SETTINGS_MOCK[0].name, + ); await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue); }); it('should validate wrong values for inputType text', async () => { - await testValue(CONFIG_SETTINGS_MOCK[0], 123456789); + await testValue(CONFIG_SETTINGS_MOCK[0], 123_456_789); await testValue(CONFIG_SETTINGS_MOCK[0], false); await testValue(CONFIG_SETTINGS_MOCK[0], []); }); it('should validate wrong values for inputType password', async () => { - await testValue(CONFIG_SETTINGS_MOCK[0], 123456789); + await testValue(CONFIG_SETTINGS_MOCK[0], 123_456_789); await testValue(CONFIG_SETTINGS_MOCK[0], false); await testValue(CONFIG_SETTINGS_MOCK[0], []); }); @@ -155,34 +213,43 @@ describe('SettingsProvider', () => { it('should validate wrong values for inputType singleChoice text', async () => { await testValue(CONFIG_SETTINGS_MOCK[3], ''); - await testValue(CONFIG_SETTINGS_MOCK[3], 123456); + await testValue(CONFIG_SETTINGS_MOCK[3], 123_456); await testValue(CONFIG_SETTINGS_MOCK[3], false); await testValue(CONFIG_SETTINGS_MOCK[3], []); }); it('should validate wrong values for inputType singleChoice boolean', async () => { await testValue(CONFIG_SETTINGS_MOCK[5], ''); - await testValue(CONFIG_SETTINGS_MOCK[5], 123456); + await testValue(CONFIG_SETTINGS_MOCK[5], 123_456); await testValue(CONFIG_SETTINGS_MOCK[5], []); }); it('should validate wrong values for inputType multipleChoice', async () => { await testValue(CONFIG_SETTINGS_MOCK[6], ''); - await testValue(CONFIG_SETTINGS_MOCK[6], 123456); + await testValue(CONFIG_SETTINGS_MOCK[6], 123_456); await testValue(CONFIG_SETTINGS_MOCK[6], false); await testValue(CONFIG_SETTINGS_MOCK[6], [1, 9]); }); - async function testValue(setting: SCSetting, value: any) { + /** + * TODO + */ + async function testValue(setting: SCSetting, value: unknown) { let error: Error; await settingsProvider.provideSetting(JSON.parse(JSON.stringify(setting))); try { - await settingsProvider.setSettingValue(setting.categories[0], setting.name, value); - } catch (err) { - error = err; + await settingsProvider.setSettingValue( + setting.categories[0], + setting.name, + value as never, + ); + } catch (error_) { + error = error_; } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await expect(error).toBeDefined(); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await expect(error.message).toMatch(/is not valid/); } @@ -270,13 +337,15 @@ describe('SettingsProvider', () => { }, translations: { de: { - description: 'Mit welcher Benutzergruppe soll die App verwendet werden?' - + ' Die Einstellung wird beispielsweise für die Vorauswahl der Preiskategorie der Mensa verwendet.', + description: + 'Mit welcher Benutzergruppe soll die App verwendet werden?' + + ' Die Einstellung wird beispielsweise für die Vorauswahl der Preiskategorie der Mensa verwendet.', name: 'Gruppe', }, en: { - description: 'The user group the app is going to be used.' - + 'This settings for example is getting used for the predefined price category of mensa meals.', + description: + 'The user group the app is going to be used.' + + 'This settings for example is getting used for the predefined price category of mensa meals.', name: 'Group', }, }, diff --git a/src/app/modules/settings/settings.provider.ts b/src/app/modules/settings/settings.provider.ts index 21960759..7696bac1 100644 --- a/src/app/modules/settings/settings.provider.ts +++ b/src/app/modules/settings/settings.provider.ts @@ -13,11 +13,7 @@ * this program. If not, see . */ import {Injectable} from '@angular/core'; -import { - SCSetting, - SCSettingValue, - SCSettingValues, -} from '@openstapps/core'; +import {SCSetting, SCSettingValue, SCSettingValues} from '@openstapps/core'; import deepMerge from 'deepmerge'; import {Subject} from 'rxjs'; import {ConfigProvider} from '../config/config.provider'; @@ -38,7 +34,7 @@ export interface CategoryWithSettings { /** * Settings that belong in this category */ - settings: { [key: string]: SCSetting; }; + settings: {[key: string]: SCSetting}; } /** @@ -99,14 +95,17 @@ export class SettingsProvider { * Source of settings actions */ private settingsActionSource = new Subject(); + /** * Order of the setting categories */ categoriesOrder: string[]; + /** * Settings actions observable */ settingsActionChanged$ = this.settingsActionSource.asObservable(); + /** * Cache for the imported settings */ @@ -114,6 +113,7 @@ export class SettingsProvider { /** * Return true if all given values are valid to possible values in given settingInput + * * @param possibleValues Possible values * @param enteredValues Entered value */ @@ -121,7 +121,7 @@ export class SettingsProvider { possibleValues: SCSettingValues | undefined, enteredValues: SCSettingValues, ): boolean { - if ( typeof possibleValues === 'undefined' ) { + if (typeof possibleValues === 'undefined') { return false; } @@ -136,6 +136,7 @@ export class SettingsProvider { /** * Returns true if given value is valid to possible values in given settingInput + * * @param possibleValues Possible values * @param enteredValue Entered value */ @@ -143,21 +144,27 @@ export class SettingsProvider { possibleValues: SCSettingValues | undefined, enteredValue: SCSettingValue, ): boolean { - if ( typeof possibleValues === 'undefined' ) { + if (typeof possibleValues === 'undefined') { return false; } - return possibleValues !== undefined - && (Array.isArray(possibleValues) - && possibleValues.includes(enteredValue)); + return ( + possibleValues !== undefined && + Array.isArray(possibleValues) && + possibleValues.includes(enteredValue) + ); } /** * Validates value for given settings inputType. Returns true if value is valid. + * * @param setting setting to check value against * @param value value to validate */ - public static validateValue(setting: SCSetting, value: SCSettingValue | SCSettingValues): boolean { + public static validateValue( + setting: SCSetting, + value: SCSettingValue | SCSettingValues, + ): boolean { let isValueValid = false; switch (setting.inputType) { case 'number': @@ -166,11 +173,9 @@ export class SettingsProvider { } break; case 'multiple choice': - if (!Array.isArray(value)) { - isValueValid = false; - } else { - isValueValid = SettingsProvider.checkMultipleChoiceValue(setting.values, value); - } + isValueValid = !Array.isArray(value) + ? false + : SettingsProvider.checkMultipleChoiceValue(setting.values, value); break; case 'password': case 'text': @@ -179,11 +184,9 @@ export class SettingsProvider { } break; case 'single choice': - if (Array.isArray(value)) { - isValueValid = false; - } else { - isValueValid = SettingsProvider.checkSingleChoiceValue(setting.values, value); - } + isValueValid = Array.isArray(value) + ? false + : SettingsProvider.checkSingleChoiceValue(setting.values, value); break; default: } @@ -196,14 +199,17 @@ export class SettingsProvider { * @param storage TODO * @param configProvider TODO */ - constructor(private readonly storage: StorageProvider, - private readonly configProvider: ConfigProvider) { + constructor( + private readonly storage: StorageProvider, + private readonly configProvider: ConfigProvider, + ) { this.categoriesOrder = []; this.settingsCache = {}; } /** * Add an Setting to the Cache if not exist and set undefined value to defaultValue + * * @param setting Setting with categories, defaultValue, name, input type and valid values */ private addSetting(setting: SCSetting): void { @@ -214,7 +220,8 @@ export class SettingsProvider { if (setting.value === undefined) { setting.value = setting.defaultValue; } - this.settingsCache[setting.categories[0]].settings[setting.name] = setting; + this.settingsCache[setting.categories[0]].settings[setting.name] = + setting; } } @@ -226,7 +233,9 @@ export class SettingsProvider { // iterate through keys of categories for (const categoryKey of Object.keys(this.settingsCache)) { // iterate through keys of settingValueContainer - for (const settingKey of Object.keys(this.settingsCache[categoryKey].settings)) { + for (const settingKey of Object.keys( + this.settingsCache[categoryKey].settings, + )) { if (typeof settingValuesContainer[categoryKey] === 'undefined') { settingValuesContainer[categoryKey] = {}; } @@ -240,6 +249,7 @@ export class SettingsProvider { /** * Add category if not exists + * * @param category the category to provide */ private provideCategory(category: string): void { @@ -256,6 +266,7 @@ export class SettingsProvider { /** * Returns true if category exists + * * @param category Category key name */ public categoryExists(category: string): boolean { @@ -280,32 +291,39 @@ export class SettingsProvider { /** * Returns copy of a setting if exist + * * @param category the category of requested setting * @param name the name of requested setting - * * @throws Exception if setting is not provided */ public async getSetting(category: string, name: string): Promise { await this.init(); if (this.settingExists(category, name)) { // return a copy of the settings - return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name])); + return JSON.parse( + JSON.stringify(this.settingsCache[category].settings[name]), + ); } throw new Error(`Setting "${name}" not provided`); } /** * Returns copy of a settings value if exist + * * @param category the category of requested setting * @param name the name of requested setting - * * @throws Exception if setting is not provided */ - public async getValue(category: string, name: string): Promise { + public async getValue( + category: string, + name: string, + ): Promise { await this.init(); if (this.settingExists(category, name)) { // return a copy of the settings value - return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name].value)); + return JSON.parse( + JSON.stringify(this.settingsCache[category].settings[name].value), + ); } throw new Error(`Setting "${name}" not provided`); } @@ -313,31 +331,39 @@ export class SettingsProvider { /** * Initializes settings from config and stored values if exist */ - public async init(): Promise { + public async init(): Promise { try { - const settings: SCSetting[] = (await this.configProvider.getValue('settings')) as SCSetting[]; - settings.forEach((setting) => this.addSetting(setting)); + const settings: SCSetting[] = (await this.configProvider.getValue( + 'settings', + )) as SCSetting[]; + for (const setting of settings) this.addSetting(setting); for (const category of Object.keys(this.settingsCache)) { if (!this.categoriesOrder.includes(category)) { this.categoriesOrder.push(category); } } - } catch (error) { + } catch { this.settingsCache = {}; } if (await this.storage.has(STORAGE_KEY_SETTING_VALUES)) { // get setting values from StorageProvider into settingsCache const valuesContainer: SettingValuesContainer = - await this.storage.get(STORAGE_KEY_SETTING_VALUES); + await this.storage.get( + STORAGE_KEY_SETTING_VALUES, + ); // iterate through keys of categories for (const categoryKey of Object.keys(this.settingsCache)) { // iterate through setting keys of category - for (const settingKey of Object.keys(this.settingsCache[categoryKey].settings)) { + for (const settingKey of Object.keys( + this.settingsCache[categoryKey].settings, + )) { // if saved setting value exists set it, otherwise set to default value - if (typeof valuesContainer[categoryKey] !== 'undefined' - && typeof valuesContainer[categoryKey][settingKey] !== 'undefined') { + if ( + typeof valuesContainer[categoryKey] !== 'undefined' && + typeof valuesContainer[categoryKey][settingKey] !== 'undefined' + ) { this.settingsCache[categoryKey].settings[settingKey].value = valuesContainer[categoryKey][settingKey]; } else { @@ -352,6 +378,7 @@ export class SettingsProvider { /** * Adds given setting and its category if not exist + * * @param setting the setting to add */ public provideSetting(setting: SCSetting): void { @@ -371,7 +398,9 @@ export class SettingsProvider { */ async resetDefault(): Promise { for (const catKey of Object.keys(this.settingsCache)) { - for (const settingKey of Object.keys(this.settingsCache[catKey].settings)) { + for (const settingKey of Object.keys( + this.settingsCache[catKey].settings, + )) { const settingInput = this.settingsCache[catKey].settings[settingKey]; settingInput.value = settingInput.defaultValue; } @@ -385,18 +414,29 @@ export class SettingsProvider { public async saveSettingValues(): Promise { if (await this.storage.has(STORAGE_KEY_SETTING_VALUES)) { const savedSettingsValues: SettingValuesContainer = - await this.storage.get(STORAGE_KEY_SETTING_VALUES); + await this.storage.get( + STORAGE_KEY_SETTING_VALUES, + ); const cacheSettingsValues = this.getSettingValuesFromCache(); - const mergedSettingValues = deepMerge(savedSettingsValues, cacheSettingsValues); - await this.storage - .put(STORAGE_KEY_SETTING_VALUES, mergedSettingValues); + const mergedSettingValues = deepMerge( + savedSettingsValues, + cacheSettingsValues, + ); + await this.storage.put( + STORAGE_KEY_SETTING_VALUES, + mergedSettingValues, + ); } else { - await this.storage.put(STORAGE_KEY_SETTING_VALUES, this.getSettingValuesFromCache()); + await this.storage.put( + STORAGE_KEY_SETTING_VALUES, + this.getSettingValuesFromCache(), + ); } } /** * Sets the order the given categories show up in the settings page + * * @param categoryNames the order of the categories */ public setCategoriesOrder(categoryNames: string[]) { @@ -409,11 +449,13 @@ export class SettingsProvider { * @param category Category key name * @param name Setting key name * @param value Value to be set - * * @throws Exception if setting is not provided or value not valid to the settings inputType */ - public async setSettingValue(category: string, name: string, - value: SCSettingValue | SCSettingValues): Promise { + public async setSettingValue( + category: string, + name: string, + value: SCSettingValue | SCSettingValues, + ): Promise { await this.init(); if (this.settingExists(category, name)) { const setting: SCSetting = this.settingsCache[category].settings[name]; @@ -423,7 +465,10 @@ export class SettingsProvider { this.settingsCache[category].settings[name].value = value; await this.saveSettingValues(); // publish setting changes - this.settingsActionSource.next({type: 'stapps.settings.changed', payload: {category, name, value}}); + this.settingsActionSource.next({ + type: 'stapps.settings.changed', + payload: {category, name, value}, + }); } else { throw new Error(`Value "${value}" of type ${typeof value} is not valid for ${setting.inputType}`); @@ -435,10 +480,14 @@ export class SettingsProvider { /** * Returns true if setting in category exists + * * @param category Category key name * @param setting Setting key name */ public settingExists(category: string, setting: string): boolean { - return this.categoryExists(category) && this.settingsCache[category].settings[setting] !== undefined; + return ( + this.categoryExists(category) && + this.settingsCache[category].settings[setting] !== undefined + ); } } diff --git a/src/app/modules/storage/storage.module.ts b/src/app/modules/storage/storage.module.ts index ccf6ce40..732b1fb3 100644 --- a/src/app/modules/storage/storage.module.ts +++ b/src/app/modules/storage/storage.module.ts @@ -20,11 +20,7 @@ import {StorageProvider} from './storage.provider'; * Angular storage provider module */ @NgModule({ - imports: [ - IonicStorageModule.forRoot(), - ], - providers: [ - StorageProvider, - ], + imports: [IonicStorageModule.forRoot()], + providers: [StorageProvider], }) export class StorageModule {} diff --git a/src/app/modules/storage/storage.provider.spec.ts b/src/app/modules/storage/storage.provider.spec.ts index 1c888c4d..98d1fa15 100644 --- a/src/app/modules/storage/storage.provider.spec.ts +++ b/src/app/modules/storage/storage.provider.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /* * Copyright (C) 2018, 2019 StApps * This program is free software: you can redistribute it and/or modify it @@ -61,17 +62,23 @@ describe('StorageProvider', () => { it('should properly put and get a value', async () => { await storageProvider.init(); await storageProvider.put('some-uid', {some: 'thing'}); - const result: Map = await storageProvider.get>('some-uid'); - expect(result).toEqual({some: 'thing'}); + // eslint-disable-next-line @typescript-eslint/ban-types + const result: Map = await storageProvider.get< + // eslint-disable-next-line @typescript-eslint/ban-types + Map + >('some-uid'); + await expect(result).toEqual({some: 'thing'}); }); it('should throw an error when value is null', async () => { + // eslint-disable-next-line unicorn/error-message let error: Error = new Error(); + // eslint-disable-next-line unicorn/no-null spyOn(storage, 'get').and.returnValue(Promise.resolve(null)); try { await storageProvider.get('something-else'); - } catch (err) { - error = err; + } catch (error_) { + error = error_; } expect(error).toEqual(new Error('Value not found.')); }); @@ -91,29 +98,34 @@ describe('StorageProvider', () => { expect((storageProvider.get as jasmine.Spy).calls.count()).toEqual(2); expect(storageProvider.get).toHaveBeenCalledWith('foo'); expect(storageProvider.get).toHaveBeenCalledWith('bar'); - expect(Array.from(entries.values())).toEqual(['Bar', {foo: 'BarFoo'}]); - expect(Array.from(entries.keys())).toEqual(['foo', 'bar']); + expect([...entries.values()]).toEqual(['Bar', {foo: 'BarFoo'}]); + expect([...entries.keys()]).toEqual(['foo', 'bar']); }); it('should get all values from the storage', async () => { spyOn(storageProvider, 'get').and.callThrough(); await storageProvider.putMultiple(sampleEntries); const entries = await storageProvider.getAll(); - expect(Array.from(entries.values()).map((item) => (item.foo) ? item.foo : item).sort()) - .toEqual(Array.from(sampleEntries.values()).map((item) => (item.foo) ? item.foo : item).sort()); - expect(Array.from(entries.keys()).sort()).toEqual(['bar', 'foo', 'foo.bar']); + expect( + [...entries.values()].map(item => (item.foo ? item.foo : item)).sort(), + ).toEqual( + [...sampleEntries.values()] + .map(item => (item.foo ? item.foo : item)) + .sort(), + ); + expect([...entries.keys()].sort()).toEqual(['bar', 'foo', 'foo.bar']); }); it('should delete one or more entries from the storage', async () => { spyOn(storage, 'remove').and.callThrough(); await storageProvider.putMultiple(sampleEntries); let entries = await storageProvider.getAll(); - expect(Array.from(entries.values()).length).toBe(3); + expect([...entries.values()].length).toBe(3); await storageProvider.delete('bar'); expect(storage.remove).toHaveBeenCalled(); entries = await storageProvider.getAll(); - expect(Array.from(entries.values())).toEqual(['Bar', 123]); + expect([...entries.values()]).toEqual(['Bar', 123]); await storageProvider.delete('foo', 'foo.bar'); expect(await storageProvider.length()).toBe(0); @@ -123,12 +135,12 @@ describe('StorageProvider', () => { spyOn(storage, 'clear').and.callThrough(); await storageProvider.putMultiple(sampleEntries); let entries = await storageProvider.getAll(); - expect(Array.from(entries.values()).length).toBe(3); + expect([...entries.values()].length).toBe(3); await storageProvider.deleteAll(); entries = await storageProvider.getAll(); expect(storage.clear).toHaveBeenCalled(); - expect(Array.from(entries.values()).length).toBe(0); + expect([...entries.values()].length).toBe(0); }); it('should provide number of entries', async () => { @@ -152,7 +164,9 @@ describe('StorageProvider', () => { }); it('should provide information if storage contains a specific entry (key)', async () => { - spyOn(storage, 'keys').and.returnValue(Promise.resolve(Array.from(sampleEntries.keys()))); + spyOn(storage, 'keys').and.returnValue( + Promise.resolve([...sampleEntries.keys()]), + ); expect(await storageProvider.has('foo')).toBeTruthy(); expect(await storageProvider.has('something-else')).toBeFalsy(); }); @@ -160,14 +174,14 @@ describe('StorageProvider', () => { it('should allow search by regex', async () => { await storageProvider.putMultiple(sampleEntries); const found: Map = await storageProvider.search(/bar/); - expect(Array.from(found.keys()).sort()).toEqual(['bar', 'foo.bar']); - expect(Array.from(found.values())).toEqual([{foo: 'BarFoo'}, 123]); + expect([...found.keys()].sort()).toEqual(['bar', 'foo.bar']); + expect([...found.values()]).toEqual([{foo: 'BarFoo'}, 123]); }); it('should allow search by string', async () => { await storageProvider.putMultiple(sampleEntries); const found: Map = await storageProvider.search('foo.ba'); - expect(Array.from(found.keys())).toEqual(['foo.bar']); - expect(Array.from(found.values())).toEqual([123]); + expect([...found.keys()]).toEqual(['foo.bar']); + expect([...found.values()]).toEqual([123]); }); }); diff --git a/src/app/modules/storage/storage.provider.ts b/src/app/modules/storage/storage.provider.ts index 37a2fb44..9c820eb7 100644 --- a/src/app/modules/storage/storage.provider.ts +++ b/src/app/modules/storage/storage.provider.ts @@ -23,8 +23,7 @@ export class StorageProvider { /** * @param storage TODO */ - constructor(private readonly storage: Storage) { - } + constructor(private readonly storage: Storage) {} /** * Deletes storage entries using keys used to save them @@ -32,7 +31,7 @@ export class StorageProvider { * @param keys Unique identifiers of the resources for deletion */ async delete(...keys: string[]): Promise { - keys.forEach(async (key) => { + keys.map(async key => { await this.storage.remove(key); }); } @@ -58,12 +57,13 @@ export class StorageProvider { return entry; } - // tslint:disable:no-any + /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Retrieves all the storage entries */ async getAll(): Promise> { const map: Map = new Map(); + // eslint-disable-next-line unicorn/no-array-for-each await this.storage.forEach((value, key) => { map.set(key, value); }); @@ -82,7 +82,7 @@ export class StorageProvider { const getToMap = async (key: string) => { map.set(key, await this.get(key)); }; - keys.forEach((key) => { + keys.map(key => { gets.push(getToMap(key)); }); await Promise.all(gets); @@ -137,9 +137,9 @@ export class StorageProvider { */ async putMultiple(entries: Map): Promise> { const puts: Array> = []; - entries.forEach(async (value, key) => { + for (const [key, value] of entries.entries()) { puts.push(this.put(key, value)); - }); + } await Promise.all(puts); return entries; @@ -164,6 +164,7 @@ export class StorageProvider { }; }; const checkIt = check(pattern); + // eslint-disable-next-line unicorn/no-array-for-each await this.storage.forEach((value, key) => { if (checkIt(pattern, key)) { map.set(key, value); diff --git a/src/app/translation/common-string-pipes.ts b/src/app/translation/common-string-pipes.ts index 6ba97fe8..e1177ee0 100644 --- a/src/app/translation/common-string-pipes.ts +++ b/src/app/translation/common-string-pipes.ts @@ -13,14 +13,11 @@ * this program. If not, see . */ - import {DecimalPipe} from '@angular/common'; import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import {Subscription} from 'rxjs'; -// tslint:disable: completed-docs - @Injectable() @Pipe({ name: 'join', @@ -29,21 +26,21 @@ import {Subscription} from 'rxjs'; export class ArrayJoinPipe implements PipeTransform { value = ''; - - transform(anArray: [], separator: string): unknown { + transform(anArray: unknown[], separator: string | unknown): unknown { if (typeof separator !== 'string' || separator.length <= 0) { return this.value; } - if (!Array.isArray(anArray)){ - throw new SyntaxError(`Wrong parameter in ArrayJoinPipe. Expected a valid Array, received: ${anArray}`); + if (!Array.isArray(anArray)) { + throw new SyntaxError( + `Wrong parameter in ArrayJoinPipe. Expected a valid Array, received: ${anArray}`, + ); } this.value = anArray.join(separator); return this.value; } - } @Injectable() @@ -52,25 +49,25 @@ export class ArrayJoinPipe implements PipeTransform { pure: false, // required to update the value when the promise is resolved }) export class StringSplitPipe implements PipeTransform { - value = Array(); + value = new Array(); - transform(aString: string, splitter: string): unknown { + transform(aString: string | T, splitter: string | T): T { if (typeof splitter !== 'string' || splitter.length <= 0) { - return this.value; + return this.value as never; } - if (typeof aString !== 'string'){ - throw new SyntaxError(`Wrong parameter in StringSplitPipe. Expected a valid String, received: ${aString}`); + if (typeof aString !== 'string') { + throw new SyntaxError( + `Wrong parameter in StringSplitPipe. Expected a valid String, received: ${aString}`, + ); } this.value = aString.split(splitter); - return this.value; + return this.value as never; } - } - @Injectable() @Pipe({ name: 'numberLocalized', @@ -78,8 +75,11 @@ export class StringSplitPipe implements PipeTransform { }) export class NumberLocalizedPipe implements PipeTransform, OnDestroy { decimalPipe: DecimalPipe; + locale: string; + onLangChange: Subscription; + value: unknown; constructor(private readonly translate: TranslateService) { @@ -109,21 +109,22 @@ export class NumberLocalizedPipe implements PipeTransform, OnDestroy { * Default is `3`. */ transform(value: unknown, digitsInfo?: string | undefined): unknown { - this.updateValue(value, digitsInfo); this._dispose(); - if (typeof this.onLangChange === 'undefined' || this.onLangChange.closed ) { - this.onLangChange = this.translate.onLangChange.subscribe((event: LangChangeEvent) => { + if (typeof this.onLangChange === 'undefined' || this.onLangChange.closed) { + this.onLangChange = this.translate.onLangChange.subscribe( + (event: LangChangeEvent) => { this.locale = event.lang; this.updateValue(value, digitsInfo); - }); - } + }, + ); + } return this.value; } updateValue(value: unknown, digitsInfo?: string | undefined): void { // this.value = this.locale; - this.value = this.decimalPipe.transform(value, digitsInfo,this.locale); + this.value = this.decimalPipe.transform(value, digitsInfo, this.locale); } } diff --git a/src/app/translation/thing-translate.module.ts b/src/app/translation/thing-translate.module.ts index 4a4addc0..e411c771 100644 --- a/src/app/translation/thing-translate.module.ts +++ b/src/app/translation/thing-translate.module.ts @@ -14,45 +14,55 @@ */ import {ModuleWithProviders, NgModule, Provider} from '@angular/core'; -import {ArrayJoinPipe, NumberLocalizedPipe, StringSplitPipe} from './common-string-pipes'; -import {ThingTranslateDefaultParser, ThingTranslateParser} from './thing-translate.parser'; -import {ThingPropertyNameTranslatePipe, ThingTranslatePipe} from './thing-translate.pipe'; +import { + ArrayJoinPipe, + NumberLocalizedPipe, + StringSplitPipe, +} from './common-string-pipes'; +import { + ThingTranslateDefaultParser, + ThingTranslateParser, +} from './thing-translate.parser'; +import { + ThingPropertyNameTranslatePipe, + ThingTranslatePipe, +} from './thing-translate.pipe'; import {ThingTranslateService} from './thing-translate.service'; - -// tslint:disable: completed-docs export interface ThingTranslateModuleConfig { parser?: Provider; } @NgModule({ declarations: [ - ThingTranslatePipe, - ThingPropertyNameTranslatePipe, ArrayJoinPipe, - StringSplitPipe, NumberLocalizedPipe, - // ThingTranslatorDirective + StringSplitPipe, + ThingPropertyNameTranslatePipe, + ThingTranslatePipe, ], exports: [ - ThingTranslatePipe, - ThingPropertyNameTranslatePipe, ArrayJoinPipe, - StringSplitPipe, NumberLocalizedPipe, - // ThingTranslatorDirective + StringSplitPipe, + ThingPropertyNameTranslatePipe, + ThingTranslatePipe, ], }) export class ThingTranslateModule { - /** * Use this method in your other (non root) modules to import the directive/pipe */ - static forChild(config: ThingTranslateModuleConfig = {}): ModuleWithProviders { + static forChild( + config: ThingTranslateModuleConfig = {}, + ): ModuleWithProviders { return { ngModule: ThingTranslateModule, providers: [ - config.parser ?? {provide: ThingTranslateParser, useClass: ThingTranslateDefaultParser}, + config.parser ?? { + provide: ThingTranslateParser, + useClass: ThingTranslateDefaultParser, + }, ThingTranslateService, ], }; @@ -61,11 +71,16 @@ export class ThingTranslateModule { /** * Use this method in your root module to provide the TranslatorService */ - static forRoot(config: ThingTranslateModuleConfig = {}): ModuleWithProviders { + static forRoot( + config: ThingTranslateModuleConfig = {}, + ): ModuleWithProviders { return { ngModule: ThingTranslateModule, providers: [ - config.parser ?? {provide: ThingTranslateParser, useClass: ThingTranslateDefaultParser}, + config.parser ?? { + provide: ThingTranslateParser, + useClass: ThingTranslateDefaultParser, + }, ThingTranslateService, ], }; diff --git a/src/app/translation/thing-translate.parser.ts b/src/app/translation/thing-translate.parser.ts index 84d224b0..6c4d4842 100644 --- a/src/app/translation/thing-translate.parser.ts +++ b/src/app/translation/thing-translate.parser.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-types */ /* * Copyright (C) 2020-2021 StApps * This program is free software: you can redistribute it and/or modify it @@ -15,7 +16,7 @@ import {Injectable} from '@angular/core'; -// tslint:disable: member-ordering prefer-function-over-method completed-docs +/* eslint-disable @typescript-eslint/member-ordering, class-methods-use-this */ export abstract class ThingTranslateParser { /** @@ -27,22 +28,23 @@ export abstract class ThingTranslateParser { @Injectable() export class ThingTranslateDefaultParser extends ThingTranslateParser { - getValueFromKeyPath(instance: object, keyPath: string): unknown { // keyPath = aproperty[0].anotherproperty["arrayproperty"][42].finalproperty - let path = keyPath.replace(/(?:\"|\')'"/gmi, '.'); + let path = keyPath.replace(/["']'"/gim, '.'); // path = aproperty[0].anotherproperty[.arrayproperty.][42].finalproperty - path = path.replace(/(?:\[|\])/gmi, '.'); + path = path.replace(/[\[\]]/gim, '.'); // path = aproperty.0..anotherproperty..arrayproperty...42..finalproperty - path = path.replace(/\.{2,}/gmi, '.'); + // TODO + // eslint-disable-next-line @typescript-eslint/no-unused-vars + path = path.replace(/\.{2,}/gim, '.'); // path = aproperty.0.anotherproperty.arrayproperty.42.finalproperty const keyPathChain = keyPath.split('.'); - // tslint:disable-next-line: no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any let property = instance as any; - for(const key of keyPathChain) { + for (const key of keyPathChain) { property = property[key] ?? undefined; } @@ -50,6 +52,9 @@ export class ThingTranslateDefaultParser extends ThingTranslateParser { } } +/** + * TODO + */ export function isDefined(value?: T | null): value is T { return typeof value !== 'undefined' && value !== null; } diff --git a/src/app/translation/thing-translate.pipe.ts b/src/app/translation/thing-translate.pipe.ts index d7004f34..33f00ce4 100644 --- a/src/app/translation/thing-translate.pipe.ts +++ b/src/app/translation/thing-translate.pipe.ts @@ -14,14 +14,13 @@ */ import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core'; -import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; +import {TranslateService} from '@ngx-translate/core'; import {isThing, SCThings, SCThingType} from '@openstapps/core'; import {Subscription} from 'rxjs'; import {ThingTranslateService} from './thing-translate.service'; // tslint:disable: member-ordering prefer-function-over-method completed-docs - @Injectable() @Pipe({ name: 'thingTranslate', @@ -29,28 +28,35 @@ import {ThingTranslateService} from './thing-translate.service'; }) export class ThingTranslatePipe implements PipeTransform, OnDestroy { value: unknown; + lastKey?: string; + lastThing: SCThings; + onLangChange: Subscription; - constructor(private readonly translate: TranslateService, - // private readonly _ref: ChangeDetectorRef, - private readonly thingTranslate: ThingTranslateService) { - } + constructor( + private readonly translate: TranslateService, + // private readonly _ref: ChangeDetectorRef, + private readonly thingTranslate: ThingTranslateService, + ) {} updateValue(key: string, thing: SCThings): void { this.value = this.thingTranslate.get(thing, key); } - transform(query: P, thing: T): - P extends keyof T ? T[P] : P | unknown { + transform( + query: P, + thing: T, + ): P extends keyof T ? T[P] : P | unknown { if (typeof query !== 'string' || query.length <= 0) { - // tslint:disable-next-line:no-any - return query as any; + return query as never; } if (!isThing(thing)) { - throw new SyntaxError(`Wrong parameter in ThingTranslatePipe. Expected a valid SCThing, received: ${thing}`); + throw new SyntaxError( + `Wrong parameter in ThingTranslatePipe. Expected a valid SCThing, received: ${thing}`, + ); } // store the params, in case they change @@ -63,7 +69,7 @@ export class ThingTranslatePipe implements PipeTransform, OnDestroy { this._dispose(); if (this.onLangChange?.closed ?? true) { - this.onLangChange = this.translate.onLangChange.subscribe((_event: LangChangeEvent) => { + this.onLangChange = this.translate.onLangChange.subscribe(() => { if (typeof this.lastKey === 'string') { this.lastKey = undefined; // we want to make sure it doesn't return the same value until it's been updated this.updateValue(query, thing); @@ -71,8 +77,7 @@ export class ThingTranslatePipe implements PipeTransform, OnDestroy { }); } - // tslint:disable-next-line:no-any - return this.value as any; + return this.value as never; } /** @@ -89,21 +94,26 @@ export class ThingTranslatePipe implements PipeTransform, OnDestroy { } } - @Injectable() @Pipe({ name: 'propertyNameTranslate', pure: false, // required to update the value when the promise is resolved }) -export class ThingPropertyNameTranslatePipe implements PipeTransform, OnDestroy { +export class ThingPropertyNameTranslatePipe + implements PipeTransform, OnDestroy +{ value: unknown; + lastKey?: string; + lastType: string; + onLangChange: Subscription; - constructor(private readonly translate: TranslateService, - private readonly thingTranslate: ThingTranslateService) { - } + constructor( + private readonly translate: TranslateService, + private readonly thingTranslate: ThingTranslateService, + ) {} updateValue(key: string, type: string): void { this.value = this.thingTranslate.getPropertyName(type as SCThingType, key); @@ -115,12 +125,15 @@ export class ThingPropertyNameTranslatePipe implements PipeTransform, OnDestroy } if (!isThing(thingOrType) && typeof thingOrType !== 'string') { - throw new SyntaxError(`Wrong parameter in ThingTranslatePipe. Expected a valid SCThing or String, received: ${thingOrType}`); + throw new SyntaxError( + `Wrong parameter in ThingTranslatePipe. Expected a valid SCThing or String, received: ${thingOrType}`, + ); } // store the params, in case they change this.lastKey = query; - this.lastType = typeof thingOrType === 'string' ? thingOrType : thingOrType.type; + this.lastType = + typeof thingOrType === 'string' ? thingOrType : thingOrType.type; this.updateValue(query, this.lastType); @@ -128,7 +141,7 @@ export class ThingPropertyNameTranslatePipe implements PipeTransform, OnDestroy this._dispose(); if (this.onLangChange?.closed ?? true) { - this.onLangChange = this.translate.onLangChange.subscribe((_event: LangChangeEvent) => { + this.onLangChange = this.translate.onLangChange.subscribe(() => { if (typeof this.lastKey === 'string') { this.lastKey = undefined; // we want to make sure it doesn't return the same value until it's been updated this.updateValue(query, this.lastType); diff --git a/src/app/translation/thing-translate.service.ts b/src/app/translation/thing-translate.service.ts index b87da8e0..d3ee9e6d 100644 --- a/src/app/translation/thing-translate.service.ts +++ b/src/app/translation/thing-translate.service.ts @@ -15,58 +15,81 @@ import {Injectable, OnDestroy} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; -import {SCLanguage, SCLanguageCode, SCThings, SCThingTranslator, SCThingType, SCTranslations} from '@openstapps/core'; +import { + SCLanguage, + SCLanguageCode, + SCThings, + SCThingTranslator, + SCThingType, + SCTranslations, +} from '@openstapps/core'; import moment from 'moment'; import {Subscription} from 'rxjs'; import {isDefined, ThingTranslateParser} from './thing-translate.parser'; // export const DEFAULT_LANGUAGE = new InjectionToken('DEFAULT_LANGUAGE'); -// tslint:disable: member-ordering prefer-function-over-method newline-per-chained-call completed-docs +/* eslint-disable @typescript-eslint/member-ordering, class-methods-use-this, newline-per-chained-call, */ @Injectable({ providedIn: 'root', }) export class ThingTranslateService implements OnDestroy { - onLangChange: Subscription; + translator: SCThingTranslator; /** * * @param translateService Instance of Angular TranslateService * @param parser An instance of the parser currently used - * @param language TODO */ - constructor(private readonly translateService: TranslateService, - public parser: ThingTranslateParser){ - this.translator = new SCThingTranslator((translateService.currentLang ?? translateService.defaultLang) as SCLanguageCode); + constructor( + private readonly translateService: TranslateService, + public parser: ThingTranslateParser, + ) { + this.translator = new SCThingTranslator( + (translateService.currentLang ?? + translateService.defaultLang) as SCLanguageCode, + ); /** set the default language from configuration */ - this.onLangChange = this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { - this.translator.language = event.lang as keyof SCTranslations; - moment.locale(event.lang); - }); - + this.onLangChange = this.translateService.onLangChange.subscribe( + (event: LangChangeEvent) => { + this.translator.language = + event.lang as keyof SCTranslations; + moment.locale(event.lang); + }, + ); } /** * Returns the parsed result of the translations */ - // tslint:disable-next-line: no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/ban-types getParsedResult(target: object, key: string): any { return this.parser.getValueFromKeyPath(target, key); } /** * Gets the translated value of a key (or an array of keys) + * + * @param thing SCThing to get + * @param keyPath Path to the key * @returns the translated key, or an object of translated keys */ - public get(thing: SCThings, keyPath: string | string[]): string | number | boolean | object { + public get( + thing: SCThings, + keyPath: string | string[], + // eslint-disable-next-line @typescript-eslint/ban-types + ): string | number | boolean | object { if (!isDefined(keyPath) || keyPath.length === 0) { throw new Error(`Parameter "keyPath" required`); } - if (keyPath instanceof Array) { - return this.getParsedResult(this.translator.translate(thing), keyPath.join('.')); + if (Array.isArray(keyPath)) { + return this.getParsedResult( + this.translator.translate(thing), + keyPath.join('.'), + ); } return this.getParsedResult(this.translator.translate(thing), keyPath); @@ -74,24 +97,30 @@ export class ThingTranslateService implements OnDestroy { /** * Gets the translated value of a key (or an array of keys) + * + * @param type Type of the property + * @param keyPath Path to the key * @returns the translated key, or an object of translated keys */ - public getPropertyName(type: SCThingType, keyPath: string | string[]): string { - const translatedPropertyNames = this.translator.translatedPropertyNames(type); + public getPropertyName( + type: SCThingType, + keyPath: string | string[], + ): string { + const translatedPropertyNames = + this.translator.translatedPropertyNames(type); if (!isDefined(translatedPropertyNames)) { throw new Error(`Parameter "type" is an invalid SCThingType`); } if (!isDefined(keyPath) || keyPath.length === 0) { throw new Error(`Parameter "keyPath" required`); } - if (keyPath instanceof Array) { - return this.getParsedResult(translatedPropertyNames!, keyPath.join('.')); + if (Array.isArray(keyPath)) { + return this.getParsedResult(translatedPropertyNames, keyPath.join('.')); } - return this.getParsedResult(translatedPropertyNames!, keyPath); + return this.getParsedResult(translatedPropertyNames, keyPath); } - // tslint:disable-next-line: completed-docs ngOnDestroy() { if (!this.onLangChange.closed) { this.onLangChange.unsubscribe(); diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 9bf79286..1749f661 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -12,6 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ +// eslint-disable-next-line unicorn/prevent-abbreviations export const environment = { backend_url: 'https://mobile.server.uni-frankfurt.de', backend_version: '2.0.0', diff --git a/src/index.html b/src/index.html index 557e49a7..1b8f83bf 100644 --- a/src/index.html +++ b/src/index.html @@ -1,23 +1,25 @@ - + - - - StApps + + + StApps - + - - - + + + - + - - - - - - - - + + + + + + + diff --git a/src/main.ts b/src/main.ts index 40fa73f7..39f69a94 100644 --- a/src/main.ts +++ b/src/main.ts @@ -24,4 +24,4 @@ if (environment.production) { platformBrowserDynamic() .bootstrapModule(AppModule) // tslint:disable-next-line:no-console - .catch(async (err) => console.error(err)); + .catch(async error => console.error(error)); diff --git a/src/polyfills.ts b/src/polyfills.ts index c5b6dbf1..492093f5 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -71,7 +71,7 @@ import 'core-js/es7/reflect'; /*************************************************************************************************** * Zone JS is required by Angular itself. */ -import 'zone.js/dist/zone'; // Included with Angular CLI. +import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/src/test.ts b/src/test.ts index 18cc8c37..17e673fd 100644 --- a/src/test.ts +++ b/src/test.ts @@ -21,17 +21,15 @@ import { } from '@angular/platform-browser-dynamic/testing'; import 'zone.js/dist/zone-testing'; -// tslint:disable-next-line:no-any +// eslint-disable-next-line @typescript-eslint/no-explicit-any declare const require: any; // First, initialize the Angular testing environment. -getTestBed() - .initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - ); +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting(), +); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. -context.keys() - .map(context); +context.keys().map(context); diff --git a/tslint.json b/tslint.json deleted file mode 100644 index b7e16f34..00000000 --- a/tslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./node_modules/@openstapps/configuration/tslint.json", - "linterOptions": { - "exclude": [ - "src/**/*.spec.ts" - ] - } -}