diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..e9ee3cb4d --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true \ No newline at end of file diff --git a/README.md b/README.md index 567a52c6a..63a64a856 100755 --- a/README.md +++ b/README.md @@ -269,7 +269,7 @@ $ANDROID_HOME/build-tools/27.0.2/zipalign -v 4 /platforms/and ## Questionnaire Input Types -The questionnaire input types supported are `audio`, `checkbox`, `descriptive`, `info-screen`, `matrix-radio`, `radio`, `range-info`, `range-input`, `slider`, `text`, `date`, `time`, and `timed-test`. +The questionnaire input types supported are `audio`, `checkbox`, `descriptive`, `info-screen`, `matrix-radio`, `radio`, `range-info`, `range-input`, `slider`, `text`, `date`, `time`, `healthkit`, and `timed-test`. ### Descriptive Input Type @@ -297,17 +297,30 @@ Here is the output: -## Common Errors +## Healthkit Input Type -Here are some common errors you might find during installation. +Please see `/src/app/shared/models/health.ts` for a list of supported data types. In order to add support for new data types, follow the steps below: -### Error: cordova-custom-config +### Add the New Data Type to `HealthkitDataType` -When you are running `ionic cordova run ios`, you might encounter the problem, we solved this problem by refering this [issue](https://github.com/dpa99c/cordova-custom-config/issues/144) with `cordova-custom-config`. +Open the `health.ts` file and add the new data type to the `HealthkitDataType` enum. Use a descriptive key and a string value that matches the Healthkit data type. -We enter the following command at the root directory. - -``` -cd plugins/cordova-custom-config -npm install +```typescript +export enum HealthkitDataType { + ... + VO2_MAX = 'vo2Max', +} ``` + +### Add a New Permission to HealthkitPermission +Add the corresponding permission to the `HealthkitPermission` enum. The permission should match the new data type. + +### Map the Data Type to Its Permission +Update the `HealthkitPermissionMap` object to link the new `HealthkitDataType` to its `HealthkitPermission`. + +### Add the Kafka Topic to HealthkitTopic +Add the corresponding topic to the `HealthkitTopic` enum. The topic should be a descriptive string representing the data type's usage in your system. + +### Add to the Appropriate Data Type Sets (if applicable) +Depending on the data type (e.g., numeric or string), add the new data type to the relevant set: `HealthkitFloatDataTypes` or `HealthkitStringDataTypes`. + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e1f31b24c..0f254ed66 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" + android:usesCleartextTraffic="true" android:hardwareAccelerated="true"> UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + diff --git a/package-lock.json b/package-lock.json index 5ec8e0cf6..a70effe47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "radar-questionnaire", - "version": "3.3.2", + "version": "3.3.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "radar-questionnaire", - "version": "3.3.2", + "version": "3.3.4", "hasInstallScript": true, "dependencies": { "morph-expressions": "^1.1.1", @@ -25,6 +25,7 @@ "capacitor-grab-intent-extras": "^0.0.4", "url-join": "^4.0.1", "tslib": "^2.5.0", + "js-md5": "^0.8.3", "pako": "^2.1.0", "@capacitor/app-launcher": "^5.0.7", "path": "^0.12.7", @@ -35,6 +36,7 @@ "ajv-formats": "^2.1.1", "@capacitor/local-notifications": "^5.0.2", "execa": "^4.0.3", + "emojis-list": "^3.0.0", "@capacitor-mlkit/barcode-scanning": "^5.4.0", "buffer": "^6.0.3", "@perfood/capacitor-healthkit": "^1.3.0", @@ -51,7 +53,7 @@ "browserify": "^16.3.0", "@ionic/storage": "2.2.0", "unorm": "^1.6.0", - "avro-js": "^1.11.1", + "avro-js": "^1.11.3", "dompurify": "^2.2.8", "@capacitor-firebase/analytics": "^5.0.0", "capacitor-voice-recorder": "github:mpgxvii/capacitor-voice-recorder", @@ -60,8 +62,10 @@ "@auth0/angular-jwt": "5.0.0", "@logisticinfotech/ionic4-datepicker": "^1.4.4", "@capacitor-firebase/remote-config": "^5.0.0", - "@capacitor/ios": "^5.0.3", + "@capacitor/ios": "5.7.0", + "follow-redirects": "^1.15.6", "compare-versions": "^5.0.3", + "eventemitter3": "^5.0.1", "@capacitor/core": "5.7.0", "graphlib": "^2.1.8", "autoprefixer": "^10.0.0", @@ -79,6 +83,7 @@ "@capacitor/keyboard": "^5.0.8", "@angular/platform-browser": "~14.3.0", "@capacitor/dialog": "^5.0.2", + "requires-port": "^1.0.0", "@angular/compiler": "~14.3.0", "@capacitor/android": "^5.0.3", "firebase": "^10.8.0", @@ -116,7 +121,7 @@ "@types/jasmine": "~3.6.0", "karma-browserstack-launcher": "^1.6.0", "rxjs-tslint": "^0.1.8", - "@types/node": "^20.12.2", + "@types/node": "20.12.2", "stylelint": "^13.6.1", "tslint-config-prettier": "^1.15.0", "ts-node": "^10.9.1", @@ -151,8 +156,9 @@ }, "node_modules/@colors/colors": { "version": "1.5.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, "engines": { "node": ">=0.1.90" } @@ -189,8 +195,9 @@ }, "node_modules/extglob/node_modules/define-property": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, - "license": "MIT", "dependencies": { "is-descriptor": "^1.0.0" }, @@ -251,8 +258,9 @@ }, "node_modules/custom-event": { "version": "1.0.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true }, "node_modules/@firebase/app-compat": { "version": "0.2.27", @@ -267,8 +275,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/path-key": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -289,8 +298,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/parse5-sax-parser": { "version": "6.0.1", @@ -337,8 +347,9 @@ }, "node_modules/import-sort-cli/node_modules/fast-glob": { "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", "dev": true, - "license": "MIT", "dependencies": { "@mrmlnc/readdir-enhanced": "^2.2.1", "@nodelib/fs.stat": "^1.1.2", @@ -366,6 +377,17 @@ "fast-safe-stringify": "^2.0.7" } }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "dev": true, @@ -384,8 +406,9 @@ }, "node_modules/void-elements": { "version": "2.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -417,8 +440,9 @@ }, "node_modules/import-sort-cli/node_modules/wrap-ansi/node_modules/string-width": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", "dev": true, - "license": "MIT", "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -430,8 +454,9 @@ }, "node_modules/karma/node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -491,8 +516,9 @@ }, "node_modules/expand-brackets/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -519,7 +545,8 @@ }, "node_modules/ora/node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/stylelint-order/node_modules/slice-ansi": { "version": "1.0.0", @@ -559,8 +586,19 @@ } }, "node_modules/fast-uri": { - "version": "3.0.3", - "license": "BSD-3-Clause" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/terser-webpack-plugin/node_modules/terser": { "version": "5.28.1", @@ -599,8 +637,9 @@ }, "node_modules/protractor/node_modules/chalk": { "version": "1.1.3", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -614,16 +653,18 @@ }, "node_modules/stylefmt/node_modules/postcss-less/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/stylefmt/node_modules/stylelint/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -633,16 +674,18 @@ }, "node_modules/stylelint-order/node_modules/is-fullwidth-code-point": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/import-sort-cli/node_modules/strip-ansi": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -652,8 +695,9 @@ }, "node_modules/del/node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -794,8 +838,9 @@ }, "node_modules/import-sort-cli/node_modules/@nodelib/fs.stat": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } @@ -904,8 +949,9 @@ }, "node_modules/har-schema": { "version": "2.0.0", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, "engines": { "node": ">=4" } @@ -940,8 +986,9 @@ }, "node_modules/watchify/node_modules/is-number/node_modules/kind-of": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dev": true, - "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -1019,8 +1066,9 @@ }, "node_modules/base64id": { "version": "2.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, "engines": { "node": "^4.5.0 || >= 5.9" } @@ -1037,8 +1085,9 @@ }, "node_modules/socket.io-adapter/node_modules/ws": { "version": "8.11.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, "engines": { "node": ">=10.0.0" }, @@ -1110,8 +1159,9 @@ }, "node_modules/caseless": { "version": "0.12.0", - "devOptional": true, - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true }, "node_modules/stylelint-order/node_modules/path-exists": { "version": "2.1.0", @@ -1134,7 +1184,9 @@ }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -1412,8 +1464,10 @@ }, "node_modules/protractor": { "version": "7.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "deprecated": "We have news to share - Protractor is deprecated and will reach end-of-life by Summer 2023. To learn more and find out about other options please refer to this post on the Angular blog. Thank you for using and contributing to Protractor. https://goo.gle/state-of-e2e-in-angular", + "dev": true, "dependencies": { "@types/q": "^0.0.32", "@types/selenium-webdriver": "^3.0.0", @@ -1441,8 +1495,9 @@ }, "node_modules/object.pick": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, - "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -1492,7 +1547,9 @@ }, "node_modules/@npmcli/move-file/node_modules/glob": { "version": "7.2.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1512,23 +1569,11 @@ "version": "0.2.0", "license": "Apache-2.0" }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "2.0.4", - "license": "MIT", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/exit": { "version": "0.1.2", - "devOptional": true, + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -1543,8 +1588,9 @@ }, "node_modules/webdriver-manager": { "version": "12.1.9", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", + "dev": true, "dependencies": { "adm-zip": "^0.5.2", "chalk": "^1.1.1", @@ -1601,8 +1647,9 @@ } }, "node_modules/@ionic/angular/node_modules/@stencil/core": { - "version": "4.23.0", - "license": "MIT", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.25.1.tgz", + "integrity": "sha512-SJhAAN6nHj7l2n2F7H6NoOUFhXC5tYXSvOpAaNFi5As6c2jOvaDOvAH+om4OKmw8U2kHI9yihEqpZrtY1J20dQ==", "bin": { "stencil": "bin/stencil" }, @@ -1771,6 +1818,18 @@ "postcss": "^8.4" } }, + "node_modules/crypto-browserify/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "license": "MIT" @@ -1877,8 +1936,9 @@ }, "node_modules/expand-brackets/node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1917,8 +1977,9 @@ }, "node_modules/del/node_modules/pify": { "version": "2.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -1948,24 +2009,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "license": "MIT", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/extglob": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, - "license": "MIT", "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -1982,8 +2030,9 @@ }, "node_modules/cors": { "version": "2.8.5", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, "dependencies": { "object-assign": "^4", "vary": "^1" @@ -2016,16 +2065,18 @@ }, "node_modules/yargs-parser": { "version": "20.2.9", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, "engines": { "node": ">=10" } }, "node_modules/import-sort-style-eslint/node_modules/onetime": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, - "license": "MIT", "dependencies": { "mimic-fn": "^1.0.0" }, @@ -2043,8 +2094,9 @@ }, "node_modules/karma/node_modules/glob": { "version": "7.2.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2276,8 +2328,9 @@ }, "node_modules/decamelize": { "version": "1.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2406,8 +2459,9 @@ }, "node_modules/karma/node_modules/yargs": { "version": "16.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -2423,8 +2477,9 @@ }, "node_modules/protractor/node_modules/require-main-filename": { "version": "2.0.0", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "node_modules/read-pkg-up/node_modules/p-try": { "version": "1.0.0", @@ -2471,8 +2526,9 @@ }, "node_modules/protractor/node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2510,8 +2566,9 @@ }, "node_modules/meow/node_modules/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, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -2543,16 +2600,6 @@ "node": ">=8.10.0" } }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001589", "funding": [ @@ -2747,8 +2794,9 @@ }, "node_modules/del/node_modules/rimraf": { "version": "2.7.1", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -2865,8 +2913,9 @@ }, "node_modules/jszip/node_modules/lie": { "version": "3.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, "dependencies": { "immediate": "~3.0.5" } @@ -2897,8 +2946,9 @@ }, "node_modules/webdriver-manager/node_modules/ansi-styles": { "version": "2.2.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -3011,8 +3061,9 @@ }, "node_modules/connect/node_modules/finalhandler": { "version": "1.1.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -3083,13 +3134,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/big.js": { - "version": "5.2.2", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "dev": true, @@ -3198,8 +3242,9 @@ }, "node_modules/streamroller/node_modules/universalify": { "version": "0.1.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -3244,8 +3289,9 @@ }, "node_modules/selenium-webdriver/node_modules/rimraf": { "version": "2.7.1", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3255,8 +3301,9 @@ }, "node_modules/performance-now": { "version": "2.1.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true }, "node_modules/@csstools/postcss-ic-unit": { "version": "1.0.1", @@ -3282,8 +3329,9 @@ }, "node_modules/watchify/node_modules/readdirp": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", @@ -3320,27 +3368,19 @@ }, "node_modules/import-sort-cli/node_modules/yargs-parser": { "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/expand-brackets": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -3376,7 +3416,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/commander": { "version": "2.20.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", @@ -3387,8 +3428,9 @@ }, "node_modules/webdriver-manager/node_modules/ini": { "version": "1.3.8", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/@angular-devkit/build-angular/node_modules/events": { "version": "3.3.0", @@ -3477,8 +3519,9 @@ }, "node_modules/setimmediate": { "version": "1.0.5", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true }, "node_modules/quick-lru": { "version": "4.0.1", @@ -3540,8 +3583,9 @@ }, "node_modules/es6-promise": { "version": "4.2.8", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true }, "node_modules/postcss-initial": { "version": "4.0.1", @@ -3552,8 +3596,9 @@ }, "node_modules/arrify": { "version": "1.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -3603,8 +3648,9 @@ }, "node_modules/protractor/node_modules/strip-ansi": { "version": "3.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -3804,8 +3850,10 @@ }, "node_modules/request": { "version": "2.88.2", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, "dependencies": { "isstream": "~0.1.2", "oauth-sign": "~0.9.0", @@ -3848,8 +3896,9 @@ }, "node_modules/webdriver-manager/node_modules/xmlbuilder": { "version": "11.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -3930,8 +3979,9 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/chalk/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -4099,8 +4149,9 @@ }, "node_modules/import-sort-cli/node_modules/locate-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4130,7 +4181,8 @@ }, "node_modules/serve-index/node_modules/depd": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "engines": { "node": ">= 0.6" } @@ -4326,7 +4378,8 @@ }, "node_modules/@babel/traverse/node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -4412,8 +4465,9 @@ }, "node_modules/import-sort-cli/node_modules/y18n": { "version": "4.0.3", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "node_modules/schema-utils/node_modules/ajv": { "version": "6.12.6", @@ -4521,8 +4575,9 @@ }, "node_modules/import-sort-cli/node_modules/micromatch": { "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "license": "MIT", "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -4593,15 +4648,18 @@ }, "node_modules/tough-cookie/node_modules/punycode": { "version": "2.3.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } }, "node_modules/saucelabs": { "version": "1.5.0", - "devOptional": true, + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, "dependencies": { "https-proxy-agent": "^2.2.1" }, @@ -4647,8 +4705,9 @@ }, "node_modules/streamroller/node_modules/fs-extra": { "version": "8.1.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -4717,8 +4776,9 @@ }, "node_modules/stylelint/node_modules/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, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -4806,8 +4866,9 @@ }, "node_modules/stylefmt/node_modules/postcss-less/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -4859,8 +4920,9 @@ }, "node_modules/getpass": { "version": "0.1.7", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, "dependencies": { "assert-plus": "^1.0.0" } @@ -4891,8 +4953,9 @@ }, "node_modules/import-sort-cli/node_modules/to-regex-range": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -4978,8 +5041,9 @@ }, "node_modules/karma/node_modules/tmp": { "version": "0.2.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, "dependencies": { "rimraf": "^3.0.0" }, @@ -5078,8 +5142,9 @@ }, "node_modules/stylefmt/node_modules/postcss-reporter/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -5089,8 +5154,9 @@ }, "node_modules/karma": { "version": "6.4.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", + "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "dev": true, "dependencies": { "isbinaryfile": "^4.0.8", "yargs": "^16.1.1", @@ -5169,8 +5235,9 @@ }, "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "5.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -5328,8 +5395,10 @@ }, "node_modules/request/node_modules/uuid": { "version": "3.4.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, "bin": { "uuid": "bin/uuid" } @@ -5381,21 +5450,24 @@ }, "node_modules/import-sort-cli/node_modules/get-caller-file": { "version": "1.0.3", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true }, "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { "version": "5.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/import-sort-cli/node_modules/is-fullwidth-code-point": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -5413,8 +5485,9 @@ }, "node_modules/watchify/node_modules/binary-extensions": { "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5462,8 +5535,9 @@ }, "node_modules/socket.io-adapter": { "version": "2.5.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dev": true, "dependencies": { "debug": "~4.3.4", "ws": "~8.11.0" @@ -5635,8 +5709,9 @@ }, "node_modules/protractor/node_modules/color-name": { "version": "1.1.4", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/@firebase/app-check": { "version": "0.8.2", @@ -5724,7 +5799,9 @@ }, "node_modules/webpack/node_modules/events": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "engines": { "node": ">=0.8.x" } @@ -5792,7 +5869,9 @@ }, "node_modules/webpack/node_modules/ajv-keywords": { "version": "3.5.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -5847,8 +5926,9 @@ }, "node_modules/saucelabs/node_modules/agent-base": { "version": "4.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, "dependencies": { "es6-promisify": "^5.0.0" }, @@ -5921,8 +6001,9 @@ }, "node_modules/karma/node_modules/mkdirp": { "version": "0.5.6", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -6292,7 +6373,8 @@ }, "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "0.4.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/snapdragon/node_modules/debug": { "version": "2.6.9", @@ -6304,8 +6386,9 @@ }, "node_modules/import-sort-cli/node_modules/find-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -6326,8 +6409,9 @@ }, "node_modules/sshpk/node_modules/jsbn": { "version": "0.1.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true }, "node_modules/electron-to-chromium": { "version": "1.4.680", @@ -6345,7 +6429,8 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/stylelint-order/node_modules/trim-newlines": { "version": "1.0.0", @@ -6403,8 +6488,9 @@ }, "node_modules/import-sort-cli/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", "dev": true, - "license": "MIT", "dependencies": { "number-is-nan": "^1.0.0" }, @@ -6414,8 +6500,9 @@ }, "node_modules/jsprim": { "version": "1.4.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -6505,8 +6592,9 @@ }, "node_modules/protractor/node_modules/supports-color": { "version": "2.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -6623,8 +6711,9 @@ }, "node_modules/stylefmt/node_modules/postcss-less/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -6735,8 +6824,9 @@ }, "node_modules/socket.io": { "version": "4.7.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -6893,8 +6983,9 @@ }, "node_modules/del/node_modules/globby": { "version": "5.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==", + "dev": true, "dependencies": { "array-union": "^1.0.1", "arrify": "^1.0.0", @@ -6933,8 +7024,9 @@ }, "node_modules/@types/cors": { "version": "2.8.17", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -7049,7 +7141,8 @@ }, "node_modules/critters/node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/promise-inflight": { "version": "1.0.1", @@ -7221,7 +7314,8 @@ }, "node_modules/postcss-loader/node_modules/parse-json": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -7554,8 +7648,9 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -7581,8 +7676,9 @@ }, "node_modules/isbinaryfile": { "version": "4.0.10", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, "engines": { "node": ">= 8.0.0" }, @@ -7626,8 +7722,9 @@ }, "node_modules/aws4": { "version": "1.12.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true }, "node_modules/ldjson-stream/node_modules/split2": { "version": "0.2.1", @@ -7670,8 +7767,9 @@ }, "node_modules/is-path-in-cwd": { "version": "1.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, "dependencies": { "is-path-inside": "^1.0.0" }, @@ -7702,8 +7800,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -7791,8 +7890,9 @@ }, "node_modules/set-blocking": { "version": "2.0.0", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/lcid": { "version": "2.0.0", @@ -7822,8 +7922,9 @@ }, "node_modules/fragment-cache": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", "dev": true, - "license": "MIT", "dependencies": { "map-cache": "^0.2.2" }, @@ -7933,8 +8034,9 @@ }, "node_modules/path-is-inside": { "version": "1.0.2", - "devOptional": true, - "license": "(WTFPL OR MIT)" + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true }, "node_modules/compressible": { "version": "2.0.18", @@ -7948,13 +8050,15 @@ }, "node_modules/psl": { "version": "1.9.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "node_modules/import-sort-style-eslint/node_modules/is-fullwidth-code-point": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -7968,8 +8072,9 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/supports-color": { "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^1.0.0" }, @@ -7979,8 +8084,9 @@ }, "node_modules/selenium-webdriver/node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8002,6 +8108,18 @@ "@types/jasmine": "*" } }, + "node_modules/parse-asn1/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/once": { "version": "1.4.0", "license": "ISC", @@ -8206,8 +8324,9 @@ }, "node_modules/os-locale/node_modules/which": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -8253,8 +8372,9 @@ }, "node_modules/protractor/node_modules/cliui": { "version": "6.0.0", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -8270,7 +8390,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/ajv": { "version": "6.12.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8284,16 +8405,18 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "devOptional": true, - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/import-sort-cli/node_modules/cliui": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -8312,7 +8435,10 @@ }, "node_modules/sourcemap-codec": { "version": "1.4.8", - "license": "MIT" + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true }, "node_modules/expand-range/node_modules/is-number": { "version": "2.1.0", @@ -8435,8 +8561,9 @@ }, "node_modules/os-locale/node_modules/get-stream": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, - "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -8446,8 +8573,9 @@ }, "node_modules/browserstack/node_modules/https-proxy-agent": { "version": "2.2.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, "dependencies": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -8605,16 +8733,18 @@ }, "node_modules/selenium-webdriver/node_modules/xmlbuilder": { "version": "11.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, "engines": { "node": ">=4.0" } }, "node_modules/protractor/node_modules/q": { "version": "1.4.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg==", + "dev": true, "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" @@ -8790,8 +8920,10 @@ }, "node_modules/import-sort-cli/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8852,8 +8984,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/mimic-fn": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -8898,8 +9031,9 @@ }, "node_modules/import-sort-cli/node_modules/dir-glob": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "dev": true, - "license": "MIT", "dependencies": { "path-type": "^3.0.0" }, @@ -8961,8 +9095,9 @@ }, "node_modules/os-locale/node_modules/cross-spawn": { "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, - "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -8976,7 +9111,8 @@ }, "node_modules/ora/node_modules/color-convert": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { "color-name": "~1.1.4" }, @@ -9016,8 +9152,9 @@ }, "node_modules/tweetnacl": { "version": "0.14.5", - "devOptional": true, - "license": "Unlicense" + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true }, "node_modules/find-cache-dir": { "version": "3.3.2", @@ -9052,8 +9189,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/chalk/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -9187,16 +9325,18 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, "dependencies": { "pinkie": "^2.0.0" }, @@ -9341,8 +9481,9 @@ }, "node_modules/extglob/node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, - "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -9463,8 +9604,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -9474,8 +9616,9 @@ }, "node_modules/stylelint/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -9541,8 +9684,9 @@ }, "node_modules/del/node_modules/array-union": { "version": "1.0.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, "dependencies": { "array-uniq": "^1.0.1" }, @@ -9611,12 +9755,14 @@ }, "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { "version": "0.4.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/karma/node_modules/rimraf": { "version": "3.0.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -9629,8 +9775,9 @@ }, "node_modules/protractor/node_modules/y18n": { "version": "4.0.3", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "node_modules/stylelint-order/node_modules/browserslist": { "version": "1.7.7", @@ -9843,8 +9990,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -9964,7 +10112,9 @@ }, "node_modules/typescript": { "version": "4.6.4", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", + "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9975,8 +10125,9 @@ }, "node_modules/jszip/node_modules/pako": { "version": "1.0.11", - "devOptional": true, - "license": "(MIT AND Zlib)" + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true }, "node_modules/schema-utils": { "version": "2.7.1", @@ -10015,7 +10166,9 @@ }, "node_modules/yargs": { "version": "17.5.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -10106,13 +10259,15 @@ }, "node_modules/extend": { "version": "3.0.2", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "node_modules/watchify/node_modules/fill-range": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "dev": true, - "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -10181,7 +10336,9 @@ }, "node_modules/webpack/node_modules/ajv": { "version": "6.12.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -10195,8 +10352,9 @@ }, "node_modules/@types/cookie": { "version": "0.4.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", @@ -10273,8 +10431,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/table/node_modules/strip-ansi": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^4.1.0" }, @@ -10284,8 +10443,9 @@ }, "node_modules/import-sort-cli/node_modules/wrap-ansi": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", "dev": true, - "license": "MIT", "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -10296,8 +10456,9 @@ }, "node_modules/webdriver-manager/node_modules/strip-ansi": { "version": "3.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -10389,8 +10550,9 @@ }, "node_modules/protractor/node_modules/ansi-styles": { "version": "2.2.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10475,8 +10637,9 @@ }, "node_modules/connect": { "version": "3.7.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", @@ -10515,7 +10678,8 @@ }, "node_modules/mini-css-extract-plugin/node_modules/ajv": { "version": "8.17.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -10544,8 +10708,9 @@ }, "node_modules/di": { "version": "0.0.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true }, "node_modules/@firebase/app": { "version": "0.9.27", @@ -10675,8 +10840,9 @@ }, "node_modules/@types/q": { "version": "0.0.32", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==", + "dev": true }, "node_modules/ansi-colors": { "version": "4.1.3", @@ -10829,8 +10995,9 @@ }, "node_modules/json-schema": { "version": "0.4.0", - "devOptional": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", @@ -10959,8 +11126,9 @@ }, "node_modules/expand-brackets/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, - "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -10999,6 +11167,18 @@ "node": ">=0.10.0" } }, + "node_modules/browserify-sign/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/stylelint-order/node_modules/ms": { "version": "2.0.0", "dev": true, @@ -11081,23 +11261,28 @@ } }, "node_modules/crypto-browserify": { - "version": "3.12.0", - "license": "MIT", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" }, "engines": { - "node": "*" + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/ajv-formats": { @@ -11144,8 +11329,9 @@ }, "node_modules/dashdash": { "version": "1.14.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -11243,8 +11429,9 @@ }, "node_modules/stylefmt/node_modules/postcss-less/node_modules/chalk/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -11288,8 +11475,9 @@ }, "node_modules/watchify/node_modules/is-binary-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", "dev": true, - "license": "MIT", "dependencies": { "binary-extensions": "^1.0.0" }, @@ -11349,8 +11537,9 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver" } @@ -11449,8 +11638,9 @@ }, "node_modules/es6-promisify": { "version": "5.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dev": true, "dependencies": { "es6-promise": "^4.0.3" } @@ -11472,8 +11662,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/acorn": { "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -11547,8 +11738,9 @@ }, "node_modules/expand-brackets/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, - "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -11604,16 +11796,18 @@ }, "node_modules/import-sort-cli/node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/import-sort-style-eslint/node_modules/astral-regex": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -11690,8 +11884,9 @@ }, "node_modules/import-sort-cli/node_modules/glob-parent": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -11759,8 +11954,9 @@ }, "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { "version": "6.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11795,8 +11991,9 @@ }, "node_modules/socket.io-parser": { "version": "4.2.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -11869,7 +12066,9 @@ }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { "node": ">=12" } @@ -11919,8 +12118,9 @@ }, "node_modules/import-sort-cli/node_modules/ansi-regex": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -12057,16 +12257,18 @@ }, "node_modules/arr-diff": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/tough-cookie": { "version": "2.5.0", - "devOptional": true, - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -12102,8 +12304,9 @@ }, "node_modules/sugarss/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -12142,8 +12345,9 @@ }, "node_modules/which-module": { "version": "2.0.1", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true }, "node_modules/@babel/plugin-proposal-optional-chaining": { "version": "7.21.0", @@ -12275,7 +12479,9 @@ }, "node_modules/extsprintf": { "version": "1.4.1", - "devOptional": true, + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -12287,8 +12493,9 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -12507,8 +12714,9 @@ }, "node_modules/has-ansi/node_modules/ansi-regex": { "version": "2.1.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -12693,8 +12901,9 @@ }, "node_modules/call-me-maybe": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true }, "node_modules/has-symbols": { "version": "1.0.3", @@ -12778,8 +12987,9 @@ }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", - "devOptional": true, - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -12856,7 +13066,6 @@ }, "node_modules/@angular-devkit/build-angular/node_modules/webpack": { "version": "5.76.0", - "license": "MIT", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dependencies": { @@ -12993,8 +13202,9 @@ }, "node_modules/array-uniq": { "version": "1.0.3", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -13022,8 +13232,9 @@ }, "node_modules/@types/selenium-webdriver": { "version": "3.0.26", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz", + "integrity": "sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==", + "dev": true }, "node_modules/minipass/node_modules/yallist": { "version": "4.0.0", @@ -13119,8 +13330,9 @@ }, "node_modules/dom-serialize": { "version": "2.2.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, "dependencies": { "custom-event": "~1.0.0", "ent": "~2.2.0", @@ -13180,8 +13392,9 @@ }, "node_modules/ecc-jsbn": { "version": "0.1.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -13239,7 +13452,8 @@ }, "node_modules/express/node_modules/ms": { "version": "2.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/proc-log": { "version": "2.0.1", @@ -13507,8 +13721,9 @@ }, "node_modules/date-format": { "version": "4.0.14", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true, "engines": { "node": ">=4.0" } @@ -13641,8 +13856,9 @@ }, "node_modules/browserstack": { "version": "1.5.3", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", + "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", + "dev": true, "dependencies": { "https-proxy-agent": "^2.2.1" } @@ -13663,14 +13879,19 @@ } }, "node_modules/parse-asn1": { - "version": "5.1.6", - "license": "ISC", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/stylelint/node_modules/ansi-styles": { @@ -13689,8 +13910,9 @@ }, "node_modules/har-validator/node_modules/json-schema-traverse": { "version": "0.4.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/postcss-reporter": { "version": "7.1.0", @@ -13796,8 +14018,9 @@ }, "node_modules/saucelabs/node_modules/debug": { "version": "3.2.7", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -13815,8 +14038,9 @@ }, "node_modules/engine.io/node_modules/ws": { "version": "8.11.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, "engines": { "node": ">=10.0.0" }, @@ -13835,8 +14059,9 @@ }, "node_modules/stylefmt/node_modules/postcss-less/node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -13882,7 +14107,9 @@ }, "node_modules/@angular/compiler-cli": { "version": "14.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-14.3.0.tgz", + "integrity": "sha512-eoKpKdQ2X6axMgzcPUMZVYl3bIlTMzMeTo5V29No4BzgiUB+QoOTYGNJZkGRyqTNpwD9uSBJvmT2vG9+eC4ghQ==", + "dev": true, "dependencies": { "@babel/core": "^7.17.2", "chokidar": "^3.0.0", @@ -13909,21 +14136,23 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.2", - "license": "ISC", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", "dependencies": { "bn.js": "^5.2.1", "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", + "elliptic": "^6.5.5", + "hash-base": "~3.0", "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 4" + "node": ">= 0.12" } }, "node_modules/@firebase/performance": { @@ -13953,8 +14182,9 @@ }, "node_modules/aws-sign2": { "version": "0.7.0", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, "engines": { "node": "*" } @@ -14072,8 +14302,9 @@ }, "node_modules/sshpk": { "version": "1.18.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -14311,8 +14542,9 @@ }, "node_modules/mime": { "version": "2.6.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, "bin": { "mime": "cli.js" }, @@ -14408,18 +14640,6 @@ "node": ">=0.10.0" } }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.2", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@csstools/postcss-text-decoration-shorthand": { "version": "1.0.0", "license": "CC0-1.0", @@ -14536,8 +14756,9 @@ }, "node_modules/@socket.io/component-emitter": { "version": "3.1.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -14705,8 +14926,9 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/require-from-string": { "version": "2.0.2", @@ -14717,7 +14939,9 @@ }, "node_modules/webpack/node_modules/acorn": { "version": "8.11.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -14813,8 +15037,9 @@ }, "node_modules/file-uri-to-path": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/@webassemblyjs/utf8": { @@ -14943,7 +15168,8 @@ }, "node_modules/@npmcli/move-file/node_modules/minimatch": { "version": "3.1.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -15035,16 +15261,18 @@ }, "node_modules/os-locale/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/webdriver-js-extender": { "version": "2.1.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, "dependencies": { "@types/selenium-webdriver": "^3.0.0", "selenium-webdriver": "^3.0.1" @@ -15112,8 +15340,9 @@ "license": "MIT" }, "node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/immediate": { "version": "3.0.6", @@ -15137,6 +15366,11 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/js-md5": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.8.3.tgz", + "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==" + }, "node_modules/@capacitor/dialog": { "version": "5.0.7", "license": "MIT", @@ -15146,8 +15380,9 @@ }, "node_modules/import-sort-cli/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -15455,8 +15690,9 @@ }, "node_modules/protractor/node_modules/wrap-ansi": { "version": "6.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -15482,7 +15718,8 @@ }, "node_modules/wrap-ansi/node_modules/color-convert": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { "color-name": "~1.1.4" }, @@ -15491,8 +15728,9 @@ } }, "node_modules/elliptic": { - "version": "6.5.4", - "license": "MIT", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -15522,8 +15760,10 @@ }, "node_modules/del/node_modules/glob": { "version": "7.2.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15539,24 +15779,15 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/handle-thing": { "version": "2.0.1", "license": "MIT" }, "node_modules/import-sort-cli/node_modules/braces": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "license": "MIT", "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -15706,8 +15937,9 @@ }, "node_modules/forever-agent": { "version": "0.6.1", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, "engines": { "node": "*" } @@ -15719,7 +15951,9 @@ }, "node_modules/dependency-graph": { "version": "0.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, "engines": { "node": ">= 0.6.0" } @@ -15750,8 +15984,10 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -15780,9 +16016,11 @@ }, "node_modules/watchify/node_modules/fsevents": { "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", "dev": true, "hasInstallScript": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -15854,8 +16092,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/supports-color": { "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^1.0.0" }, @@ -15893,8 +16132,9 @@ }, "node_modules/postcss-sass/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -15906,7 +16146,9 @@ }, "node_modules/jsprim/node_modules/extsprintf": { "version": "1.3.0", - "devOptional": true, + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -15933,16 +16175,18 @@ }, "node_modules/oauth-sign": { "version": "0.9.0", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, "engines": { "node": "*" } }, "node_modules/selenium-webdriver/node_modules/tmp": { "version": "0.0.30", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", + "dev": true, "dependencies": { "os-tmpdir": "~1.0.1" }, @@ -15970,8 +16214,9 @@ }, "node_modules/has-ansi": { "version": "2.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -16087,8 +16332,9 @@ }, "node_modules/protractor/node_modules/glob": { "version": "7.2.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -16205,8 +16451,9 @@ }, "node_modules/selenium-webdriver/node_modules/xml2js": { "version": "0.4.23", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -16263,16 +16510,18 @@ }, "node_modules/connect/node_modules/statuses": { "version": "1.5.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/streamroller": { "version": "3.1.5", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -16451,13 +16700,15 @@ }, "node_modules/expand-brackets/node_modules/ms": { "version": "2.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -16470,6 +16721,7 @@ "license": "MIT", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", + "dev": true, "dependencies": { "chrome-trace-event": "^1.0.2", "eslint-scope": "5.1.1", @@ -16598,8 +16850,9 @@ }, "node_modules/browserstack/node_modules/agent-base": { "version": "4.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, "dependencies": { "es6-promisify": "^5.0.0" }, @@ -16609,8 +16862,9 @@ }, "node_modules/pinkie": { "version": "2.0.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -16701,8 +16955,9 @@ }, "node_modules/watchify/node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16832,8 +17087,9 @@ }, "node_modules/streamroller/node_modules/jsonfile": { "version": "4.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -16847,8 +17103,9 @@ }, "node_modules/sax": { "version": "1.1.4", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "dev": true }, "node_modules/stylelint-order/node_modules/json-schema-traverse": { "version": "0.4.1", @@ -16875,8 +17132,9 @@ }, "node_modules/ecc-jsbn/node_modules/jsbn": { "version": "0.1.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true }, "node_modules/chokidar": { "version": "3.6.0", @@ -16902,7 +17160,9 @@ }, "node_modules/ua-parser-js": { "version": "0.7.37", - "devOptional": true, + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -16924,8 +17184,9 @@ }, "node_modules/is-path-in-cwd/node_modules/is-path-inside": { "version": "1.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==", + "dev": true, "dependencies": { "path-is-inside": "^1.0.1" }, @@ -17019,7 +17280,8 @@ }, "node_modules/@npmcli/move-file/node_modules/brace-expansion": { "version": "1.1.11", - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -17141,8 +17403,10 @@ }, "node_modules/har-validator": { "version": "5.1.5", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -17164,8 +17428,9 @@ }, "node_modules/os-locale/node_modules/npm-run-path": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^2.0.0" }, @@ -17327,8 +17592,9 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -17343,8 +17609,9 @@ }, "node_modules/class-utils/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, - "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -17489,8 +17756,9 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -17512,7 +17780,8 @@ }, "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/stylefmt/node_modules/debug": { "version": "2.6.9", @@ -17642,10 +17911,19 @@ "node": ">=6.9.0" } }, + "node_modules/@angular-devkit/build-angular/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/watchify/node_modules/is-number": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "dev": true, - "license": "MIT", "dependencies": { "kind-of": "^3.0.2" }, @@ -17655,8 +17933,9 @@ }, "node_modules/webdriver-manager/node_modules/supports-color": { "version": "2.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -17694,8 +17973,9 @@ }, "node_modules/engine.io/node_modules/cookie": { "version": "0.4.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -17807,8 +18087,9 @@ }, "node_modules/protractor/node_modules/jasmine-core": { "version": "2.8.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", + "dev": true }, "node_modules/multimatch/node_modules/brace-expansion": { "version": "1.1.11", @@ -17821,16 +18102,18 @@ }, "node_modules/qjobs": { "version": "1.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, "engines": { "node": ">=0.9" } }, "node_modules/engine.io": { "version": "6.5.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dev": true, "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -18155,8 +18438,9 @@ }, "node_modules/import-sort-cli/node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -18182,8 +18466,9 @@ }, "node_modules/webdriver-manager/node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -18303,7 +18588,9 @@ }, "node_modules/magic-string": { "version": "0.26.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", + "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", + "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" }, @@ -18411,8 +18698,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/table/node_modules/ansi-regex": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -18706,8 +18994,9 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -18818,8 +19107,9 @@ }, "node_modules/protractor/node_modules/source-map-support": { "version": "0.4.18", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, "dependencies": { "source-map": "^0.5.6" } @@ -18927,8 +19217,9 @@ }, "node_modules/protractor/node_modules/jasmine": { "version": "2.8.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", + "dev": true, "dependencies": { "exit": "^0.1.2", "glob": "^7.0.6", @@ -18940,8 +19231,9 @@ }, "node_modules/import-sort-cli/node_modules/path-type/node_modules/pify": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -19003,8 +19295,9 @@ }, "node_modules/webdriver-manager/node_modules/glob": { "version": "7.2.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -19054,8 +19347,9 @@ }, "node_modules/os-locale/node_modules/path-key": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -19221,7 +19515,9 @@ }, "node_modules/webpack/node_modules/json-schema-traverse": { "version": "0.4.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@angular/platform-browser": { "version": "14.3.0", @@ -19245,16 +19541,18 @@ }, "node_modules/stylefmt/node_modules/postcss-reporter/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/import-sort-cli/node_modules/p-locate": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -19301,8 +19599,9 @@ }, "node_modules/import-sort-cli/node_modules/array-union": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, - "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -19323,8 +19622,9 @@ }, "node_modules/protractor/node_modules/ansi-regex": { "version": "2.1.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -19412,8 +19712,9 @@ }, "node_modules/nanomatch": { "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, - "license": "MIT", "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -19444,8 +19745,9 @@ }, "node_modules/flatted": { "version": "3.3.1", - "devOptional": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.23.6", @@ -19493,8 +19795,9 @@ }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, - "license": "MIT", "dependencies": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" @@ -19605,7 +19908,9 @@ }, "node_modules/cliui": { "version": "7.0.4", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -19688,8 +19993,9 @@ }, "node_modules/nan": { "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/@nodelib/fs.walk": { @@ -19743,7 +20049,8 @@ }, "node_modules/compression/node_modules/ms": { "version": "2.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/@grpc/proto-loader/node_modules/cliui": { "version": "8.0.1", @@ -19759,8 +20066,9 @@ }, "node_modules/@mrmlnc/readdir-enhanced/node_modules/glob-to-regexp": { "version": "0.3.0", - "dev": true, - "license": "BSD" + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true }, "node_modules/stylefmt/node_modules/stylelint": { "version": "7.13.0", @@ -19840,8 +20148,9 @@ }, "node_modules/import-sort-cli/node_modules/slash": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -19888,8 +20197,9 @@ }, "node_modules/protractor/node_modules/yargs": { "version": "15.4.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -19934,8 +20244,9 @@ }, "node_modules/import-sort-cli/node_modules/is-number/node_modules/kind-of": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dev": true, - "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -19945,8 +20256,9 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.23.3", @@ -20217,13 +20529,15 @@ }, "node_modules/verror/node_modules/core-util-is": { "version": "1.0.2", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true }, "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -20246,16 +20560,6 @@ "node": ">=4" } }, - "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/pretty-hrtime": { "version": "1.0.3", "dev": true, @@ -20347,8 +20651,9 @@ }, "node_modules/isstream": { "version": "0.1.2", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true }, "node_modules/bonjour-service": { "version": "1.2.1", @@ -20477,8 +20782,9 @@ }, "node_modules/extglob/node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -20581,7 +20887,9 @@ }, "node_modules/webpack/node_modules/acorn-import-assertions": { "version": "1.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, "peerDependencies": { "acorn": "^8" } @@ -20644,8 +20952,9 @@ }, "node_modules/webdriver-manager/node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -20939,8 +21248,9 @@ }, "node_modules/connect/node_modules/on-finished": { "version": "2.3.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -20964,8 +21274,9 @@ }, "node_modules/webdriver-manager/node_modules/ansi-regex": { "version": "2.1.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -21038,8 +21349,9 @@ }, "node_modules/import-sort-cli/node_modules/fill-range/node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, - "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -21081,8 +21393,10 @@ }, "node_modules/selenium-webdriver/node_modules/glob": { "version": "7.2.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -21193,8 +21507,9 @@ }, "node_modules/har-validator/node_modules/ajv": { "version": "6.12.6", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -21341,16 +21656,18 @@ }, "node_modules/request/node_modules/qs": { "version": "6.5.3", - "devOptional": true, - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, "engines": { "node": ">=0.6" } }, "node_modules/saucelabs/node_modules/https-proxy-agent": { "version": "2.2.4", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, "dependencies": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -21361,7 +21678,9 @@ }, "node_modules/reflect-metadata": { "version": "0.1.14", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "dev": true }, "node_modules/arr-flatten": { "version": "1.1.0", @@ -21436,8 +21755,9 @@ }, "node_modules/import-sort-style-eslint/node_modules/inquirer/node_modules/ansi-regex": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -21489,8 +21809,9 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -21740,8 +22061,9 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/make-dir": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, - "license": "MIT", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -21771,8 +22093,9 @@ }, "node_modules/jszip": { "version": "3.10.1", - "devOptional": true, - "license": "(MIT OR GPL-3.0-or-later)", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -21782,8 +22105,9 @@ }, "node_modules/import-sort-cli/node_modules/string-width": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, - "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -21906,8 +22230,9 @@ }, "node_modules/watchify/node_modules/fill-range/node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, - "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -21917,8 +22242,9 @@ }, "node_modules/protractor/node_modules/color-convert": { "version": "2.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -22018,8 +22344,9 @@ }, "node_modules/log4js": { "version": "6.9.1", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -22213,8 +22540,9 @@ }, "node_modules/import-sort-cli/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -22261,8 +22589,9 @@ }, "node_modules/selenium-webdriver": { "version": "3.6.0", - "devOptional": true, - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, "dependencies": { "jszip": "^3.1.3", "rimraf": "^2.5.4", @@ -22393,7 +22722,9 @@ "license": "MIT" }, "node_modules/follow-redirects": { - "version": "1.15.5", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -22462,8 +22793,9 @@ }, "node_modules/protractor/node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -22737,8 +23069,9 @@ }, "node_modules/browserstack/node_modules/debug": { "version": "3.2.7", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -22804,8 +23137,9 @@ }, "node_modules/webdriver-manager/node_modules/chalk": { "version": "1.1.3", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -23121,8 +23455,9 @@ }, "node_modules/expand-brackets/node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, - "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -23262,8 +23597,9 @@ }, "node_modules/import-sort-cli/node_modules/braces/node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, - "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -23339,8 +23675,9 @@ }, "node_modules/adm-zip": { "version": "0.5.10", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, "engines": { "node": ">=6.0" } @@ -23430,8 +23767,9 @@ }, "node_modules/watchify/node_modules/micromatch": { "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "license": "MIT", "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -23581,8 +23919,9 @@ }, "node_modules/rfdc": { "version": "1.3.1", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true }, "node_modules/eslint/node_modules/globals": { "version": "13.24.0", @@ -23623,8 +23962,9 @@ }, "node_modules/blocking-proxy": { "version": "1.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -23637,8 +23977,9 @@ }, "node_modules/posix-character-classes": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -23653,8 +23994,9 @@ }, "node_modules/engine.io-parser": { "version": "5.2.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -23680,16 +24022,18 @@ }, "node_modules/is-path-cwd": { "version": "1.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==", + "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/bindings": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "file-uri-to-path": "1.0.0" @@ -23807,8 +24151,9 @@ }, "node_modules/stylefmt/node_modules/postcss-sorting/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -23855,7 +24200,9 @@ }, "node_modules/verror": { "version": "1.10.0", - "devOptional": true, + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -23893,8 +24240,9 @@ }, "node_modules/http-signature": { "version": "1.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -23972,8 +24320,9 @@ }, "node_modules/import-sort-cli/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -24065,8 +24414,9 @@ }, "node_modules/assert-plus": { "version": "1.0.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, "engines": { "node": ">=0.8" } @@ -24159,8 +24509,9 @@ }, "node_modules/selenium-webdriver/node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -24180,8 +24531,9 @@ }, "node_modules/q": { "version": "1.5.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "dev": true, "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" @@ -24189,8 +24541,9 @@ }, "node_modules/connect/node_modules/debug": { "version": "2.6.9", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -24252,8 +24605,9 @@ }, "node_modules/stylefmt/node_modules/stylelint/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -24324,8 +24678,9 @@ }, "node_modules/watchify/node_modules/to-regex-range": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -24336,8 +24691,9 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -24525,8 +24881,9 @@ }, "node_modules/webdriver-manager/node_modules/rimraf": { "version": "2.7.1", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -24536,8 +24893,9 @@ }, "node_modules/import-sort-cli/node_modules/glob-parent/node_modules/is-glob": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.0" }, @@ -24662,8 +25020,10 @@ }, "node_modules/karma-coverage-istanbul-reporter/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -24789,8 +25149,9 @@ }, "node_modules/protractor/node_modules/source-map": { "version": "0.5.7", - "devOptional": true, - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -24808,8 +25169,9 @@ }, "node_modules/import-sort-cli/node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -24860,8 +25222,9 @@ }, "node_modules/webdriver-manager/node_modules/semver": { "version": "5.7.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -24917,8 +25280,9 @@ }, "node_modules/form-data": { "version": "2.3.3", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -25084,8 +25448,9 @@ }, "node_modules/del": { "version": "2.2.2", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ==", + "dev": true, "dependencies": { "globby": "^5.0.0", "is-path-cwd": "^1.0.0", @@ -25182,8 +25547,9 @@ }, "node_modules/tslint/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -25263,8 +25629,9 @@ }, "node_modules/protractor/node_modules/yargs-parser": { "version": "18.1.3", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -25288,8 +25655,9 @@ }, "node_modules/import-sort-cli/node_modules/fill-range": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "dev": true, - "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -25481,8 +25849,9 @@ }, "node_modules/asn1": { "version": "0.2.6", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -25511,8 +25880,9 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -25539,13 +25909,13 @@ } }, "node_modules/asn1.js": { - "version": "5.4.1", - "license": "MIT", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "minimalistic-assert": "^1.0.0" } }, "node_modules/postcss-cli/node_modules/path-type": { @@ -25561,8 +25931,9 @@ }, "node_modules/protractor/node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "6.0.1", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -25639,6 +26010,11 @@ "@types/node": "*" } }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "node_modules/object.assign": { "version": "4.1.5", "license": "MIT", @@ -25663,20 +26039,6 @@ "node": ">=0.10.0" } }, - "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.4", - "license": "MIT", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/agentkeepalive": { "version": "4.5.0", "dev": true, @@ -25809,8 +26171,9 @@ } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" }, "node_modules/@angular-devkit/core/node_modules/ajv": { "version": "8.11.0", @@ -25870,8 +26233,9 @@ }, "node_modules/karma/node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -25899,8 +26263,9 @@ }, "node_modules/import-sort-cli/node_modules/is-number": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "dev": true, - "license": "MIT", "dependencies": { "kind-of": "^3.0.2" }, @@ -25922,8 +26287,9 @@ }, "node_modules/jasminewd2": { "version": "2.2.0", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", + "dev": true, "engines": { "node": ">= 6.9.x" } @@ -25971,8 +26337,9 @@ }, "node_modules/connect/node_modules/ms": { "version": "2.0.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/node-gyp-build": { "version": "4.8.0", @@ -26021,8 +26388,9 @@ }, "node_modules/import-sort-cli/node_modules/path-type": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "license": "MIT", "dependencies": { "pify": "^3.0.0" }, @@ -26212,8 +26580,9 @@ }, "node_modules/webdriver-manager/node_modules/xml2js": { "version": "0.4.23", - "devOptional": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -26277,8 +26646,9 @@ }, "node_modules/del/node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -26288,8 +26658,9 @@ }, "node_modules/stylefmt/node_modules/sugarss/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -26505,8 +26876,9 @@ }, "node_modules/ent": { "version": "2.2.0", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true }, "node_modules/onecolor": { "version": "3.1.0", @@ -26555,4 +26927,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index ef22902ff..175ada176 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "ajv-formats": "^2.1.1", "angular-svg-round-progressbar": "^9.0.0", "autoprefixer": "^10.0.0", - "avro-js": "^1.11.1", + "avro-js": "^1.11.3", "base64-js": "^1.5.1", "browserify": "^16.3.0", "browserify-zlib": "^0.2.0", @@ -87,17 +87,22 @@ "compare-versions": "^5.0.3", "core-js": "2.6.8", "dompurify": "^2.2.8", + "emojis-list": "^3.0.0", + "eventemitter3": "^5.0.1", "execa": "^4.0.3", "firebase": "^10.8.0", + "follow-redirects": "^1.15.6", "graphlib": "^2.1.8", "install": "^0.13.0", "ionicons": "^6.1.1", + "js-md5": "^0.8.3", "moment": "^2.29.4", "moment-timezone": "^0.5.40", "morph-expressions": "^1.1.1", "ngx-moment": "^5.0.0", "pako": "^2.1.0", "path": "^0.12.7", + "requires-port": "^1.0.0", "rxjs": "^7.5.0", "sass": "^1.75.0", "smoothscroll-polyfill": "^0.4.4", @@ -121,7 +126,7 @@ "@ionic/angular-toolkit": "^7.0.0", "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", - "@types/node": "^20.12.2", + "@types/node": "20.12.2", "codelyzer": "^6.0.2", "cordova-sqlite-storage": "^6.0.0", "eslint": "^7.6.0", diff --git a/resources/icon.png b/resources/icon-old.png similarity index 100% rename from resources/icon.png rename to resources/icon-old.png diff --git a/src/app/app.module.ts b/src/app/app.module.ts index fb4c2963f..19b0920ad 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -28,7 +28,6 @@ import { CompletionLogConverterService } from './core/services/kafka/converters/ import { ConverterFactoryService } from './core/services/kafka/converters/converter-factory.service.' import { ConverterService } from './core/services/kafka/converters/converter.service' import { HealthkitConverterService } from './core/services/kafka/converters/healthkit-converter.service' -import { KeyConverterService } from './core/services/kafka/converters/key-converter.service' import { TimezoneConverterService } from './core/services/kafka/converters/timezone-converter.service' import { KafkaService } from './core/services/kafka/kafka.service' import { SchemaService } from './core/services/kafka/schema.service' @@ -56,6 +55,8 @@ import { PagesModule } from './pages/pages.module' import { TranslatePipe } from './shared/pipes/translate/translate' import { jwtOptionsFactory } from './shared/utilities/jwtOptionsFactory' import { Utility } from './shared/utilities/util' +import { DefaultKeyConverterService } from './core/services/kafka/converters/default-key-converter.service' +import { KeyConverterService } from './core/services/kafka/converters/key-converter.service' @NgModule({ imports: [ @@ -115,8 +116,8 @@ import { Utility } from './shared/utilities/util' AppEventConverterService, CompletionLogConverterService, TimezoneConverterService, - KeyConverterService, HealthkitConverterService, + { provide: KeyConverterService, useClass: DefaultKeyConverterService }, CacheService, NotificationGeneratorService, FcmRestNotificationService, @@ -129,4 +130,4 @@ import { Utility } from './shared/utilities/util' ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) -export class AppModule {} +export class AppModule { } diff --git a/src/app/core/services/kafka/cache.service.ts b/src/app/core/services/kafka/cache.service.ts index 28ac87e67..bf4769b9a 100755 --- a/src/app/core/services/kafka/cache.service.ts +++ b/src/app/core/services/kafka/cache.service.ts @@ -1,61 +1,62 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http' import { Injectable } from '@angular/core' +import { md5 } from 'js-md5' -import { - DefaultClientAcceptType, - DefaultKafkaRequestContentType, - DefaultKafkaURI -} from '../../../../assets/data/defaultConfig' -import { ConfigKeys } from '../../../shared/enums/config' import { DataEventType } from '../../../shared/enums/events' import { StorageKeys } from '../../../shared/enums/storage' import { CacheValue } from '../../../shared/models/cache' -import { - KafkaObject, - KeyExport, - SchemaType -} from '../../../shared/models/kafka' -import { RemoteConfigService } from '../config/remote-config.service' -import { SubjectConfigService } from '../config/subject-config.service' +import { SchemaType } from '../../../shared/models/kafka' import { LogService } from '../misc/log.service' import { StorageService } from '../storage/storage.service' -import { TokenService } from '../token/token.service' import { AnalyticsService } from '../usage/analytics.service' -import { SchemaService } from './schema.service' @Injectable() export class CacheService { URI_topics: string = '/topics/' - HEALTH_CACHE_LIMIT = 10000 private readonly KAFKA_STORE = { LAST_UPLOAD_DATE: StorageKeys.LAST_UPLOAD_DATE, CACHE_ANSWERS: StorageKeys.CACHE_ANSWERS } - private isCacheSending: boolean - constructor( private storage: StorageService, private analytics: AnalyticsService, private logger: LogService - ) {} + ) { } init() { return Promise.all([this.setCache({})]) } - storeInCache(type, kafkaObject: KafkaObject, cacheValue: any) { - return this.getCache().then(cache => { - this.logger.log('KAFKA-SERVICE: Caching answers.') - cache[kafkaObject.value.time] = cacheValue - this.sendDataEvent(DataEventType.CACHED, cacheValue) + storeInCache(type, kafkaObject, cacheValue: any) { + return this.getCache().then(cache => { + this.logger.log('KAFKA-SERVICE: Caching answers.') + const key = this.generateCacheKey(type, kafkaObject) + cache[key] = cacheValue + this.sendDataEvent(DataEventType.CACHED, cacheValue) + return this.setCache(cache) + }) + } + + removeFromCache(cacheKey: string) { + return this.getCache().then(cache => { + if (cache) { + if (cache[cacheKey]) { + this.sendDataEvent( + DataEventType.REMOVED_FROM_CACHE, + cache[cacheKey] + ) + this.logger.log('Deleting ' + cacheKey) + delete cache[cacheKey] + } + this.setLastUploadDate(Date.now()) return this.setCache(cache) - }) - + } + }) } - removeFromCache(cacheKeys: number[]) { + + removeFromCacheMultiple(cacheKeys: string[]) { if (!cacheKeys.length) return Promise.resolve() return this.getCache().then(cache => { if (cache) { @@ -79,10 +80,6 @@ export class CacheService { return this.storage.set(this.KAFKA_STORE.CACHE_ANSWERS, cache) } - setCacheSending(val: boolean) { - this.isCacheSending = val - } - setLastUploadDate(date) { return this.storage.set(this.KAFKA_STORE.LAST_UPLOAD_DATE, date) } @@ -112,10 +109,12 @@ export class CacheService { }) } + generateCacheKey(prefix: string, data: any): string { + const hash = md5(JSON.stringify(data)) + return `${prefix}:${hash}` + } + reset() { - return Promise.all([ - this.setCache({}), - this.setLastUploadDate(null) - ]) + return Promise.all([this.setCache({}), this.setLastUploadDate(null)]) } } diff --git a/src/app/core/services/kafka/converters/app-event-converter.service.ts b/src/app/core/services/kafka/converters/app-event-converter.service.ts index f08406860..043972e15 100644 --- a/src/app/core/services/kafka/converters/app-event-converter.service.ts +++ b/src/app/core/services/kafka/converters/app-event-converter.service.ts @@ -9,6 +9,7 @@ import { Utility } from 'src/app/shared/utilities/util' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' import { ConverterService } from './converter.service' +import { KeyConverterService } from './key-converter.service' import { RemoteConfigService } from '../../config/remote-config.service' @Injectable() @@ -18,9 +19,10 @@ export class AppEventConverterService extends ConverterService { http: HttpClient, token: TokenService, private utility: Utility, + keyConverter: KeyConverterService, remoteConfig: RemoteConfigService ) { - super(logger, http, token, remoteConfig) + super(logger, http, token, keyConverter, remoteConfig) } init() { } diff --git a/src/app/core/services/kafka/converters/assessment-converter.service.ts b/src/app/core/services/kafka/converters/assessment-converter.service.ts index abedc9567..d308d873c 100644 --- a/src/app/core/services/kafka/converters/assessment-converter.service.ts +++ b/src/app/core/services/kafka/converters/assessment-converter.service.ts @@ -7,14 +7,21 @@ import { getSeconds } from 'src/app/shared/utilities/time' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' import { ConverterService } from './converter.service' +import { KeyConverterService } from './key-converter.service' import { RemoteConfigService } from '../../config/remote-config.service' @Injectable() export class AssessmentConverterService extends ConverterService { GENERAL_TOPIC: string = 'questionnaire_response' - constructor(logger: LogService, http: HttpClient, token: TokenService, remoteConfig: RemoteConfigService) { - super(logger, http, token, remoteConfig) + constructor( + logger: LogService, + http: HttpClient, + token: TokenService, + keyConverter: KeyConverterService, + remoteConfig: RemoteConfigService + ) { + super(logger, http, token, keyConverter, remoteConfig) } init() { } @@ -52,10 +59,6 @@ export class AssessmentConverterService extends ConverterService { if (this.topicExists(specTopic, topics)) { return Promise.resolve(specTopic) } - const questionnaireTopic = `${payload.avsc}_${payload.name}` - if (this.topicExists(questionnaireTopic, topics)) { - return Promise.resolve(questionnaireTopic) - } const defaultTopic = this.GENERAL_TOPIC if (this.topicExists(defaultTopic, topics)) { return Promise.resolve(defaultTopic) diff --git a/src/app/core/services/kafka/converters/completion-log-converter.service.ts b/src/app/core/services/kafka/converters/completion-log-converter.service.ts index be2553651..61dd04428 100644 --- a/src/app/core/services/kafka/converters/completion-log-converter.service.ts +++ b/src/app/core/services/kafka/converters/completion-log-converter.service.ts @@ -8,12 +8,19 @@ import { getSeconds } from 'src/app/shared/utilities/time' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' import { ConverterService } from './converter.service' +import { KeyConverterService } from './key-converter.service' import { RemoteConfigService } from '../../config/remote-config.service' @Injectable() export class CompletionLogConverterService extends ConverterService { - constructor(logger: LogService, http: HttpClient, token: TokenService, remoteConfig: RemoteConfigService) { - super(logger, http, token, remoteConfig) + constructor( + logger: LogService, + http: HttpClient, + token: TokenService, + keyConverter: KeyConverterService, + remoteConfig: RemoteConfigService + ) { + super(logger, http, token, keyConverter, remoteConfig) } init() { } diff --git a/src/app/core/services/kafka/converters/converter-factory.service..ts b/src/app/core/services/kafka/converters/converter-factory.service..ts index f933da405..afd3a95b1 100644 --- a/src/app/core/services/kafka/converters/converter-factory.service..ts +++ b/src/app/core/services/kafka/converters/converter-factory.service..ts @@ -1,4 +1,3 @@ -import { HttpClient } from '@angular/common/http' import { Injectable } from '@angular/core' import { SchemaType } from 'src/app/shared/models/kafka' @@ -6,7 +5,6 @@ import { AppEventConverterService } from './app-event-converter.service' import { AssessmentConverterService } from './assessment-converter.service' import { CompletionLogConverterService } from './completion-log-converter.service' import { HealthkitConverterService } from './healthkit-converter.service' -import { KeyConverterService } from './key-converter.service' import { TimezoneConverterService } from './timezone-converter.service' @Injectable() @@ -17,7 +15,6 @@ export class ConverterFactoryService { private appEventConverter: AppEventConverterService, private completionLogConverter: CompletionLogConverterService, private timzoneConverter: TimezoneConverterService, - private keyConverter: KeyConverterService ) { } init() { } @@ -34,8 +31,6 @@ export class ConverterFactoryService { return this.timzoneConverter case SchemaType.APP_EVENT: return this.appEventConverter - case SchemaType.KEY: - return this.keyConverter default: return this.assessmentConverter } diff --git a/src/app/core/services/kafka/converters/converter.service.ts b/src/app/core/services/kafka/converters/converter.service.ts index f5aeda51a..9af744ae1 100644 --- a/src/app/core/services/kafka/converters/converter.service.ts +++ b/src/app/core/services/kafka/converters/converter.service.ts @@ -9,6 +9,7 @@ import * as YAML from 'yaml' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' +import { KeyConverterService } from './key-converter.service' import { ConfigKeys } from 'src/app/shared/enums/config' import { RemoteConfigService } from '../../config/remote-config.service' @@ -24,6 +25,7 @@ export abstract class ConverterService { public logger: LogService, private http: HttpClient, public token: TokenService, + public keyConverter: KeyConverterService, private remoteConfig: RemoteConfigService ) { this.updateURI() @@ -48,31 +50,41 @@ export abstract class ConverterService { } } - convertToRecord(kafkaValue, topic, valueSchemaMetadata) { - const value = JSON.parse(valueSchemaMetadata.schema) - const record = { - schema: valueSchemaMetadata.id, - value: this.convertToAvro(value, kafkaValue), - topic - } - return record - } - - batchConvertToRecord(kafkaValues, topic, valueSchemaMetadata) { - const value = JSON.parse(valueSchemaMetadata.schema) - return this.batchConvertToAvro(value, kafkaValues).map(v => ({ - value: v, - schema: valueSchemaMetadata.id - })) + convertToAvro(kafkaValue, valueSchemaMetadata) { + const schema = JSON.parse(valueSchemaMetadata.schema) + return AvroSchema.parse(schema).clone(kafkaValue, { wrapUnions: true }) } - convertToAvro(schema, value): any { - return AvroSchema.parse(schema).clone(value, { wrapUnions: true }) + batchConvertToAvro(kafkaValues, valueSchemaMetadata) { + const schema = JSON.parse(valueSchemaMetadata.schema) + const parsedSchema = AvroSchema.parse(schema) + return kafkaValues.map(v => parsedSchema.clone(v, { wrapUnions: true })) } - batchConvertToAvro(schema, values): any { - const parsedSchema = AvroSchema.parse(schema) - return values.map(v => parsedSchema.clone(v, { wrapUnions: true })) + getKafkaPayload( + type, + kafkaKey, + kafkaObject: any, + cacheKey: any, + topics + ): Promise { + return this.getKafkaTopic(kafkaObject, topics).then(topic => + this.getSchemas(topic).then(schema => { + return Promise.all([ + this.keyConverter + .convertToRecord(kafkaKey, topic), + this.convertToAvro(kafkaObject, schema) + ]).then(([key, record]) => ({ + topic, + cacheKey: cacheKey, + record: { + key_schema_id: key.schema, + value_schema_id: schema.id, + records: [{ key: key.value, value: record }] + } + })) + }) + ) } getUniqueTimeNow() { diff --git a/src/app/core/services/kafka/converters/default-key-converter.service.ts b/src/app/core/services/kafka/converters/default-key-converter.service.ts new file mode 100644 index 000000000..2f14554c1 --- /dev/null +++ b/src/app/core/services/kafka/converters/default-key-converter.service.ts @@ -0,0 +1,72 @@ +import { HttpClient } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { KeyExport, SchemaMetadata } from 'src/app/shared/models/kafka' + +import { LogService } from '../../misc/log.service' +import { TokenService } from '../../token/token.service' +import { KeyConverterService } from './key-converter.service' + +@Injectable() +export class DefaultKeyConverterService extends KeyConverterService { + schemas = {} + specifications + URI_schema: string = '/schema/subjects/' + URI_version: string = '/versions/' + BASE_URI: string + + constructor(private logger: LogService, private http: HttpClient, public token: TokenService, + ) { + super() + this.updateURI() + } + + updateURI() { + return this.token.getURI().then(uri => (this.BASE_URI = uri)) + } + + async getSchema(topic) { + if (this.schemas[topic]) return Promise.resolve(this.schemas[topic]) + else { + const versionStr = this.URI_version + 'latest' + const uri = + this.BASE_URI + + this.URI_schema + + topic + + '-key' + + versionStr + const schema = await this.getLatestKafkaSchemaVersion(uri) + this.schemas[topic] = schema + return schema + } + } + + convertToRecord(kafkaKey, topic): any { + return this.getSchema(topic).then(keySchemaMetadata => { + const key = JSON.parse(keySchemaMetadata.schema) + const record = { + schema: keySchemaMetadata.id, + value: this.convertToAvro(key, kafkaKey) + } + return record + }) + } + + processData(payload) { + const key: KeyExport = { + sourceId: payload.sourceId, + userId: payload.userId, + projectId: payload.projectId + } + + return key + } + + getLatestKafkaSchemaVersion(uri): Promise { + return this.http + .get(uri) + .toPromise() + .catch(e => { + throw this.logger.error('Failed to get latest Kafka schema versions', e) + }) + } +} diff --git a/src/app/core/services/kafka/converters/healthkit-converter.service.ts b/src/app/core/services/kafka/converters/healthkit-converter.service.ts index cc1385756..9dd7dbed8 100644 --- a/src/app/core/services/kafka/converters/healthkit-converter.service.ts +++ b/src/app/core/services/kafka/converters/healthkit-converter.service.ts @@ -1,89 +1,210 @@ import { HttpClient } from '@angular/common/http' import { Injectable } from '@angular/core' -import { AnswerValueExport } from 'src/app/shared/models/answer' import { + HealthKitDataKey, HealthKitDataTypeKey, HealthkitDataType, - HealthkitStringDataType + HealthkitFloatDataTypes, + HealthkitStringDataTypes, + HealthkitTopic, + HealthkitValueExport } from 'src/app/shared/models/health' -import { QuestionType } from 'src/app/shared/models/question' import { getSeconds } from 'src/app/shared/utilities/time' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' import { ConverterService } from './converter.service' +import { HealthkitService } from 'src/app/pages/questions/services/healthkit.service' +import { StorageService } from '../../storage/storage.service' +import { StorageKeys } from 'src/app/shared/enums/storage' +import { KeyConverterService } from './key-converter.service' +import { Utility } from 'src/app/shared/utilities/util' import { RemoteConfigService } from '../../config/remote-config.service' @Injectable() export class HealthkitConverterService extends ConverterService { GENERAL_TOPIC: string = 'questionnaire_response' + HEALTHKIT_TOPIC = 'active_apple_healthkit_steps' - HEALTHKIT_KEYS: Set = new Set([ - HealthkitDataType.ACTIVITY, - HealthkitDataType.APPLE_EXERCISE_TIME, - HealthkitDataType.CALORIES, - HealthkitDataType.DISTANCE, - HealthkitDataType.STAIRS, - HealthkitDataType.VO2MAX - ]) - - constructor(logger: LogService, http: HttpClient, token: TokenService, remoteConfig: RemoteConfigService) { - super(logger, http, token, remoteConfig) + constructor( + private healthkit: HealthkitService, + private storage: StorageService, + private util: Utility, + logger: LogService, + http: HttpClient, + token: TokenService, + keyConverter: KeyConverterService, + remoteConfig: RemoteConfigService + ) { + super(logger, http, token, keyConverter, remoteConfig) } init() { } - processData(payload) { - const answers = payload.data.answers - let processedData = {} - Object.entries(answers).forEach(([k, v]) => { - if (v && v instanceof Array) { - processedData[k] = this.processSingleDatatype( - k, - v, - payload.data.timeCompleted - ) - } - }) - return processedData + processData(data) { + return { + name: 'healthkit', + time: getSeconds({ milliseconds: Date.now() }), + data: { key: data.key, value: data.value } + } } - processSingleDatatype(key, data, timeReceived) { + async processSingleDatatype( + key: string, + data: any[], + timeReceived: number + ): Promise { const type = this.getDataTypeFromKey(key) - const results = data.map(d => - Object.assign( - {}, - { - time: getSeconds({ milliseconds: new Date(d.startDate).getTime() }), - endTime: getSeconds({ milliseconds: new Date(d.endDate).getTime() }), - timeReceived: timeReceived, - sourceId: d.sourceBundleId, - sourceName: d.sourceName, - unit: d.unit, + const valueKey = this.getValueKey(key) + + if (typeof Worker !== 'undefined') { + return new Promise((resolve, reject) => { + const worker = new Worker( + 'assets/workers/healthkit-converter.worker.js' + ) + + worker.onmessage = ({ data }) => { + resolve(data) + worker.terminate() + } + + worker.onerror = error => { + reject(error) + worker.terminate() + } + worker.postMessage({ key, - intValue: null, - floatValue: null, - doubleValue: null, - stringValue: null - }, - { [type]: d.value } + inputData: data, + timeReceived, + type, + valueKey + }) + }) + } else { + return data.map(d => + Object.assign( + {}, + { + time: Math.floor(new Date(d.startDate).getTime() / 1000), + endTime: Math.floor(new Date(d.endDate).getTime() / 1000), + timeReceived: timeReceived, + sourceId: d.sourceBundleId, + sourceName: d.device + ? `${d.device.manufacturer}_${d.device.model}_${d.device.hardwareVersion}` + : d.source, + unit: d.unitName ?? '', + key, + intValue: null, + floatValue: null, + doubleValue: null, + stringValue: null + }, + { [type]: d[valueKey] } + ) ) - ) - return results + } + } + + convertToHealthkitRecord(kafkaValue, valueSchemaMetadata) { + const data = kafkaValue.data + const name = data.key + const startTime = data.value.startTime + const endTime = data.value.endTime + return Promise.all([ + this.getLastPollTimes(), + this.healthkit.query(startTime, endTime, name) + ]).then(async ([dic, res]) => { + if (res.length) { + const sample = res[res.length - 1] + const lastDataDate = new Date(sample['endDate']) + dic[name] = lastDataDate + this.setLastPollTimes(dic) + const processedData = await this.processSingleDatatype( + name, + res, + Date.now() + ) + const avroData = this.batchConvertToAvro( + processedData, + valueSchemaMetadata + ) + return avroData + } + return null + }) + } + + setLastPollTimes(dic: any) { + return this.storage.set(StorageKeys.HEALTH_LAST_POLL_TIMES, dic) + } + + getLastPollTimes() { + return this.storage.get(StorageKeys.HEALTH_LAST_POLL_TIMES) + } + + getSchemas() { + if (this.schemas[this.HEALTHKIT_TOPIC]) + return this.schemas[this.HEALTHKIT_TOPIC] + else { + const versionStr = this.URI_version + 'latest' + const uri = + this.BASE_URI + + this.URI_schema + + this.HEALTHKIT_TOPIC + + '-value' + + versionStr + const schema = this.getLatestKafkaSchemaVersion(uri) + this.schemas[this.HEALTHKIT_TOPIC] = schema + return schema + } } getDataTypeFromKey(key) { - if ( - Object.values(HealthkitStringDataType).includes( - key as HealthkitStringDataType - ) - ) { + if (HealthkitStringDataTypes.has(key as HealthkitDataType)) { return HealthKitDataTypeKey.STRING } else return HealthKitDataTypeKey.FLOAT } - getKafkaTopic(payload, topics): Promise { - const key = payload.key - return Promise.resolve('active_apple_healthkit_' + key) + getValueKey(type) { + if (type == HealthkitDataType.SLEEP_ANALYSIS) + return HealthKitDataKey.SLEEP_STATE + if (type == HealthkitDataType.WORKOUT_TYPE) + return HealthKitDataKey.ACTIVITY_TYPE + return HealthKitDataKey.DEFAULT + } + + getKafkaTopic(key): String { + for (const k in HealthkitDataType) { + if (HealthkitDataType[k] == key) return HealthkitTopic[k] + } + return this.HEALTHKIT_TOPIC + } + + getKafkaPayload( + type, + kafkaKey, + kafkaObject: any, + cacheKey: any, + topics + ): Promise { + return this.getSchemas().then(schema => { + return Promise.all([ + this.keyConverter.convertToRecord(kafkaKey, this.HEALTHKIT_TOPIC), + this.convertToHealthkitRecord(kafkaObject, schema) + ]).then(([key, records]) => ({ + topic: this.getKafkaTopic(kafkaObject.data.key), + cacheKey: cacheKey, + record: { + key_schema_id: key.schema, + value_schema_id: schema.id, + records: records + ? records.map(r => ({ + key: key.value, + value: r + })) + : [] + } + })) + }) } } diff --git a/src/app/core/services/kafka/converters/key-converter.service.ts b/src/app/core/services/kafka/converters/key-converter.service.ts index 72d1e9d55..433ac7be8 100644 --- a/src/app/core/services/kafka/converters/key-converter.service.ts +++ b/src/app/core/services/kafka/converters/key-converter.service.ts @@ -1,64 +1,34 @@ -import { HttpClient } from '@angular/common/http' -import { Injectable } from '@angular/core' -import { AnswerValueExport } from 'src/app/shared/models/answer' -import { KeyExport } from 'src/app/shared/models/kafka' -import { QuestionType } from 'src/app/shared/models/question' -import { getSeconds } from 'src/app/shared/utilities/time' - -import { LogService } from '../../misc/log.service' -import { TokenService } from '../../token/token.service' -import { ConverterService } from './converter.service' -import { RemoteConfigService } from '../../config/remote-config.service' - -@Injectable() -export class KeyConverterService extends ConverterService { - constructor(logger: LogService, http: HttpClient, token: TokenService, remoteConfig: RemoteConfigService) { - super(logger, http, token, remoteConfig) - } - - init() { } - - getKafkaTopic(payload): Promise { - return Promise.resolve() - } - - getSchemas(topic) { - if (this.schemas[topic]) return this.schemas[topic] - else { - const versionStr = this.URI_version + 'latest' - const uri = - this.BASE_URI + - this.URI_schema + - 'questionnaire_response' + - '-key' + - versionStr - const schema = this.getLatestKafkaSchemaVersion(uri) - this.schemas[topic] = schema - return schema - } - } +import { Injectable } from '@angular/core'; +import * as AvroSchema from 'avro-js' - convertToRecord(kafkaKey, topics, schema): any { - return this.getKafkaTopic(kafkaKey).then(topic => - this.getSchemas(topic).then(keySchemaMetadata => { - const key = JSON.parse(keySchemaMetadata.schema) - const record = { - schema: keySchemaMetadata.id, - value: this.convertToAvro(key, kafkaKey), - topic - } - return record - }) - ) - } - - processData(payload) { - const key: KeyExport = { - sourceId: payload.sourceId, - userId: payload.userId, - projectId: payload.projectId - } +import { KeyExport } from 'src/app/shared/models/kafka' - return key +@Injectable({ + providedIn: 'root' +}) +export abstract class KeyConverterService { + /** + * Converts a Kafka key to a record format based on the topic schema. + * @param kafkaKey The Kafka key to convert. + * @param topic The topic name to use for schema lookup. + * @returns A promise resolving to the converted record. + */ + abstract convertToRecord(kafkaKey: any, topic: string): Promise + + /** + * Processes the payload into a KeyExport object. + * @param payload The payload to process. + * @returns A KeyExport object. + */ + abstract processData(payload: any): KeyExport + + /** + * Converts a value to Avro format using the provided schema. + * @param schema The schema to use for conversion. + * @param value The value to convert. + * @returns The Avro-formatted value. + */ + convertToAvro(schema, value): any { + return AvroSchema.parse(schema).clone(value, { wrapUnions: true }) } } diff --git a/src/app/core/services/kafka/converters/timezone-converter.service.ts b/src/app/core/services/kafka/converters/timezone-converter.service.ts index 44ce0796d..0bebfbd53 100644 --- a/src/app/core/services/kafka/converters/timezone-converter.service.ts +++ b/src/app/core/services/kafka/converters/timezone-converter.service.ts @@ -8,12 +8,19 @@ import { getSeconds } from 'src/app/shared/utilities/time' import { LogService } from '../../misc/log.service' import { TokenService } from '../../token/token.service' import { ConverterService } from './converter.service' +import { KeyConverterService } from './key-converter.service' import { RemoteConfigService } from '../../config/remote-config.service' @Injectable() export class TimezoneConverterService extends ConverterService { - constructor(logger: LogService, http: HttpClient, token: TokenService, remoteConfig: RemoteConfigService) { - super(logger, http, token, remoteConfig) + constructor( + logger: LogService, + http: HttpClient, + token: TokenService, + keyConverter: KeyConverterService, + remoteConfig: RemoteConfigService + ) { + super(logger, http, token, keyConverter, remoteConfig) } init() { } diff --git a/src/app/core/services/kafka/kafka.service.spec.ts b/src/app/core/services/kafka/kafka.service.spec.ts index 28b4f9ce6..d35f64cfd 100644 --- a/src/app/core/services/kafka/kafka.service.spec.ts +++ b/src/app/core/services/kafka/kafka.service.spec.ts @@ -8,7 +8,8 @@ import { RemoteConfigServiceMock, SchemaServiceMock, StorageServiceMock, - TokenServiceMock + TokenServiceMock, + UtilityMock } from '../../../shared/testing/mock-services' import { RemoteConfigService } from '../config/remote-config.service' import { LogService } from '../misc/log.service' @@ -38,7 +39,8 @@ describe('KafkaService', () => { provide: AnalyticsService, useClass: FirebaseAnalyticsServiceMock }, - { provide: RemoteConfigService, useClass: RemoteConfigServiceMock } + { provide: RemoteConfigService, useClass: RemoteConfigServiceMock }, + { provide: Utility, useClass: UtilityMock } ] }) ) diff --git a/src/app/core/services/kafka/kafka.service.ts b/src/app/core/services/kafka/kafka.service.ts index 1ffab84b2..7aad6216c 100755 --- a/src/app/core/services/kafka/kafka.service.ts +++ b/src/app/core/services/kafka/kafka.service.ts @@ -1,6 +1,11 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http' +import { + HttpClient, + HttpErrorResponse, + HttpHeaders +} from '@angular/common/http' import { Injectable } from '@angular/core' import * as pako from 'pako' +import { CapacitorHttp } from '@capacitor/core'; import { DefaultClientAcceptType, @@ -21,6 +26,8 @@ import { TokenService } from '../token/token.service' import { AnalyticsService } from '../usage/analytics.service' import { CacheService } from './cache.service' import { SchemaService } from './schema.service' +import { Subject } from 'rxjs' +import { debounceTime } from 'rxjs/operators' @Injectable() export class KafkaService { @@ -31,11 +38,17 @@ export class KafkaService { private KAFKA_CLIENT_URL: string private isCacheSending: boolean - private topics: string[] = null + private topics: string[] = [] private lastTopicFetch: number = 0 private TOPIC_CACHE_VALIDITY = KafkaService.DEFAULT_TOPIC_CACHE_VALIDITY HTTP_ERROR = 'HttpErrorResponse' + eventCallback = new Subject() // Source + eventCallback$ = this.eventCallback.asObservable() // Stream + private progressSubject = new Subject(); + progress = 0 + cacheSize = 0 + constructor( private storage: StorageService, private cache: CacheService, @@ -48,6 +61,11 @@ export class KafkaService { ) { this.updateURI() this.readTopicCacheValidity() + this.progressSubject + .pipe(debounceTime(2000)) + .subscribe((progress) => { + this.eventCallback.next(progress); + }); } init() { @@ -66,9 +84,7 @@ export class KafkaService { readTopicCacheValidity() { return this.storage.get(StorageKeys.TOPIC_CACHE_TIMEOUT).then(timeout => { - if (typeof timeout === 'number') { - this.TOPIC_CACHE_VALIDITY = timeout - } + if (typeof timeout === 'number') this.TOPIC_CACHE_VALIDITY = timeout }) } @@ -128,106 +144,79 @@ export class KafkaService { prepareKafkaObjectAndStore(type, payload) { const name = type == SchemaType.ASSESSMENT ? payload.metadata.name : type const value = this.schema.getKafkaObjectValue(type, payload) - const kafkaObject: KafkaObject = { value } const cacheValue: CacheValue = { - kafkaObject, + kafkaObject: { value }, name, avsc: payload.metadata ? payload.metadata.avsc : this.DEFAULT_KAFKA_AVSC } this.sendDataEvent( DataEventType.PREPARED_OBJECT, name, - kafkaObject.value.name, - kafkaObject.value.timestamp + value['name'], + value['timestamp'] ) - return this.cache.storeInCache(type, kafkaObject, cacheValue) + return this.cache.storeInCache(type, value, cacheValue) } sendAllFromCache(): Promise { - let successKeys = [] - let failedKeys = [] + let successKeys: string[] = [] + let failedKeys: string[] = [] if (this.isCacheSending) return Promise.resolve([]) - this.cache.setCacheSending(true) + this.setCacheSending(true) return Promise.all([ this.cache.getCache(), - this.getKafkaHeaders(DefaultKafkaRequestContentType) + this.cache.getCacheSize(), + this.getKafkaHeaders(DefaultKafkaRequestContentType), + this.schema.getKafkaObjectKey(), ]) - .then(([cache, headers]) => { - const completeCache = { ...cache } - return this.convertCacheToRecords(completeCache).then(records => { - return Promise.all( - records.map(r => - this.sendToKafka(r.topic, r.record, headers) - .then(() => (successKeys = successKeys.concat(r.cacheKey))) + .then(([cache, size, headers, kafkaKey]) => { + this.progress = 0 + this.cacheSize = size + return Promise.all( + Object.entries(cache) + .filter(([k]) => k) + .map((entry, i) => { + const [k, v] = entry + return this.convertEntryToRecord(kafkaKey, k, v) + .then(r => { + return this.sendToKafka(r.topic, r.record, headers) + }) + .then(() => { + successKeys.push(k) + return this.cache.removeFromCache(k) + }) .catch(e => { - failedKeys = failedKeys.concat(r.cacheKey) + failedKeys.push(k) return this.logger.error( 'Failed to send data from cache to kafka', e ) }) - ) - ) - }) + .finally(() => this.updateProgress(++this.progress, this.cacheSize)) + }) + ) }) - .then(() => - this.cache - .removeFromCache(successKeys) - .then(() => { - this.cache.setCacheSending(false) - return { successKeys, failedKeys } - }) - ) - .catch(e => { - this.cache.setCacheSending(false) - return [this.logger.error('Failed to send all data from cache', e)] + .then(() => { + this.updateProgress(this.cacheSize, this.cacheSize) + this.setCacheSending(false) + return { successKeys, failedKeys } }) } - convertCacheToRecords(cache) { - return this.schema.getKafkaObjectKey().then(key => { - const groupedCache = {} - Object.entries(cache).map(([k, v]: [any, CacheValue]) => { - if (!v || !v.kafkaObject) return - const type = v.name - if (!groupedCache[type]) groupedCache[type] = [] - groupedCache[type].push({ - key, - value: { key: k, value: v.kafkaObject.value } - }) - }) - let allRecords = [] - Object.entries(groupedCache).map(([k, v]: [any, any]) => { - const type = k - return allRecords.push( - this.schema.getKafkaPayload( - type, - v[0].key, - v.map(a => a.value.value), - v.map(a => a.value.key), - this.topics - ) - ) - }) - return Promise.all(allRecords) - }) + convertEntryToRecord(kafkaKey, k, v) { + const type = v.name + return this.schema.getKafkaPayload( + type, + kafkaKey, + v.kafkaObject.value, + k, + this.topics + ) } sendToKafka(topic, record, headers): Promise { const allRecords = record.records - const compressed = pako.gzip(JSON.stringify(record)).buffer - return this.postData( - compressed, - topic, - headers.set('Content-Encoding', DefaultCompressedContentEncoding) - ) - .catch(e => { - if (e.name == this.HTTP_ERROR) { - this.logger.log('Retrying uncompressed..') - return this.postData(record, topic, headers) - } - throw e - }) + return this.postData(JSON.stringify(record), topic, headers) .then(() => this.sendEvent(allRecords[0], DataEventType.SEND_SUCCESS)) .catch(e => { this.sendEvent(allRecords[0], DataEventType.SEND_ERROR, e) @@ -235,22 +224,57 @@ export class KafkaService { }) } + updateProgress(progress, cacheSize) { + const normalizedProgress = progress / cacheSize + this.progressSubject.next(normalizedProgress) + } + sendEvent(record, eventType, error?) { - this.sendDataEvent( - DataEventType.SEND_SUCCESS, - eventType, - record.name ? record.value.name : record.value.questionnaireName, - record.time, - error ? JSON.stringify(error) : '' - ) + if (record && record.value) { + this.sendDataEvent( + DataEventType.SEND_SUCCESS, + eventType, + record.value.name ? record.value.name : record.value.questionnaireName, + record.time, + error ? JSON.stringify(error) : '' + ) + } + } + + private convertHeaders(headers: HttpHeaders): { [key: string]: string } { + const result: { [key: string]: string } = {}; + headers.keys().forEach((key) => { + const values = headers.getAll(key); + if (values && values.length > 0) { + result[key] = values.join(', '); // Join multiple values, if any + } + }); + return result; } - postData(data, topic, headers) { - return this.http - .post(this.KAFKA_CLIENT_URL + this.URI_topics + topic, data, { - headers + postData(data: any, topic: string, headers: HttpHeaders): Promise { + const nativeHeaders = this.convertHeaders(headers); + const request = { + url: `${this.KAFKA_CLIENT_URL}${this.URI_topics}${topic}`, + data: data, + headers: nativeHeaders, + method: 'POST', + }; + + return CapacitorHttp.request(request) + .then(response => { + if (response.status < 200 || response.status >= 300) { + throw new HttpErrorResponse({ + error: response.data, + status: response.status, + }); + } + return response; }) - .toPromise() + .catch(error => { + console.error('HTTP request failed:', error); + throw new Error(`Failed to send data to Kafka: ${error.message}`); + }); } getAccessToken() { diff --git a/src/app/core/services/kafka/schema.service.spec.ts b/src/app/core/services/kafka/schema.service.spec.ts index 533e01aa2..5223742e0 100644 --- a/src/app/core/services/kafka/schema.service.spec.ts +++ b/src/app/core/services/kafka/schema.service.spec.ts @@ -3,6 +3,7 @@ import { TestBed } from '@angular/core/testing' import { ConverterFactoryServiceMock, + KeyConverterServiceMock, LocalizationServiceMock, LogServiceMock, QuestionnaireServiceMock, @@ -19,6 +20,7 @@ import { LocalizationService } from '../misc/localization.service' import { LogService } from '../misc/log.service' import { ConverterFactoryService } from './converters/converter-factory.service.' import { SchemaService } from './schema.service' +import { KeyConverterService } from './converters/key-converter.service' import { StorageService } from '../storage/storage.service' describe('SchemaService', () => { @@ -34,6 +36,7 @@ describe('SchemaService', () => { { provide: LocalizationService, useClass: LocalizationServiceMock }, { provide: SubjectConfigService, useClass: SubjectConfigServiceMock }, { provide: RemoteConfigService, useClass: RemoteConfigServiceMock }, + { provide: KeyConverterService, useClass: KeyConverterServiceMock }, { provide: ConverterFactoryService, useClass: ConverterFactoryServiceMock diff --git a/src/app/core/services/kafka/schema.service.ts b/src/app/core/services/kafka/schema.service.ts index aba8788a5..6973580fb 100644 --- a/src/app/core/services/kafka/schema.service.ts +++ b/src/app/core/services/kafka/schema.service.ts @@ -7,12 +7,14 @@ import { } from '../../../shared/models/kafka' import { SubjectConfigService } from '../config/subject-config.service' import { ConverterFactoryService } from './converters/converter-factory.service.' +import { KeyConverterService } from './converters/key-converter.service' @Injectable() export class SchemaService { constructor( private converterFactory: ConverterFactoryService, - private subjectConfig: SubjectConfigService + private subjectConfig: SubjectConfigService, + public keyConverter: KeyConverterService, ) { } getKafkaObjectKey() { @@ -21,9 +23,7 @@ export class SchemaService { .then( payload => ( - this.converterFactory - .getConverter(SchemaType.KEY) - .processData(payload) + this.keyConverter.processData(payload) ) ) } @@ -35,29 +35,13 @@ export class SchemaService { getKafkaPayload( type, kafkaKey, - kafkaObjects: any[], - cacheKeys: any[], + kafkaObject: any, + cacheKey: string, topics ): Promise { - const valueConverter = this.converterFactory.getConverter(type) - return valueConverter.getKafkaTopic(kafkaObjects[0], topics).then(topic => - valueConverter.getSchemas(topic).then(schema => { - return Promise.all([ - this.converterFactory - .getConverter(SchemaType.KEY) - .convertToRecord(kafkaKey, topic, ''), - valueConverter.batchConvertToRecord(kafkaObjects, topic, schema) - ]).then(([key, records]) => ({ - topic, - cacheKey: cacheKeys, - record: { - key_schema_id: key.schema, - value_schema_id: records[0]['schema'], - records: records.map(r => ({ key: key.value, value: r['value'] })) - } - })) - }) - ) + return this.converterFactory + .getConverter(type) + .getKafkaPayload(type, kafkaKey, kafkaObject, cacheKey, topics) } reset() { diff --git a/src/app/core/services/usage/usage.service.ts b/src/app/core/services/usage/usage.service.ts index cb4b39f10..f70631826 100644 --- a/src/app/core/services/usage/usage.service.ts +++ b/src/app/core/services/usage/usage.service.ts @@ -46,7 +46,7 @@ export class UsageService { return this.sendEventToKafka({ eventType: type, questionnaireName: taskName, - metaData: metadata + metadata: metadata }) } diff --git a/src/app/pages/home/containers/home-page.component.ts b/src/app/pages/home/containers/home-page.component.ts index 0ec03e68c..3297db4af 100755 --- a/src/app/pages/home/containers/home-page.component.ts +++ b/src/app/pages/home/containers/home-page.component.ts @@ -57,10 +57,9 @@ export class HomePageComponent implements OnInit, OnDestroy { private platform: Platform, private usage: UsageService ) { - this.resumeListener = this.platform.resume.subscribe(() => this.onResume()) this.changeDetectionListener = this.tasksService.changeDetectionEmitter.subscribe(() => { - console.log('Changes to task service detected') + console.log('Changes to task service detected..') this.navCtrl.navigateRoot('') }) } @@ -90,7 +89,10 @@ export class HomePageComponent implements OnInit, OnDestroy { } ngOnDestroy() { - this.resumeListener.unsubscribe() + // Unsubscribe to avoid memory leaks when the page is left + if (this.resumeListener) { + this.resumeListener.unsubscribe(); + } this.changeDetectionListener.unsubscribe() } @@ -101,6 +103,14 @@ export class HomePageComponent implements OnInit, OnDestroy { this.sortedTasks = this.tasksService.getValidTasksMap() this.tasks = this.tasksService.getTasksOfToday() this.showCalendar = false + this.resumeListener = this.platform.resume.subscribe(() => this.onResume()) + } + + ionViewWillLeave() { + // Unsubscribe to avoid memory leaks when the page is left + if (this.resumeListener) { + this.resumeListener.unsubscribe(); + } } init() { @@ -200,7 +210,7 @@ export class HomePageComponent implements OnInit, OnDestroy { buttons: [ { text: this.localization.translateKey(LocKeys.BTN_OKAY), - handler: () => {} + handler: () => { } } ] }) @@ -218,7 +228,7 @@ export class HomePageComponent implements OnInit, OnDestroy { buttons: [ { text: this.localization.translateKey(LocKeys.BTN_OKAY), - handler: () => {} + handler: () => { } } ] }) diff --git a/src/app/pages/questions/components/finish/finish.component.html b/src/app/pages/questions/components/finish/finish.component.html index 1e5c15260..5a61f8f66 100755 --- a/src/app/pages/questions/components/finish/finish.component.html +++ b/src/app/pages/questions/components/finish/finish.component.html @@ -14,27 +14,17 @@

{{ content }}

- {{ 'BTN_DONE' | translate }} + {{ innerText }} - -
- Warning - {{ 'WARNING_DO_NOT_CLOSE_APP' | translate }} -
-
- -
-
+ {{ etaText }} {{ ' (' + progressDisplay + '%) ' }}
diff --git a/src/app/pages/questions/components/finish/finish.component.scss b/src/app/pages/questions/components/finish/finish.component.scss index dc25fc777..33e464860 100755 --- a/src/app/pages/questions/components/finish/finish.component.scss +++ b/src/app/pages/questions/components/finish/finish.component.scss @@ -55,3 +55,7 @@ ion-spinner * { left: 0; width: 100%; } + +ion-button { + --background: transparent; +} \ No newline at end of file diff --git a/src/app/pages/questions/components/finish/finish.component.ts b/src/app/pages/questions/components/finish/finish.component.ts index dcc32e59f..04fc7e98b 100755 --- a/src/app/pages/questions/components/finish/finish.component.ts +++ b/src/app/pages/questions/components/finish/finish.component.ts @@ -9,6 +9,9 @@ import { import { UsageService } from '../../../../core/services/usage/usage.service' import { AssessmentType } from '../../../../shared/models/assessment' import { QuestionsService } from '../../services/questions.service' +import { LocalizationService } from 'src/app/core/services/misc/localization.service' +import { LocKeys } from 'src/app/shared/enums/localisations' +import { getMinutes } from 'src/app/shared/utilities/time' @Component({ selector: 'finish', @@ -32,32 +35,44 @@ export class FinishComponent implements OnChanges { task @Input() questions + @Input() + progressCount @Output() exit: EventEmitter = new EventEmitter() + innerText = '' displayNextTaskReminder = true completedInClinic = false + shadowStyle = 'inset 100px 0 0 -50px #0B4A59' + progressDisplay = 0 + startTime = Date.now() + etaText = '' constructor( private usage: UsageService, - private questionsService: QuestionsService - ) {} + private localization: LocalizationService + ) { } ngOnChanges() { - this.displayNextTaskReminder = - this.taskType == AssessmentType.SCHEDULED && !this.isLastTask if (this.isShown) { - this.onQuestionnaireCompleted() this.usage.setPage(this.constructor.name) - setTimeout(() => (this.showDoneButton = true), 10000) } - } - onQuestionnaireCompleted() { - return this.questionsService.processCompletedQuestionnaire( - this.task, - this.questions + this.showDoneButton = this.progressCount >= 1 + + this.displayNextTaskReminder = + this.taskType == AssessmentType.SCHEDULED && !this.isLastTask + + this.innerText = this.getFinishButtonText(this.progressCount) + this.shadowStyle = this.getProgressBarStyle(this.progressCount) + + // Ensure progress is within a valid range for displaying ETA + this.progressDisplay = Math.min( + Math.max(Math.ceil(this.progressCount * 100), 1), + 99 ) + + this.etaText = this.getEtaText(this.progressDisplay) } handleClosePage() { @@ -67,4 +82,33 @@ export class FinishComponent implements OnChanges { toggleChanged(event) { this.completedInClinic = event } + + getEtaText(progress) { + if (progress <= 0) { + return 'Calculating time remaining...'; + } + + const elapsedTime = (Date.now() - this.startTime) / 1000; // Convert milliseconds to seconds + const remainingTime = (elapsedTime * (100 - progress)) / progress; + + if (remainingTime >= 60) { + const minutes = Math.floor(remainingTime / 60); + const seconds = Math.round(remainingTime % 60); + return `About ${minutes} minute${minutes > 1 ? 's' : ''} and ${seconds} second${seconds !== 1 ? 's' : ''} remaining`; + } + + return `About ${remainingTime.toFixed(0)} second${remainingTime.toFixed(0) !== '1' ? 's' : ''} remaining`; + } + + getProgressBarStyle(progress) { + return progress >= 1 + ? `inset 500px 0 0 -50px var(--cl-primary-60)` + : `inset ${progress * 400}px 0 0 -50px var(--cl-primary-60)` + } + + getFinishButtonText(progress) { + return progress < 1 + ? this.localization.translateKey(LocKeys.SETTINGS_WAIT_ALERT) + '...' + : this.localization.translateKey(LocKeys.BTN_DONE) + } } diff --git a/src/app/pages/questions/components/question/health-input/health-input.component.html b/src/app/pages/questions/components/question/health-input/health-input.component.html index cfa6447f1..1887ee9af 100644 --- a/src/app/pages/questions/components/question/health-input/health-input.component.html +++ b/src/app/pages/questions/components/question/health-input/health-input.component.html @@ -1,23 +1,2 @@ - -
- - - The device doesn't support Healthkit. - - - {{ health_display_time }} - -
diff --git a/src/app/pages/questions/components/question/health-input/health-input.component.ts b/src/app/pages/questions/components/question/health-input/health-input.component.ts index 0a4b318fd..ee5ae07da 100644 --- a/src/app/pages/questions/components/question/health-input/health-input.component.ts +++ b/src/app/pages/questions/components/question/health-input/health-input.component.ts @@ -1,5 +1,11 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' -import { Health_Requirement, Question } from 'src/app/shared/models/question' +import { + Component, + EventEmitter, + Input, + OnChanges, + Output +} from '@angular/core' +import { Question } from 'src/app/shared/models/question' import { Response } from '../../../../../shared/models/question' import { HealthkitService } from '../../../services/healthkit.service' @@ -9,15 +15,17 @@ import { HealthkitService } from '../../../services/healthkit.service' templateUrl: 'health-input.component.html', styleUrls: ['health-input.component.scss'] }) -export class HealthInputComponent implements OnInit { +export class HealthInputComponent implements OnChanges { @Output() valueChange: EventEmitter = new EventEmitter() - @Input() responses: Response[] - @Input() health_question: Question + @Input() + currentlyShown: boolean + @Input() + refTimestamp: number health_display: string health_display_time: string @@ -25,24 +33,29 @@ export class HealthInputComponent implements OnInit { constructor(private healthKitService: HealthkitService) {} - ngOnInit() { - this.loadData() + ngOnChanges() { + if (this.currentlyShown) { + this.loadData() + } } loadData() { let healthDataType = this.health_question.field_name - if (this.health_question.field_name.includes('blood_pressure')) - healthDataType = 'blood_pressure' - this.healthKitService.checkHealthkitSupported().then(() => { - this.isSupported = true - if (this.isSupported) { - this.health_display_time = new Date().toLocaleDateString() - this.health_display = 'Loading..' - this.healthKitService.loadData(healthDataType).then(data => { - this.health_display = data.length + ' records' - return this.valueChange.emit(data) - }) - } - }).catch(e => this.isSupported = false) + this.healthKitService + .checkHealthkitSupported() + .then(() => { + this.isSupported = true + if (this.isSupported) { + this.health_display_time = new Date().toLocaleDateString() + this.health_display = 'Loading..' + this.healthKitService + .loadData(healthDataType, new Date(this.refTimestamp)) + .then(data => { + this.health_display = 'Loaded records' + return this.valueChange.emit(data) + }) + } + }) + .catch(e => (this.isSupported = false)) } -} \ No newline at end of file +} diff --git a/src/app/pages/questions/components/question/question.component.html b/src/app/pages/questions/components/question/question.component.html index 8a48755ec..af9bbbe3d 100755 --- a/src/app/pages/questions/components/question/question.component.html +++ b/src/app/pages/questions/components/question/question.component.html @@ -54,9 +54,11 @@

diff --git a/src/app/pages/questions/components/question/question.component.ts b/src/app/pages/questions/components/question/question.component.ts index 816343d26..5430da547 100755 --- a/src/app/pages/questions/components/question/question.component.ts +++ b/src/app/pages/questions/components/question/question.component.ts @@ -8,7 +8,6 @@ import { Output, ViewChild } from '@angular/core' -import * as smoothscroll from 'smoothscroll-polyfill' import { KeyboardEventType, @@ -98,7 +97,6 @@ export class QuestionComponent implements OnInit, OnChanges { ]) constructor() { - smoothscroll.polyfill() this.value = null } diff --git a/src/app/pages/questions/containers/questions-page.component.html b/src/app/pages/questions/containers/questions-page.component.html index 2637e1694..1f49879ba 100755 --- a/src/app/pages/questions/containers/questions-page.component.html +++ b/src/app/pages/questions/containers/questions-page.component.html @@ -1,7 +1,7 @@
- + - + diff --git a/src/app/pages/questions/containers/questions-page.component.spec.ts b/src/app/pages/questions/containers/questions-page.component.spec.ts index cdad3c1da..75de5a89f 100644 --- a/src/app/pages/questions/containers/questions-page.component.spec.ts +++ b/src/app/pages/questions/containers/questions-page.component.spec.ts @@ -50,6 +50,10 @@ export class QuestionsServiceMock { return Promise.resolve({}) } + getProgress() { + return 1 + } + initRemoteConfigParams() { return Promise.resolve({}) } diff --git a/src/app/pages/questions/containers/questions-page.component.ts b/src/app/pages/questions/containers/questions-page.component.ts index 394c57e25..95607e1b8 100644 --- a/src/app/pages/questions/containers/questions-page.component.ts +++ b/src/app/pages/questions/containers/questions-page.component.ts @@ -2,7 +2,7 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' import { Router } from '@angular/router' import { KeepAwake } from '@capacitor-community/keep-awake' import { NavController, Platform } from '@ionic/angular' -import { Subscription } from 'rxjs' +import { Observable, Subscription } from 'rxjs' import { AlertService } from '../../../core/services/misc/alert.service' import { LocalizationService } from '../../../core/services/misc/localization.service' @@ -62,6 +62,7 @@ export class QuestionsPageComponent implements OnInit { showFinishAndLaunchScreen: boolean = false externalAppCanLaunch: boolean = false viewEntered = false + progressCount$: Observable SHOW_INTRODUCTION_SET: Set = new Set([ true, @@ -69,7 +70,7 @@ export class QuestionsPageComponent implements OnInit { ShowIntroductionType.ONCE ]) MATRIX_FIELD_NAME = 'matrix' - HEALTH_FIELD_NAME = 'health' + HEALTH_FIELD_NAME = 'healthkit' MATRIX_INPUT_SET: Set = new Set([ QuestionType.matrix_radio, QuestionType.healthkit, @@ -94,6 +95,7 @@ export class QuestionsPageComponent implements OnInit { this.sendCompletionLog() navigator['app'].exitApp() }) + this.progressCount$ = this.questionsService.getProgress() } ionViewDidLeave() { @@ -163,7 +165,6 @@ export class QuestionsPageComponent implements OnInit { : q.field_name const entry = groupedQuestions.get(key) ? groupedQuestions.get(key) : [] entry.push(q) - //? groupedQuestions.set(key, entry) }) @@ -182,13 +183,8 @@ export class QuestionsPageComponent implements OnInit { } else this.exitQuestionnaire() } - handleFinish(completedInClinic?: boolean) { - return this.questionsService - .handleClinicalFollowUp(this.assessment, completedInClinic) - .then(() => { - this.updateDoneButton(false) - return this.navCtrl.navigateRoot('/home') - }) + handleFinish() { + this.navCtrl.navigateRoot('/home') } onAnswer(event) { @@ -362,8 +358,15 @@ export class QuestionsPageComponent implements OnInit { } } - updateDoneButton(val: boolean) { - this.showDoneButton = val + onSlideFinish() { + this.onQuestionnaireCompleted() + } + + onQuestionnaireCompleted() { + return this.questionsService.processCompletedQuestionnaire( + this.task, + this.questions + ) } sendEvent(type) { diff --git a/src/app/pages/questions/questions.module.ts b/src/app/pages/questions/questions.module.ts index 9decd6964..d32eb6fcd 100644 --- a/src/app/pages/questions/questions.module.ts +++ b/src/app/pages/questions/questions.module.ts @@ -15,9 +15,10 @@ import { QuestionsPageComponent } from './containers/questions-page.component' import { AnswerService } from './services/answer.service' import { AppLauncherService } from './services/app-launcher.service' import { AudioRecordService } from './services/audio-record.service' -import { FinishTaskService } from './services/finish-task.service' import { QuestionsService } from './services/questions.service' import { TimestampService } from './services/timestamp.service' +import { DefaultQuestionnaireProcessorService } from './services/questionnaire-processor/default-questionnaire-processor.service' +import { HealthQuestionnaireProcessorService } from './services/questionnaire-processor/health-questionnaire-processor.service' const routes: Routes = [ { @@ -47,7 +48,8 @@ const routes: Routes = [ AudioRecordService, TimestampService, QuestionsService, - FinishTaskService, + DefaultQuestionnaireProcessorService, + HealthQuestionnaireProcessorService, AppLauncherService ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/src/app/pages/questions/services/finish-task.service.ts b/src/app/pages/questions/services/finish-task.service.ts deleted file mode 100644 index 21c4091e1..000000000 --- a/src/app/pages/questions/services/finish-task.service.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Injectable } from '@angular/core' -import { - HealthKitDataTypeKey, - HealthkitStringDataType -} from 'src/app/shared/models/health' - -import { ConfigService } from '../../../core/services/config/config.service' -import { KafkaService } from '../../../core/services/kafka/kafka.service' -import { ScheduleService } from '../../../core/services/schedule/schedule.service' -import { AssessmentType } from '../../../shared/models/assessment' -import { SchemaType } from '../../../shared/models/kafka' - -@Injectable({ - providedIn: 'root' -}) -export class FinishTaskService { - constructor( - private schedule: ScheduleService, - private kafka: KafkaService, - private config: ConfigService - ) {} - - processCompletedQuestionnaire(data, task, assessmentMetadata) { - // temporarily change both to healthkit - const type = task.name.toLowerCase().includes('health') - ? SchemaType.HEALTHKIT - : SchemaType.ASSESSMENT - return Promise.all([ - this.updateTaskToComplete(task), - !task.isDemo - ? this.kafka.prepareKafkaObjectAndStore(type, { - task, - data, - metadata: assessmentMetadata - }) - : [], - this.kafka - .prepareKafkaObjectAndStore(SchemaType.TIMEZONE, {}) - .then(() => this.kafka.sendAllFromCache()), - this.cancelNotificationsForCompletedTask(task) - ]) - } - - updateTaskToComplete(task): Promise { - return Promise.all([ - this.schedule - .updateTaskToComplete(task) - .then(res => this.schedule.updateTaskToReportedCompletion(task)), - task.type == AssessmentType.SCHEDULED - ? this.schedule.addToCompletedTasks(task) - : Promise.resolve() - ]) - } - - createClinicalFollowUpTask(assessment): Promise { - return this.schedule - .generateSingleAssessmentTask( - assessment, - AssessmentType.CLINICAL, - Date.now() - ) - .then(() => this.config.rescheduleNotifications()) - } - // TODO process for general questionnaire schema - - cancelNotificationsForCompletedTask(task): Promise { - console.log('Cancelling pending reminders for task..') - const notifications = task.notifications ? task.notifications : [] - return notifications.forEach(n => this.config.cancelSingleNotification(n)) - } -} diff --git a/src/app/pages/questions/services/healthkit.service.ts b/src/app/pages/questions/services/healthkit.service.ts index 284d5bbdc..155a37921 100644 --- a/src/app/pages/questions/services/healthkit.service.ts +++ b/src/app/pages/questions/services/healthkit.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core' -import { Platform } from '@ionic/angular' import { StorageService } from 'src/app/core/services/storage/storage.service' import { StorageKeys } from 'src/app/shared/enums/storage' import { @@ -7,46 +6,53 @@ import { setDateTimeToMidnight, setDateTimeToMidnightEpoch } from 'src/app/shared/utilities/time' -import { - ActivityData, - CapacitorHealthkit, - OtherData, - QueryOutput, - SampleNames, - SleepData -} from '@perfood/capacitor-healthkit' -import { LogService } from '../../../core/services/misc/log.service' +import { CapacitorHealthkit } from '@perfood/capacitor-healthkit' +import { DefaultHealthkitInterval, DefaultHealthkitPermissions } from 'src/assets/data/defaultConfig' +import { RemoteConfigService } from 'src/app/core/services/config/remote-config.service' +import { ConfigKeys } from 'src/app/shared/enums/config' +import { HealthkitPermissionMap } from 'src/app/shared/models/health' +import { Utility } from 'src/app/shared/utilities/util' -declare var Media: any // stops errors w/ cordova-plugin-media-with-compression types @Injectable({ providedIn: 'root' }) export class HealthkitService { - health_value: any - health_display: any - health_display_time: any - health_time: any - - notSupported = false // The interval days for first query - DEFAULT_LOOKBACK_INTERVAL = 30 - MIN_POLL_TIMESTAMP = new Date( - new Date().getTime() - this.DEFAULT_LOOKBACK_INTERVAL * 24 * 60 * 60 * 1000 - ) - MAX_HOURLY_RECORD_LIMIT = 500 + HEALTHKIT_INTERVAL_DAYS = String(DefaultHealthkitInterval) + HEALTHKIT_PERMISSIONS = DefaultHealthkitPermissions + DELIMITER = ',' + queryProgress = 0 constructor( - private storage: StorageService + private storage: StorageService, + private remoteConfig: RemoteConfigService, + private util: Utility ) { - this.initLastPollTimes() + this.init() } - initLastPollTimes() { + init() { + this.remoteConfig.read().then(config => { + config + .getOrDefault( + ConfigKeys.HEALTHKIT_LOOKBACK_INTERVAL_DAYS, + String(DefaultHealthkitInterval) + ) + .then(interval => + (this.HEALTHKIT_INTERVAL_DAYS = interval) + ) + config + .getOrDefault( + ConfigKeys.HEALTHKIT_PERMISSIONS, + DefaultHealthkitPermissions.toString() + ) + .then(permissions => + (this.HEALTHKIT_PERMISSIONS = this.util.stringToArray(permissions, this.DELIMITER)) + ) + }) return this.getLastPollTimes().then(dic => { - if (!dic) { - return this.setLastPollTimes({}) - } + if (!dic) return this.setLastPollTimes({}) }) } @@ -62,58 +68,43 @@ export class HealthkitService { return CapacitorHealthkit.isAvailable() } - loadData(healthDataType) { - return this.getLastPollTimes().then(dic => { - let lastPollTime = this.MIN_POLL_TIMESTAMP - if (healthDataType in dic) lastPollTime = dic[healthDataType] - return CapacitorHealthkit - .requestAuthorization( - { - all: [''], - read: [healthDataType], //read only permission - write: [''], - } - ) - .then(() => { - const endDate = new Date() - return this.query(lastPollTime, endDate, healthDataType).then(res => { - if (res.length) { - const lastDataDate = new Date(res[res.length - 1].endDate) - dic[healthDataType] = lastDataDate - this.setLastPollTimes(dic) - } - return res - }) - }) - .catch(e => { - console.log(e) - return null - }) - }) + loadData(dataType, startTime) { + return CapacitorHealthkit + .requestAuthorization( + { + all: [''], + read: this.HEALTHKIT_PERMISSIONS, + write: [''], + } + ) + .then(() => { + const endTime = new Date( + startTime.getTime() + getMilliseconds({ days: Number(this.HEALTHKIT_INTERVAL_DAYS) })) + return { startTime: startTime, endTime: endTime } + }) + .catch(e => { + console.log(e) + return null + }) } async query(queryStartTime: Date, queryEndTime: Date, dataType: string) { - let startTime = setDateTimeToMidnightEpoch(queryStartTime) - let endTime = startTime + getMilliseconds({ hours: 1 }) - let completeData = [] - while (endTime < queryEndTime.getTime()) { + try { + let startTime = setDateTimeToMidnightEpoch(queryStartTime) + let endTime = setDateTimeToMidnight(queryEndTime) const queryOptions = { sampleName: dataType, startDate: new Date(startTime).toISOString(), endDate: new Date(endTime).toISOString(), - limit: this.MAX_HOURLY_RECORD_LIMIT, - }; - await CapacitorHealthkit.queryHKitSampleType(queryOptions) - .then(res => { - return (completeData = completeData.concat(res)) - }) - startTime = endTime - endTime = endTime + getMilliseconds({ hours: 1 }) + limit: 0 // This is to get all the data + } + return (await CapacitorHealthkit.queryHKitSampleType(queryOptions)).resultData + } catch (e) { + return [] } - return completeData } reset() { - return this.setLastPollTimes({}) + return Promise.resolve() } } diff --git a/src/app/pages/questions/services/questionnaire-processor/default-questionnaire-processor.service.ts b/src/app/pages/questions/services/questionnaire-processor/default-questionnaire-processor.service.ts new file mode 100644 index 000000000..907fc389b --- /dev/null +++ b/src/app/pages/questions/services/questionnaire-processor/default-questionnaire-processor.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core' + +import { ConfigService } from '../../../../core/services/config/config.service' +import { KafkaService } from '../../../../core/services/kafka/kafka.service' +import { ScheduleService } from '../../../../core/services/schedule/schedule.service' +import { AssessmentType } from '../../../../shared/models/assessment' +import { SchemaType } from '../../../../shared/models/kafka' +import { QuestionnaireProcessorService } from './questionnaire-processor.service' + +@Injectable({ + providedIn: 'root' +}) +export class DefaultQuestionnaireProcessorService extends QuestionnaireProcessorService { + constructor( + schedule: ScheduleService, + kafka: KafkaService, + ) { + super(schedule, kafka) + } + + process(data, task, assessmentMetadata) { + const type = SchemaType.ASSESSMENT + return Promise.all([ + this.updateTaskToComplete(task), + !task.isDemo + ? this.kafka.prepareKafkaObjectAndStore(type, { + task, + data, + metadata: assessmentMetadata + }) + : [], + this.kafka + .prepareKafkaObjectAndStore(SchemaType.TIMEZONE, {}) + .then(() => this.kafka.sendAllFromCache()) + ]) + } +} diff --git a/src/app/pages/questions/services/questionnaire-processor/health-questionnaire-processor.service.ts b/src/app/pages/questions/services/questionnaire-processor/health-questionnaire-processor.service.ts new file mode 100644 index 000000000..435498d45 --- /dev/null +++ b/src/app/pages/questions/services/questionnaire-processor/health-questionnaire-processor.service.ts @@ -0,0 +1,73 @@ +import { Injectable } from '@angular/core' + +import { ConfigService } from '../../../../core/services/config/config.service' +import { KafkaService } from '../../../../core/services/kafka/kafka.service' +import { ScheduleService } from '../../../../core/services/schedule/schedule.service' +import { AssessmentType } from '../../../../shared/models/assessment' +import { SchemaType } from '../../../../shared/models/kafka' +import { HealthkitDataType, HealthkitFloatDataTypes, HealthkitStringDataTypes } from '../../../../shared/models/health' +import { getMilliseconds } from 'src/app/shared/utilities/time' +import { QuestionnaireProcessorService } from './questionnaire-processor.service' + +@Injectable({ + providedIn: 'root' +}) +export class HealthQuestionnaireProcessorService extends QuestionnaireProcessorService { + constructor( + schedule: ScheduleService, + kafka: KafkaService + ) { + super(schedule, kafka) + } + HEALTHKIT_QUERY_INTERVAL = 100 + + process(data, task, assessmentMetadata) { + const type = SchemaType.HEALTHKIT + this.updateTaskToComplete(task) + const dividedObjects = [] + Object.entries(data.answers) + .filter(([key, _]) => this.isValidDataType(key as HealthkitDataType)) + .forEach(([key, value]) => { + const startTime = value['startTime'] + const endTime = value['endTime'] + const durationInDays = this.calculateDurationInDays(startTime, endTime) + if (durationInDays <= this.HEALTHKIT_QUERY_INTERVAL) { + dividedObjects.push({ + time: data.time, + timeCompleted: data.timeCompleted, + key, + value + }) + } else { + const numberOfObjects = Math.ceil(durationInDays / this.HEALTHKIT_QUERY_INTERVAL) + const interval = durationInDays / numberOfObjects + let currentStartTime = startTime.getTime() + + for (let i = 0; i < numberOfObjects; i++) { + const currentEndTime = new Date(currentStartTime + getMilliseconds({ days: interval })) + const currentValue = { + startTime: new Date(currentStartTime), + endTime: currentEndTime > endTime ? endTime : currentEndTime + } + dividedObjects.push({ + time: data.time, + timeCompleted: data.timeCompleted, + key, + value: currentValue + }) + currentStartTime = currentEndTime.getTime() + } + } + }); + return Promise.all(dividedObjects.map(v => this.kafka.prepareKafkaObjectAndStore(type, v))) + .then(() => this.kafka.sendAllFromCache()) + } + + calculateDurationInDays(startTime, endTime) { + return (endTime.getTime() - startTime.getTime()) / getMilliseconds({ days: 1 }) + } + + isValidDataType(key: HealthkitDataType) { + return HealthkitStringDataTypes.has(key) || HealthkitFloatDataTypes.has(key) + } +} diff --git a/src/app/pages/questions/services/questionnaire-processor/questionnaire-processor.service.ts b/src/app/pages/questions/services/questionnaire-processor/questionnaire-processor.service.ts new file mode 100644 index 000000000..b9681087f --- /dev/null +++ b/src/app/pages/questions/services/questionnaire-processor/questionnaire-processor.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core' + +import { KafkaService } from '../../../../core/services/kafka/kafka.service' +import { ScheduleService } from '../../../../core/services/schedule/schedule.service' +import { AssessmentType } from '../../../../shared/models/assessment' + +@Injectable({ + providedIn: 'root' +}) +export abstract class QuestionnaireProcessorService { + constructor( + private schedule: ScheduleService, + public kafka: KafkaService, + ) { } + + process(data, task, assessmentMetadata) { } + + updateTaskToComplete(task): Promise { + return Promise.all([ + this.schedule + .updateTaskToComplete(task) + .then(res => this.schedule.updateTaskToReportedCompletion(task)), + task.type == AssessmentType.SCHEDULED + ? this.schedule.addToCompletedTasks(task) + : Promise.resolve() + ]) + } + + getProgress() { + return this.kafka.eventCallback$ + } +} diff --git a/src/app/pages/questions/services/questions.service.ts b/src/app/pages/questions/services/questions.service.ts index 07d128427..2f2d85a18 100644 --- a/src/app/pages/questions/services/questions.service.ts +++ b/src/app/pages/questions/services/questions.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core' import { DefaultAutoNextQuestionnaireTypes, + DefaultHealthkitQuestionnaireKey, DefaultShowTaskProgressCount, DefaultSkippableQuestionnaireTypes } from '../../../../assets/data/defaultConfig' @@ -19,8 +20,10 @@ import { parseAndEvalLogic } from '../../../shared/utilities/parsers' import { getSeconds } from '../../../shared/utilities/time' import { Utility } from '../../../shared/utilities/util' import { AnswerService } from './answer.service' -import { FinishTaskService } from './finish-task.service' import { TimestampService } from './timestamp.service' +import { DefaultQuestionnaireProcessorService } from './questionnaire-processor/default-questionnaire-processor.service' +import { HealthQuestionnaireProcessorService } from './questionnaire-processor/health-questionnaire-processor.service' +import { QuestionnaireProcessorService } from './questionnaire-processor/questionnaire-processor.service' @Injectable({ providedIn: 'root' @@ -38,16 +41,20 @@ export class QuestionsService { ) DELIMITER = ',' isProgressCountShown = false + questionnaireProcessor: any constructor( public questionnaire: QuestionnaireService, private answerService: AnswerService, private timestampService: TimestampService, private localization: LocalizationService, - private finish: FinishTaskService, + private defaultQuestionnaireProcessor: DefaultQuestionnaireProcessorService, + private healthProcessor: HealthQuestionnaireProcessorService, private remoteConfig: RemoteConfigService, private util: Utility - ) {} + ) { + this.questionnaireProcessor = this.defaultQuestionnaireProcessor + } initRemoteConfigParams() { return this.remoteConfig @@ -67,11 +74,11 @@ export class QuestionsService { .then(([autoNextSet, skippableSet]) => { if (autoNextSet.length) this.NEXT_BUTTON_AUTOMATIC_SET = new Set( - this.stringToArray(autoNextSet, this.DELIMITER) + this.util.stringToArray(autoNextSet, this.DELIMITER) ) if (skippableSet.length) this.NEXT_BUTTON_ENABLED_SET = new Set( - this.stringToArray(skippableSet, this.DELIMITER) + this.util.stringToArray(skippableSet, this.DELIMITER) ) }) } @@ -79,6 +86,7 @@ export class QuestionsService { reset() { this.answerService.reset() this.timestampService.reset() + this.questionnaireProcessor = this.defaultQuestionnaireProcessor } deleteLastAnswer() { @@ -206,6 +214,10 @@ export class QuestionsService { return Math.ceil((attemptedAnswers.length * 100) / total) } + getProgress() { + return this.questionnaireProcessor.getProgress() + } + recordTimeStamp(question, startTime) { const id = question.field_name this.timestampService.add({ @@ -263,10 +275,11 @@ export class QuestionsService { processCompletedQuestionnaire(task, questions): Promise { const type = task.type + this.initQuestionnaireProcessor(task.name) return this.questionnaire .getAssessmentForTask(type, task) .then(assessment => - this.finish.processCompletedQuestionnaire( + this.questionnaireProcessor.process( this.getData(questions), task, assessment.questionnaire @@ -274,13 +287,12 @@ export class QuestionsService { ) } - handleClinicalFollowUp(assessment, completedInClinic?) { - if (!completedInClinic) return Promise.resolve() - return this.finish.createClinicalFollowUpTask(assessment) - } - - stringToArray(array, delimiter) { - return array.split(delimiter).map(s => s.trim()) + initQuestionnaireProcessor(name) { + if (name.toLowerCase().includes(DefaultHealthkitQuestionnaireKey)) { + this.questionnaireProcessor = this.healthProcessor + } else { + this.questionnaireProcessor = this.defaultQuestionnaireProcessor + } } getIsProgressCountShown() { diff --git a/src/app/shared/enums/config.ts b/src/app/shared/enums/config.ts index 7ef9c5209..11a03063b 100644 --- a/src/app/shared/enums/config.ts +++ b/src/app/shared/enums/config.ts @@ -42,6 +42,9 @@ export class ConfigKeys { static SHOW_TASK_PROGRESS_COUNT = new ConfigKeys('show_task_progress_count') static SHOW_TASK_INFO = new ConfigKeys('show_task_info') + static HEALTHKIT_LOOKBACK_INTERVAL_DAYS = new ConfigKeys('healthkit_lookback_interval_days') + static HEALTHKIT_PERMISSIONS = new ConfigKeys('healthkit_permissions') + static AUDIO_SAMPLING_RATE = new ConfigKeys('audio_sampling_rate') static AUDIO_BIT_RATE = new ConfigKeys('audio_bit_rate') diff --git a/src/app/shared/enums/storage.ts b/src/app/shared/enums/storage.ts index 6ec36584d..91a9f6101 100755 --- a/src/app/shared/enums/storage.ts +++ b/src/app/shared/enums/storage.ts @@ -51,7 +51,6 @@ export class StorageKeys { ) static HEALTH_LAST_POLL_TIMES = new StorageKeys('HEALTH_LAST_POLL_TIMES') - static HEALTHKIT_CACHE = new StorageKeys('HEALTHKIT_CACHE') constructor(public value: string) { } diff --git a/src/app/shared/models/health.ts b/src/app/shared/models/health.ts index 4729df4c5..70d9c249d 100644 --- a/src/app/shared/models/health.ts +++ b/src/app/shared/models/health.ts @@ -1,40 +1,88 @@ -export enum HealthkitFloatDataType { +export enum HealthkitPermission { STAIRS = 'stairs', DISTANCE = 'distance', - APPLE_EXERCISE_TIME = 'appleExerciseTime', - VO2MAX = 'vo2Max', + DURATION = 'duration', ACTIVITY = 'activity', - CALORIES = 'calories' + CALORIES = 'calories', + BLOOD_GLUCOSE = 'bloodGlucose', + WEIGHT = 'weight', + HEART_RATE = 'heartRate', + STEPS = 'steps', } export enum HealthkitDataType { - STAIRS = 'stairs', - DISTANCE = 'distance', + STEP_COUNT = 'stepCount', + FLIGHTS_CLIMBED = 'flightsClimbed', + DISTANCE_WALKING_RUNNING = 'distanceWalkingRunning', + DISTANCE_CYCLING = 'distanceCycling', + ACTIVE_ENERGY_BURNED = 'activeEnergyBurned', + BASAL_ENERGY_BURNED = 'basalEnergyBurned', + HEART_RATE = 'heartRate', APPLE_EXERCISE_TIME = 'appleExerciseTime', - VO2MAX = 'vo2Max', - ACTIVITY = 'activity', - CALORIES = 'calories' + BLOOD_GLUCOSE = 'bloodGlucose', + SLEEP_ANALYSIS = 'sleepAnalysis', + WEIGHT = 'weight', + WORKOUT_TYPE = 'workoutType', + OXYGEN_SATURATION = 'oxygenSaturation', + BLOOD_PRESSURE_SYSTOLIC = 'blooPressureSystolic', + BLOOD_PRESSURE_DIASTOLIC = 'bloodPressureDiastolic', + RESTING_HEART_RATE = 'restingHeartRate', + RESPIRATORY_RATE = 'respiratoryRate' } -export enum HealthkitStringDataType { - SLEEP = 'sleep', - ACTIVITY = 'activity', - GENDER = 'gender', - DATE_OF_BIRTH = 'date_of_birth' +export enum HealthkitTopic { + STEP_COUNT = 'active_apple_healthkit_steps', + FLIGHTS_CLIMBED = 'active_apple_healthkit_stairs', + DISTANCE_WALKING_RUNNING = 'active_apple_healthkit_distance', + DISTANCE_CYCLING = 'active_apple_healthkit_distance', + ACTIVE_ENERGY_BURNED = 'active_apple_healthkit_calories', + BASAL_ENERGY_BURNED = 'active_apple_healthkit_calories', + HEART_RATE = 'active_apple_healthkit_heart_rate', + APPLE_EXERCISE_TIME = 'active_apple_healthkit_exercise_time', + BLOOD_GLUCOSE = 'active_apple_healthkit_blood_glucose', + SLEEP_ANALYSIS = 'active_apple_healthkit_sleep_stage', + WEIGHT = 'active_apple_healthkit_weight', + WORKOUT_TYPE = 'active_apple_healthkit_activity', + OXYGEN_SATURATION = 'active_apple_healthkit_oxygen_saturation', + BLOOD_PRESSURE_SYSTOLIC = 'active_apple_healthkit_blood_pressure', + BLOOD_PRESSURE_DIASTOLIC = 'active_apple_healthkit_blood_pressure', + RESTING_HEART_RATE = 'active_apple_healthkit_heart_rate', + RESPIRATORY_RATE = 'active_apple_healthkit_resp_rate' } +export const HealthkitFloatDataTypes = new Set([ + HealthkitDataType.STEP_COUNT, + HealthkitDataType.FLIGHTS_CLIMBED, + HealthkitDataType.DISTANCE_WALKING_RUNNING, + HealthkitDataType.DISTANCE_CYCLING, + HealthkitDataType.ACTIVE_ENERGY_BURNED, + HealthkitDataType.BASAL_ENERGY_BURNED, + HealthkitDataType.HEART_RATE, + HealthkitDataType.APPLE_EXERCISE_TIME, + HealthkitDataType.BLOOD_GLUCOSE, + HealthkitDataType.WEIGHT, + HealthkitDataType.OXYGEN_SATURATION, + HealthkitDataType.BLOOD_PRESSURE_DIASTOLIC, + HealthkitDataType.BLOOD_PRESSURE_SYSTOLIC, + HealthkitDataType.RESPIRATORY_RATE, + HealthkitDataType.RESTING_HEART_RATE +]) + +export const HealthkitStringDataTypes = new Set([ + HealthkitDataType.SLEEP_ANALYSIS, + HealthkitDataType.WORKOUT_TYPE +]) + export enum HealthKitDataTypeKey { STRING = 'stringValue', FLOAT = 'floatValue', DOUBLE = 'doubleValue' } -export enum HealthkitSchemaType { - ACTIVITY = 'healthkit_activity', - BODY_MEASUREMENT = 'healthkit_body_measurement', - CALORIES = 'healthkit_calories', - HEART_RATE = 'healthkit_heart_rate', - VITAL_SIGNS = 'healthkit_vital_signs' +export enum HealthKitDataKey { + DEFAULT = 'value', + SLEEP_STATE = 'sleepState', + ACTIVITY_TYPE = 'workoutActivityName' } export interface HealthkitValueExport { @@ -50,3 +98,19 @@ export interface HealthkitValueExport { doubleValue: number stringValue: string } + +export const HealthkitPermissionMap = { + [HealthkitDataType.STEP_COUNT]: HealthkitPermission.STEPS, + [HealthkitDataType.FLIGHTS_CLIMBED]: HealthkitPermission.STAIRS, + [HealthkitDataType.DISTANCE_WALKING_RUNNING]: HealthkitPermission.DISTANCE, + [HealthkitDataType.DISTANCE_CYCLING]: HealthkitPermission.DISTANCE, + [HealthkitDataType.ACTIVE_ENERGY_BURNED]: HealthkitPermission.CALORIES, + [HealthkitDataType.BASAL_ENERGY_BURNED]: HealthkitPermission.CALORIES, + [HealthkitDataType.HEART_RATE]: HealthkitPermission.HEART_RATE, + [HealthkitDataType.RESTING_HEART_RATE]: HealthkitPermission.HEART_RATE, + [HealthkitDataType.APPLE_EXERCISE_TIME]: HealthkitPermission.DURATION, + [HealthkitDataType.BLOOD_GLUCOSE]: HealthkitPermission.BLOOD_GLUCOSE, + [HealthkitDataType.SLEEP_ANALYSIS]: HealthkitPermission.ACTIVITY, + [HealthkitDataType.WORKOUT_TYPE]: HealthkitPermission.ACTIVITY, + [HealthkitDataType.WEIGHT]: HealthkitPermission.WEIGHT, +} diff --git a/src/app/shared/models/question.ts b/src/app/shared/models/question.ts index 830d69a60..1f1988f32 100755 --- a/src/app/shared/models/question.ts +++ b/src/app/shared/models/question.ts @@ -58,7 +58,6 @@ export class QuestionType { static yesno = 'yesno' static descriptive = 'descriptive' static matrix_radio = 'matrix-radio' - static health = 'health' static healthkit = 'healthkit' } diff --git a/src/app/shared/testing/mock-services.ts b/src/app/shared/testing/mock-services.ts index ea8085940..589e500d0 100644 --- a/src/app/shared/testing/mock-services.ts +++ b/src/app/shared/testing/mock-services.ts @@ -22,6 +22,16 @@ export class RemoteConfigServiceMock { return new Subject() } } + +export class KeyConverterServiceMock { + getKafkaTopic() { + return Promise.resolve() + } + getSchemas() { + return Promise.resolve() + } +} + export class LogServiceMock { log() {} } diff --git a/src/app/shared/utilities/util.ts b/src/app/shared/utilities/util.ts index dd8140033..b6aad813b 100755 --- a/src/app/shared/utilities/util.ts +++ b/src/app/shared/utilities/util.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core' @Injectable() export class Utility { - constructor() {} + constructor() { } /** * Partition the given array into two parts. @@ -66,4 +66,8 @@ export class Utility { base64ToUnicode(raw: string): string { return decodeURIComponent(escape(atob(raw))) } + + stringToArray(array, delimiter) { + return array.split(delimiter).map(s => s.trim()) + } } diff --git a/src/assets/data/defaultConfig.ts b/src/assets/data/defaultConfig.ts index 3fa082972..30e0c9243 100755 --- a/src/assets/data/defaultConfig.ts +++ b/src/assets/data/defaultConfig.ts @@ -1,4 +1,5 @@ // tslint:disable:max-line-length +import { HealthkitPermission } from 'src/app/shared/models/health' import { LocKeys } from '../../app/shared/enums/localisations' import { AssessmentType } from '../../app/shared/models/assessment' import { QuestionType } from '../../app/shared/models/question' @@ -16,7 +17,7 @@ import { Localisations } from './localisations' export const DefaultPlatformInstance = 'RADAR-CNS' // *Default app version -export const DefaultAppVersion = '3.0.0-alpha' +export const DefaultAppVersion = '3.3.4-alpha' // *Default Android package name export const DefaultPackageName = 'org.phidatalab.radar_armt' @@ -235,7 +236,8 @@ export const DefaultAudioRecordOptions = { // *Default question/question input types where the questionnaire will automatically move to the next question upon answering the question. export const DefaultAutoNextQuestionnaireTypes = [ QuestionType.timed, - QuestionType.audio + QuestionType.audio, + QuestionType.healthkit ] // *Default question/question input types where the next button is enabled by default, allowing the question to be skippable. @@ -311,3 +313,21 @@ export const DefaultPrivacyPolicyUrl = 'https://radar-base.org/actve-app-armt-privacy-policy/' export const DefaultHealthkitTopicPrefix = 'active_apple_healthkit_' + +export const DefaultHealthkitQuestionnaireKey = 'healthkit' + +// *Default Healthkit data permissions to request +export const DefaultHealthkitPermissions = [ + HealthkitPermission.ACTIVITY, + HealthkitPermission.BLOOD_GLUCOSE, + HealthkitPermission.CALORIES, + HealthkitPermission.DISTANCE, + HealthkitPermission.DURATION, + HealthkitPermission.HEART_RATE, + HealthkitPermission.STAIRS, + HealthkitPermission.WEIGHT, + HealthkitPermission.STEPS +] + +// *Default interval to pull Healthkit data until +export const DefaultHealthkitInterval = 3500 // days diff --git a/src/assets/data/localisations.ts b/src/assets/data/localisations.ts index 8420930dd..d4dcbb5e0 100644 --- a/src/assets/data/localisations.ts +++ b/src/assets/data/localisations.ts @@ -991,7 +991,7 @@ export const Localisations = { es: 'Cargando', it: 'Caricamento', nl: 'Laden', - pl: 'Ładowanie…', + pl: 'Ładowanie', hb: 'טוען' }, STATUS_SUCCESS: { diff --git a/src/assets/workers/healthkit-converter.worker.js b/src/assets/workers/healthkit-converter.worker.js new file mode 100644 index 000000000..6db5612bb --- /dev/null +++ b/src/assets/workers/healthkit-converter.worker.js @@ -0,0 +1,30 @@ +/// + +addEventListener('message', ({ data }) => { + const { key, inputData, timeReceived, type, valueKey } = data + + const results = inputData.map(d => + Object.assign( + {}, + { + time: Math.floor(new Date(d.startDate).getTime() / 1000), + endTime: Math.floor(new Date(d.endDate).getTime() / 1000), + timeReceived: timeReceived, + sourceId: d.sourceBundleId, + sourceName: d.device + ? `${d.device.manufacturer} ${d.device.model} ${d.device.hardwareVersion}` + : d.source, + unit: d.unitName ?? '', + key, + intValue: null, + floatValue: null, + doubleValue: null, + stringValue: null + }, + { [type]: d[valueKey] } + ) + ) + + // Post results back to the main thread + postMessage(results) +}) diff --git a/src/global.scss b/src/global.scss index 9e9d5c051..ef083dfe5 100644 --- a/src/global.scss +++ b/src/global.scss @@ -35,6 +35,7 @@ // Application ion-app.md, ion-content { + --padding-top: 16px; --ion-text-color: white; --background: var(--cl-secondary) url('./assets/imgs/bg-mobile.png') no-repeat top center / cover; @@ -178,6 +179,7 @@ ion-loading.custom-loading { width: 312px; ion-button { --ion-color-primary: white; + --border-radius: 5px; --border-color: none; --border-width: 0 !important; } diff --git a/src/polyfills.ts b/src/polyfills.ts index 5634d35cd..aeb6c2de3 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -64,5 +64,6 @@ import './zone-flags' */ (window as any).global = window; -global.Buffer = global.Buffer || require('buffer').Buffer +(window as any).process = { env: { DEBUG: undefined } }; +global.Buffer = global.Buffer || require('buffer').Buffer;