From ad3b5d8e0de30cfcd2818e29e2809ff47ebefada Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 2 Aug 2021 09:09:41 +0200 Subject: [PATCH 01/34] docs: improved documentation of entity schema --- doc/compodoc_sources/concepts/entity-schema-system.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/compodoc_sources/concepts/entity-schema-system.md b/doc/compodoc_sources/concepts/entity-schema-system.md index 5054a5545a..e2dd5c5915 100644 --- a/doc/compodoc_sources/concepts/entity-schema-system.md +++ b/doc/compodoc_sources/concepts/entity-schema-system.md @@ -1,5 +1,10 @@ # Entity Schema ----- +The Entity Schema defines details of the properties of an entity type. +(An "entity" is an object of a certain type that users work with and save to the database, like "Child" or "School") + +We define an entity type and its schema in code through a plain TypeScript class and some custom annotations. +Read more on the background and practical considerations in [How to create a new Entity Type](../how-to-guides/create-a-new-entity-type.html). An example of a schema definition: From 53a44b2cecb0973ee10c7a198b479012f7edc932 Mon Sep 17 00:00:00 2001 From: Simon <33730997+TheSlimvReal@users.noreply.github.com> Date: Mon, 2 Aug 2021 09:39:09 +0200 Subject: [PATCH 02/34] docs: added i18n guides to documentation (#928) --- .../how-to-guides/add-another-language.md | 16 ++++++++-------- .../how-to-guides/work-with-xlf.md | 2 +- doc/compodoc_sources/summary.json | 12 ++++++++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/doc/compodoc_sources/how-to-guides/add-another-language.md b/doc/compodoc_sources/how-to-guides/add-another-language.md index 4781a99048..b301bd18e2 100644 --- a/doc/compodoc_sources/how-to-guides/add-another-language.md +++ b/doc/compodoc_sources/how-to-guides/add-another-language.md @@ -1,10 +1,10 @@ -#How to add another language to the project +# How to add another language to the project ## Abstract This guide depicts the workflow one needs to go through to add another language (such as _hindi_, _bengali_, _french_ e.t.c.) to the project -###1) Find the correct language code +### 1) Find the correct language code You first need the correct ISO-639-2 Language-Code. To find this code for a given language, go to their [website](https://www.loc.gov/standards/iso639-2/php/code_list.php) and find the code that corresponds to your language (look in the `ISO 639-1 Code` column). @@ -16,7 +16,7 @@ in the US (`en-US`), Great-Britain (`en-GB`) or Australia (`en-AU`). A list of available country codes can be found [here](https://www.iso.org/obp/ui/#search/code/). Once you have the language and country code, the resulting code is _language code_-_country code_. -###2) Add the language to the list of known languages +### 2) Add the language to the list of known languages The file [angular.json](angular.json) contains all available languages. In this file, look for the `i18n` section. Add the language code from the last step (possible including the region code) as a key to the `locales` section. Specify the path `src/locale/messages..xlf` as @@ -37,7 +37,7 @@ For example, if you wanted to add the French language, this is what the `i18n` s } ``` -###3) Let xliffmerge know about the new language +### 3) Let xliffmerge know about the new language `xliffmerge` is a tool that helps in the translation process. Especially, it is needed to update the language files while retaining old translations. @@ -51,14 +51,14 @@ Again, for french, this could look like this: ] ``` -###4) Create a localization-file +### 4) Create a localization-file In order to allow the actual translation process to take place, you need to create a standardized file that translators can work with. The standard that we use is `xlf`. To generate a file, simply use the script `extract-i18n` located inside the [package.json](package.json) file. This will automatically generate the needed file if none exists -###5) [Optional] Update the nginx config for the dockerfile +### 5) [Optional] Update the nginx config for the dockerfile We can build the Project using Docker. In order to build the app in every known locale (at least for testing purposes) add the following lines to the nginx config inside the server section. For example, for french: @@ -69,7 +69,7 @@ location /fr/ { } ``` -###6) Test your build +### 6) Test your build In production, all (or a subset of all) available languages are build. However, when testing, you can only use one language to avoid too complex dev builds. You can set the language that you would like to develop in inside the [angular.json](angular.json) file at the section @@ -113,7 +113,7 @@ trans-unit that you have translated. A more detailed overview can be found in Guide [How to edit, update and work with XLF files](work-with-xlf.md). -###Conclusion +### Conclusion You have now successfully added the capability to translate the app into the target language. You can now take the translation file (`"src/locale/messages..xlf"`) and send it to a translator to have it translated. Once this process is done, replace the diff --git a/doc/compodoc_sources/how-to-guides/work-with-xlf.md b/doc/compodoc_sources/how-to-guides/work-with-xlf.md index ebe49058f0..02e2d297f0 100644 --- a/doc/compodoc_sources/how-to-guides/work-with-xlf.md +++ b/doc/compodoc_sources/how-to-guides/work-with-xlf.md @@ -1,4 +1,4 @@ -#How to edit, update and work with XLF files +# How to edit, update and work with XLF files "xlf-files" are the files generated by the `extract-i18n` script. They conform to the [XLIFF Standard](http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html) (Version 1.2) diff --git a/doc/compodoc_sources/summary.json b/doc/compodoc_sources/summary.json index 709a1384b1..5e48207cb1 100644 --- a/doc/compodoc_sources/summary.json +++ b/doc/compodoc_sources/summary.json @@ -80,6 +80,18 @@ { "title": "Create a Report", "file": "how-to-guides/reports.md" + }, + { + "title": "Build Localizable Components", + "file": "how-to-guides/build-localizable-components.md" + }, + { + "title": "Work with XLF", + "file": "how-to-guides/work-with-xlf.md" + }, + { + "title": "Add Another Language", + "file": "how-to-guides/add-another-language.md" } ] }, From 73cdfe8c6299ffc00e2dd92086fc4982e7be67f1 Mon Sep 17 00:00:00 2001 From: Simon <33730997+TheSlimvReal@users.noreply.github.com> Date: Mon, 2 Aug 2021 10:04:36 +0200 Subject: [PATCH 03/34] fix: disable language select works fixes #927 --- src/app/core/ui/ui/ui.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/core/ui/ui/ui.component.ts b/src/app/core/ui/ui/ui.component.ts index 7146cade41..9c29c3431e 100644 --- a/src/app/core/ui/ui/ui.component.ts +++ b/src/app/core/ui/ui/ui.component.ts @@ -72,9 +72,7 @@ export class UiComponent implements OnInit { .subscribe(() => { const uiConfig = this.configService.getConfig("appConfig"); this.logo_path = uiConfig?.logo_path; - if (uiConfig?.displayLanguageSelect === true) { - this.showLanguageSelect = true; - } + this.showLanguageSelect = uiConfig?.displayLanguageSelect === true; }); } From 6ff10f703a5c925661bc8d27a62413175f4468d4 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 2 Aug 2021 13:59:50 +0200 Subject: [PATCH 04/34] fix: better logging for document update conflicts in database --- src/app/core/database/pouch-database.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/core/database/pouch-database.ts b/src/app/core/database/pouch-database.ts index dc952bb050..c26f7af92b 100644 --- a/src/app/core/database/pouch-database.ts +++ b/src/app/core/database/pouch-database.ts @@ -242,6 +242,7 @@ export class PouchDatabase extends Database { return this.put(newObject); } else { existingError.message = existingError.message + " (unable to resolve)"; + existingError.affectedDocument = newObject._id; throw existingError; } } From f52425ceafcf34835b8bd5d45a0fad28120502b2 Mon Sep 17 00:00:00 2001 From: Simon <33730997+TheSlimvReal@users.noreply.github.com> Date: Tue, 3 Aug 2021 21:12:44 +0200 Subject: [PATCH 05/34] refactor: refactor remote session and remove pouchdb-authenticate --- package-lock.json | 1656 ++--------------- package.json | 1 - .../session-service/remote-session.spec.ts | 73 + .../session/session-service/remote-session.ts | 42 +- .../synced-session.service.spec.ts | 6 +- .../session-service/synced-session.service.ts | 6 +- src/app/core/session/session.module.ts | 2 + .../core/session/session.service.provider.ts | 13 +- 8 files changed, 215 insertions(+), 1584 deletions(-) create mode 100644 src/app/core/session/session-service/remote-session.spec.ts diff --git a/package-lock.json b/package-lock.json index 4086cbf076..ef1312e5f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,6 @@ "ngx-markdown": "^11.1.3", "ngx-papaparse": "^5.0.0", "pouchdb-adapter-memory": "^7.2.2", - "pouchdb-authentication": "^1.1.3", "pouchdb-browser": "^7.2.2", "reflect-metadata": "^0.1.13", "reveal": "0.0.4", @@ -6873,6 +6872,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -6909,6 +6909,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, "engines": { "node": ">=0.8" } @@ -7006,7 +7007,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -7029,14 +7031,6 @@ "node": ">= 4.5.0" } }, - "node_modules/attempt-x": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/attempt-x/-/attempt-x-1.1.3.tgz", - "integrity": "sha512-y/+ek8IjxVpTbj/phC87jK5YRhlP5Uu7FlQdCmYuut1DTjNruyrGqUWi5bcX1VKsQX1B0FX16A1hqHomKpHv3A==", - "engines": { - "node": "*" - } - }, "node_modules/autoprefixer": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.4.tgz", @@ -7061,6 +7055,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, "engines": { "node": "*" } @@ -7068,7 +7063,8 @@ "node_modules/aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true }, "node_modules/axios": { "version": "0.21.1", @@ -7671,6 +7667,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } @@ -7843,17 +7840,6 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, - "node_modules/boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dependencies": { - "hoek": "4.x.x" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -8198,14 +8184,6 @@ "node": ">=0.4.0" } }, - "node_modules/buffer-from": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.1.tgz", - "integrity": "sha1-V7GLHaChnsBvM4N6UnWiQjUb114=", - "dependencies": { - "is-array-buffer-x": "^1.0.13" - } - }, "node_modules/buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", @@ -8305,14 +8283,6 @@ "node": ">=0.10.0" } }, - "node_modules/cached-constructors-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-constructors-x/-/cached-constructors-x-1.0.2.tgz", - "integrity": "sha512-7lKwmwXweW6E/31RHAJemLtZPfb2xvcABXknFF4b/dNYv4DbSGTgQHckXLQkNw6BB4HKFYW6mJgsNjADAy1ehw==", - "engines": { - "node": "*" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -8449,7 +8419,8 @@ "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "node_modules/ccount": { "version": "1.1.0", @@ -8878,15 +8849,6 @@ "node": ">=6" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -9002,6 +8964,7 @@ "version": "1.0.8", "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" }, @@ -9926,25 +9889,6 @@ "node": "*" } }, - "node_modules/cryptiles": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz", - "integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==", - "dependencies": { - "boom": "5.x.x" - } - }, - "node_modules/cryptiles/node_modules/boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dependencies": { - "hoek": "4.x.x" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -10377,6 +10321,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -10732,6 +10677,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -11151,6 +11097,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -12058,7 +12005,8 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "node_modules/extend-shallow": { "version": "3.0.2", @@ -12143,6 +12091,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, "engines": [ "node >=0.6.0" ] @@ -12199,7 +12148,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -12567,6 +12517,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, "engines": { "node": "*" } @@ -13052,6 +13003,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, "dependencies": { "assert-plus": "^1.0.0" } @@ -13312,6 +13264,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, "engines": { "node": ">=4" } @@ -13399,46 +13352,15 @@ "node": ">=0.10.0" } }, - "node_modules/has-own-property-x": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/has-own-property-x/-/has-own-property-x-3.2.0.tgz", - "integrity": "sha512-HtRQTYpRFz/YVaQ7jh2mU5iorMAxFcML9FNOLMI1f8VNJ2K0hpOlXoi1a+nmVl6oUcGnhd6zYOFAVe7NUFStyQ==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "to-object-x": "^1.5.0", - "to-property-key-x": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "engines": { - "node": "*" - } - }, "node_modules/has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, "engines": { "node": ">= 0.4" } }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -13646,20 +13568,6 @@ "space-separated-tokens": "^1.0.0" } }, - "node_modules/hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dependencies": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - }, - "engines": { - "node": ">=4.5.0" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13694,14 +13602,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -14181,6 +14081,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -14493,14 +14394,6 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, - "node_modules/infinity-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/infinity-x/-/infinity-x-1.0.2.tgz", - "integrity": "sha512-2Ioz+exrAwlHxFBaDHQIbvUyjKFt0YjIal34/agfzx738aT1zBQwSU5A8Zgb1IQ2r24BtXrkeZZusxE40MyZaQ==", - "engines": { - "node": "*" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -14755,21 +14648,6 @@ "node": ">= 0.4" } }, - "node_modules/is-array-buffer-x": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/is-array-buffer-x/-/is-array-buffer-x-1.7.0.tgz", - "integrity": "sha512-ufSZRMY2WZX5xyNvk0NOZAG7cgi35B/sGQDGqv8w0X7MoQ2GC9vedanJhuYTPaC4PUCqLQsda1w7NF+dPZmAJw==", - "dependencies": { - "attempt-x": "^1.1.0", - "has-to-string-tag-x": "^1.4.1", - "is-object-like-x": "^1.5.1", - "object-get-own-property-descriptor-x": "^3.2.0", - "to-string-tag-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -14878,6 +14756,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -14953,29 +14832,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-falsey-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-falsey-x/-/is-falsey-x-1.0.3.tgz", - "integrity": "sha512-RWjusR6LXAhGa0Vus7aD1rwJuJwdJsvG3daAVMDvOAgvGuGm4eilNgoSuXhpv2/2qpLDvioAKTNb3t3XYidCNg==", - "dependencies": { - "to-boolean-x": "^1.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/is-finite-x": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-finite-x/-/is-finite-x-3.0.4.tgz", - "integrity": "sha512-wdSI5zk/Pl21HzGcLWFoFzuDa8gsgcqhwZGAZryL2eU7RKf7+g+q4jL2gGItrBs/YtspkjOrJ4JxXNZqquoAWA==", - "dependencies": { - "infinity-x": "^1.0.1", - "is-nan-x": "^1.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -14990,32 +14846,6 @@ "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", "dev": true }, - "node_modules/is-function-x": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/is-function-x/-/is-function-x-3.3.0.tgz", - "integrity": "sha512-SreSSU1dlgYaXR5c0mm4qJHKYHIiGiEY+7Cd8/aRLLoMP/VvofD2XcWgBnP833ajpU5XzXbUSpfysnfKZLJFlg==", - "dependencies": { - "attempt-x": "^1.1.1", - "has-to-string-tag-x": "^1.4.1", - "is-falsey-x": "^1.0.1", - "is-primitive": "^2.0.0", - "normalize-space-x": "^3.0.0", - "replace-comments-x": "^2.0.0", - "to-boolean-x": "^1.0.1", - "to-string-tag-x": "^1.4.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/is-function-x/node_modules/is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -15033,21 +14863,6 @@ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", "dev": true }, - "node_modules/is-index-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-index-x/-/is-index-x-1.1.0.tgz", - "integrity": "sha512-qULKLMepQLGC8rSVdi8uF2vI4LiDrU9XSDg1D+Aa657GIB7GV1jHpga7uXgQvkt/cpQ5mVBHUFTpSehYSqT6+A==", - "dependencies": { - "math-clamp-x": "^1.2.0", - "max-safe-integer": "^1.0.1", - "to-integer-x": "^3.0.0", - "to-number-x": "^2.0.0", - "to-string-symbols-supported-x": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -15069,14 +14884,6 @@ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, - "node_modules/is-nan-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-nan-x/-/is-nan-x-1.0.3.tgz", - "integrity": "sha512-WenNBLVGSZID8shogsB++42vF7gvotCfneXM9KMCAKwNPXa8VfAu/RWwpqvnK7dLOP4Z7uitocb0TZ6rAiOccA==", - "engines": { - "node": "*" - } - }, "node_modules/is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -15095,18 +14902,6 @@ "node": ">= 0.4" } }, - "node_modules/is-nil-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/is-nil-x/-/is-nil-x-1.4.2.tgz", - "integrity": "sha512-9aDY7ir7IGb5HlgqL+b38v2YMxf8S7MEHHxjHGzUhijg2crq47RKdxL37bS6dU0VN87wy2IBZP4akgQtIXmyvg==", - "dependencies": { - "lodash.isnull": "^3.0.0", - "validate.io-undefined": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -15139,18 +14934,6 @@ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, - "node_modules/is-object-like-x": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/is-object-like-x/-/is-object-like-x-1.7.1.tgz", - "integrity": "sha512-89nz+kESAW2Y7udq+PdRX/dZnRN2WP1b19Gdv4OYE1Xjoekn1xf31l0ZPzT40qdPD7I2nveNFm9rxxI0vmnGHA==", - "dependencies": { - "is-function-x": "^3.3.0", - "is-primitive": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -15214,14 +14997,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-primitive": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", - "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", @@ -15290,6 +15065,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -15298,6 +15074,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "dependencies": { "has-symbols": "^1.0.1" }, @@ -15308,7 +15085,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "node_modules/is-unc-path": { "version": "1.0.0", @@ -15412,7 +15190,8 @@ "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.0.0", @@ -15841,7 +15620,8 @@ "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true }, "node_modules/jsesc": { "version": "2.5.2", @@ -15877,7 +15657,8 @@ "node_modules/json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -15888,7 +15669,8 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "node_modules/json3": { "version": "3.3.3", @@ -15937,6 +15719,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -16466,19 +16249,6 @@ "source-map": "~0.6.1" } }, - "node_modules/lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lie/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, "node_modules/linebreak": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.0.2.tgz", @@ -17074,11 +16844,6 @@ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "dev": true }, - "node_modules/lodash.isnull": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnull/-/lodash.isnull-3.0.0.tgz", - "integrity": "sha1-+vvlnqHcon7teGU0A53YTC4HxW4=" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -17506,37 +17271,6 @@ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==", "dev": true }, - "node_modules/math-clamp-x": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/math-clamp-x/-/math-clamp-x-1.2.0.tgz", - "integrity": "sha512-tqpjpBcIf9UulApz3EjWXqTZpMlr2vLN9PryC9ghoyCuRmqZaf3JJhPddzgQpJnKLi2QhoFnvKBFtJekAIBSYg==", - "dependencies": { - "to-number-x": "^2.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/math-sign-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/math-sign-x/-/math-sign-x-3.0.0.tgz", - "integrity": "sha512-OzPas41Pn4d16KHnaXmGxxY3/l3zK4OIXtmIwdhgZsxz4FDDcNnbrABYPg2vGfxIkaT9ezGnzDviRH7RfF44jQ==", - "dependencies": { - "is-nan-x": "^1.0.1", - "to-number-x": "^2.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/max-safe-integer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz", - "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -17753,6 +17487,7 @@ "version": "1.46.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -17761,6 +17496,7 @@ "version": "2.1.29", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dev": true, "dependencies": { "mime-db": "1.46.0" }, @@ -18130,14 +17866,6 @@ "dev": true, "optional": true }, - "node_modules/nan-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nan-x/-/nan-x-1.0.2.tgz", - "integrity": "sha512-dndRmy03JQEN+Nh6WjQl7/OstIozeEmrtWe4TE7mEqJ8W8oMD8m2tHjsLPWt//e3hLAeRSbs4pxMyc5pk/nCkQ==", - "engines": { - "node": "*" - } - }, "node_modules/nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -18498,19 +18226,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-space-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-space-x/-/normalize-space-x-3.0.0.tgz", - "integrity": "sha512-tbCJerqZCCHPst4rRKgsTanLf45fjOyeAU5zE3mhDxJtFJKt66q39g2XArWhXelgTFVib8mNBUm6Wrd0LxYcfQ==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "trim-x": "^3.0.0", - "white-space-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -18766,34 +18481,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-get-own-property-descriptor-x": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/object-get-own-property-descriptor-x/-/object-get-own-property-descriptor-x-3.2.0.tgz", - "integrity": "sha512-Z/0fIrptD9YuzN+SNK/1kxAEaBcPQM4gSrtOSMSi9eplnL/AbyQcAyAlreAoAzmBon+DQ1Z+AdhxyQSvav5Fyg==", - "dependencies": { - "attempt-x": "^1.1.0", - "has-own-property-x": "^3.1.1", - "has-symbol-support-x": "^1.4.1", - "is-falsey-x": "^1.0.0", - "is-index-x": "^1.0.0", - "is-primitive": "^2.0.0", - "is-string": "^1.0.4", - "property-is-enumerable-x": "^1.1.0", - "to-object-x": "^1.4.1", - "to-property-key-x": "^2.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/object-get-own-property-descriptor-x/node_modules/is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", @@ -19454,20 +19141,6 @@ "is-hexadecimal": "^1.0.0" } }, - "node_modules/parse-int-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-int-x/-/parse-int-x-2.0.0.tgz", - "integrity": "sha512-NIMm52gmd1+0qxJK8lV3OZ4zzWpRH1xcz9xCHXl+DNzddwUdS4NEtd7BmTeK7iCIXoaK5e6BoDMHgieH2eNIhg==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "nan-x": "^1.0.0", - "to-string-x": "^1.4.2", - "trim-left-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -19713,7 +19386,8 @@ "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, "node_modules/picomatch": { "version": "2.2.2", @@ -20789,164 +20463,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/pouchdb-ajax": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-ajax/-/pouchdb-ajax-6.4.3.tgz", - "integrity": "sha512-3ySZrbEYjbosXShWFLk3xW8prrrUOG8z5aXKy+6lK/nokqdpqGj9NQX/gffy15VcDswbJyQtKpVQRevQlLuAGA==", - "dependencies": { - "buffer-from": "0.1.1", - "pouchdb-binary-utils": "6.4.3", - "pouchdb-errors": "6.4.3", - "pouchdb-promise": "6.4.3", - "pouchdb-utils": "6.4.3", - "request": "2.83.0" - } - }, - "node_modules/pouchdb-ajax/node_modules/ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dependencies": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "node_modules/pouchdb-ajax/node_modules/fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "node_modules/pouchdb-ajax/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/pouchdb-ajax/node_modules/har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dependencies": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pouchdb-ajax/node_modules/json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "node_modules/pouchdb-ajax/node_modules/oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "engines": { - "node": "*" - } - }, - "node_modules/pouchdb-ajax/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "node_modules/pouchdb-ajax/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/pouchdb-ajax/node_modules/request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/pouchdb-ajax/node_modules/tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dependencies": { - "punycode": "^1.4.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/pouchdb-ajax/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/pouchdb-authentication": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pouchdb-authentication/-/pouchdb-authentication-1.1.3.tgz", - "integrity": "sha512-xzxmqAK6+rtJlVcFwebLBDlY0dDD5aqEb+bT0xStFp3s6HPC1QEa9C1NzkBScNBb8UG2BygTrVRMJzJLTR2LrA==", - "dependencies": { - "inherits": "2.0.3", - "pouchdb-ajax": "~6.4.0", - "pouchdb-binary-utils": "~6.4.0", - "pouchdb-promise": "~6.4.0", - "pouchdb-utils": "~6.4.0", - "url-join": "4.0.0", - "url-parse": "1.2.0" - } - }, - "node_modules/pouchdb-authentication/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/pouchdb-binary-utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-6.4.3.tgz", - "integrity": "sha512-eRKH/1eiZwrqNdAR3CL1XIIkq04I9hHIABHwIRboz1LjBSchKmaf4ZDngiWGDvRYT9Gl/MogGDGOk1WRMoV4wg==", - "dependencies": { - "buffer-from": "0.1.1" - } - }, "node_modules/pouchdb-browser": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/pouchdb-browser/-/pouchdb-browser-7.2.2.tgz", @@ -20968,24 +20484,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/pouchdb-collections": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-6.4.3.tgz", - "integrity": "sha512-uWb9+hvjiijeyrCeEz/FUND1oj0AQK/f166egBOTofNlAwQLNrJUTn+uJ34b3NODAmKhg7+ZeDVvnl9D2pijuQ==" - }, - "node_modules/pouchdb-errors": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-6.4.3.tgz", - "integrity": "sha512-EU83ZZJjorwGL9DQZ9HAILY8D+ulX2RYVMtsCfIuzaIJEUrHh/dhSIy5854n42NBOUWug3gFDyO58w5k+64HTQ==", - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/pouchdb-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, "node_modules/pouchdb-json": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/pouchdb-json/-/pouchdb-json-7.2.2.tgz", @@ -21021,47 +20519,6 @@ "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz", "integrity": "sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==" }, - "node_modules/pouchdb-promise": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz", - "integrity": "sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==", - "dependencies": { - "lie": "3.1.1" - } - }, - "node_modules/pouchdb-utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-6.4.3.tgz", - "integrity": "sha512-22QXh743YXl/afheeumrUKsO/0Q4Q8bvoboFp/1quXq//BDJa9nv55WUZX0l05t3VPW+nD/pse2FzU9cs3nEag==", - "dependencies": { - "argsarray": "0.0.1", - "clone-buffer": "1.0.0", - "immediate": "3.0.6", - "inherits": "2.0.3", - "pouchdb-collections": "6.4.3", - "pouchdb-errors": "6.4.3", - "pouchdb-promise": "6.4.3", - "uuid": "3.2.1" - } - }, - "node_modules/pouchdb-utils/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "node_modules/pouchdb-utils/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/pouchdb-utils/node_modules/uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -21222,18 +20679,6 @@ "xtend": "^4.0.0" } }, - "node_modules/property-is-enumerable-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/property-is-enumerable-x/-/property-is-enumerable-x-1.1.0.tgz", - "integrity": "sha512-22cKy3w3OpRswU6to9iKWDDlg+F9vF2REcwGlGW23jyLjHb1U/jJEWA44sWupOnkhGfDgotU6Lw+N2oyhNi+5A==", - "dependencies": { - "to-object-x": "^1.4.1", - "to-property-key-x": "^2.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/protractor": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", @@ -21617,11 +21062,6 @@ "node": ">=0.4.x" } }, - "node_modules/querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -22546,18 +21986,6 @@ "node": ">=0.10" } }, - "node_modules/replace-comments-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-comments-x/-/replace-comments-x-2.0.0.tgz", - "integrity": "sha512-+vMP4jqU+8HboLWms6YMNEiaZG5hh1oR6ENCnGYDF/UQ7aYiJUK/8tcl3+KZAHRCKKa3gqzrfiarlUBHQSgRlg==", - "dependencies": { - "require-coercible-to-string-x": "^1.0.0", - "to-string-x": "^1.4.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -22621,18 +22049,6 @@ "uuid": "bin/uuid" } }, - "node_modules/require-coercible-to-string-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/require-coercible-to-string-x/-/require-coercible-to-string-x-1.0.2.tgz", - "integrity": "sha512-GZ3BSCL0n/zhho8ITganW9FGPh0Kxhq71nCjck8Qau/30Wf4Po8a3XpQdzEMFiXCwZ/0m0E3lKSdSG8gkcIofQ==", - "dependencies": { - "require-object-coercible-x": "^1.4.3", - "to-string-x": "^1.4.5" - }, - "engines": { - "node": "*" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -22647,17 +22063,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "node_modules/require-object-coercible-x": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/require-object-coercible-x/-/require-object-coercible-x-1.4.3.tgz", - "integrity": "sha512-5wEaS+NIiU5HLJQTqBQ+6XHtX7yplUS374j/H/nRDlc7rMWfENqp026jnUHWAOCZ+ekixkXuFHEnTF28oqqVLA==", - "dependencies": { - "is-nil-x": "^1.4.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -22954,7 +22359,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/sane": { "version": "4.1.0", @@ -24126,17 +23532,6 @@ "urix": "^0.1.0" } }, - "node_modules/sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dependencies": { - "hoek": "4.x.x" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/socket.io": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.2.tgz", @@ -24542,6 +23937,7 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -25032,11 +24428,6 @@ "node": ">=4" } }, - "node_modules/stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" - }, "node_modules/strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -25638,14 +25029,6 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "node_modules/to-boolean-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-boolean-x/-/to-boolean-x-1.0.3.tgz", - "integrity": "sha512-kQiMyJUgFprL8J+0CfgJuaSFKJMs3EvFe27/6aj/hVzVZT0HY4aA1QjPldLNxzBmjhLcapp7CctYHuD8QqtS3g==", - "engines": { - "node": "*" - } - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -25654,35 +25037,6 @@ "node": ">=4" } }, - "node_modules/to-integer-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/to-integer-x/-/to-integer-x-3.0.0.tgz", - "integrity": "sha512-794L2Lpwjtynm7RxahJi2YdbRY75gTxUW27TMuN26UgwPkmJb/+HPhkFEFbz+E4vNoiP0dxq5tq5fkXoXLaK/w==", - "dependencies": { - "is-finite-x": "^3.0.2", - "is-nan-x": "^1.0.1", - "math-sign-x": "^3.0.0", - "to-number-x": "^2.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/to-number-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-number-x/-/to-number-x-2.0.0.tgz", - "integrity": "sha512-lGOnCoccUoSzjZ/9Uen8TC4+VFaQcFGhTroWTv2tYWxXgyJV1zqAZ8hEIMkez/Eo790fBMOjidTnQ/OJSCvAoQ==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "nan-x": "^1.0.0", - "parse-int-x": "^2.0.0", - "to-primitive-x": "^1.1.0", - "trim-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -25707,57 +25061,6 @@ "node": ">=0.10.0" } }, - "node_modules/to-object-x": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/to-object-x/-/to-object-x-1.5.0.tgz", - "integrity": "sha512-AKn5GQcdWky+s20vjWkt+Wa6y3dxQH3yQyMBhOfBOPldUwqwhgvlqcIg5H092ntNc+TX8/Cxzs1kMHH19pyCnA==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "require-object-coercible-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/to-primitive-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/to-primitive-x/-/to-primitive-x-1.1.0.tgz", - "integrity": "sha512-gyMY0gi3wjK3e4MUBKqv9Zl8QGcWguIkaUr2VJmoBEsOpDcpDZSEyljR773eVG4maS48uX7muLkoQoh/BA82OQ==", - "dependencies": { - "has-symbol-support-x": "^1.4.1", - "is-date-object": "^1.0.1", - "is-function-x": "^3.2.0", - "is-nil-x": "^1.4.1", - "is-primitive": "^2.0.0", - "is-symbol": "^1.0.1", - "require-object-coercible-x": "^1.4.1", - "validate.io-undefined": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/to-primitive-x/node_modules/is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-property-key-x": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-property-key-x/-/to-property-key-x-2.0.2.tgz", - "integrity": "sha512-YISLpZFYIazNm0P8hLsKEEUEZ3m8U3+eDysJZqTu3+B9tQp+2TrMpaEGT8Agh4fZ5LSoums60/glNEzk5ozqrg==", - "dependencies": { - "has-symbol-support-x": "^1.4.1", - "to-primitive-x": "^1.1.0", - "to-string-x": "^1.4.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -25784,43 +25087,6 @@ "node": ">=8.0" } }, - "node_modules/to-string-symbols-supported-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-string-symbols-supported-x/-/to-string-symbols-supported-x-1.0.2.tgz", - "integrity": "sha512-3MRqhIhSNVDsVAk4M6WNcuBZrAQe54W13xrXX6RzxXS+pA4nj6DQ96RegQS5z9BSNyYbFsBsPvMVDIpP+a/5RA==", - "dependencies": { - "cached-constructors-x": "^1.0.2", - "has-symbol-support-x": "^1.4.2", - "is-symbol": "^1.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/to-string-tag-x": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/to-string-tag-x/-/to-string-tag-x-1.4.3.tgz", - "integrity": "sha512-5+0EZ6dOVt/XArXmkooxPzWxmOR081HM/uXitUow7h11WYg5pPo15uYqDWuqO7ZY+O3Atn/dG26wcJCK+mFevg==", - "dependencies": { - "lodash.isnull": "^3.0.0", - "validate.io-undefined": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/to-string-x": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/to-string-x/-/to-string-x-1.4.5.tgz", - "integrity": "sha512-5xzlZDyDa9BUWNjNzZzHgKQ95PnV7qjvEhbqpFaj1ixaHgfJXOFaa3xdMJ+WLYd4hhaMJaxt8Pt5uKaWXfruXA==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "is-symbol": "^1.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/toggle-selection": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", @@ -25876,50 +25142,12 @@ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", "dev": true }, - "node_modules/trim-left-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-left-x/-/trim-left-x-3.0.0.tgz", - "integrity": "sha512-+m6cqkppI+CxQBTwWEZliOHpOBnCArGyMnS1WCLb6IRgukhTkiQu/TNEN5Lj2eM9jk8ewJsc7WxFZfmwNpRXWQ==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "require-coercible-to-string-x": "^1.0.0", - "white-space-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/trim-right-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-right-x/-/trim-right-x-3.0.0.tgz", - "integrity": "sha512-iIqEsWEbWVodqdixJHi4FoayJkUxhoL4AvSNGp4FF4FfQKRPGizt8++/RnyC9od75y7P/S6EfONoVqP+NddiKA==", - "dependencies": { - "cached-constructors-x": "^1.0.0", - "require-coercible-to-string-x": "^1.0.0", - "white-space-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/trim-trailing-lines": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", "dev": true }, - "node_modules/trim-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-x/-/trim-x-3.0.0.tgz", - "integrity": "sha512-w8s38RAUScQ6t3XqMkS75iz5ZkIYLQpVnv2lp3IuTS36JdlVzC54oe6okOf4Wz3UH4rr3XAb2xR3kR5Xei82fw==", - "dependencies": { - "trim-left-x": "^3.0.0", - "trim-right-x": "^3.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -26647,6 +25875,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -26657,7 +25886,8 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true }, "node_modules/type": { "version": "1.2.0", @@ -27167,11 +26397,6 @@ "querystring": "0.2.0" } }, - "node_modules/url-join": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" - }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -27200,15 +26425,6 @@ "node": ">= 10.13.0" } }, - "node_modules/url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", - "dependencies": { - "querystringify": "~1.0.0", - "requires-port": "~1.0.0" - } - }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", @@ -27310,11 +26526,6 @@ "builtins": "^1.0.3" } }, - "node_modules/validate.io-undefined": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/validate.io-undefined/-/validate.io-undefined-1.0.3.tgz", - "integrity": "sha1-fif8uzFbhB54JDQxiXZxkp4gt/Q=" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -27338,6 +26549,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -29367,14 +28579,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "node_modules/white-space-x": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/white-space-x/-/white-space-x-3.0.1.tgz", - "integrity": "sha512-BwMFXQNPna/4RsNPOgldVYn+FkEv+lc3wUiFzuaW6Z2DH/oSk1UrRD6SBqDgWQO4JU+aBq3PVuPD9Vz0j7mh0w==", - "engines": { - "node": "*" - } - }, "node_modules/wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -35453,6 +34657,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, "requires": { "safer-buffer": "~2.1.0" } @@ -35507,7 +34712,8 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, "assign-symbols": { "version": "1.0.0", @@ -35573,7 +34779,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "at-least-node": { "version": "1.0.0", @@ -35587,11 +34794,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "attempt-x": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/attempt-x/-/attempt-x-1.1.3.tgz", - "integrity": "sha512-y/+ek8IjxVpTbj/phC87jK5YRhlP5Uu7FlQdCmYuut1DTjNruyrGqUWi5bcX1VKsQX1B0FX16A1hqHomKpHv3A==" - }, "autoprefixer": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.4.tgz", @@ -35609,12 +34811,14 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true }, "aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true }, "axios": { "version": "0.21.1", @@ -36178,6 +35382,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, "requires": { "tweetnacl": "^0.14.3" } @@ -36332,14 +35537,6 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.x.x" - } - }, "boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -36646,14 +35843,6 @@ "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", "dev": true }, - "buffer-from": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.1.tgz", - "integrity": "sha1-V7GLHaChnsBvM4N6UnWiQjUb114=", - "requires": { - "is-array-buffer-x": "^1.0.13" - } - }, "buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", @@ -36740,11 +35929,6 @@ } } }, - "cached-constructors-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-constructors-x/-/cached-constructors-x-1.0.2.tgz", - "integrity": "sha512-7lKwmwXweW6E/31RHAJemLtZPfb2xvcABXknFF4b/dNYv4DbSGTgQHckXLQkNw6BB4HKFYW6mJgsNjADAy1ehw==" - }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -36853,7 +36037,8 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "ccount": { "version": "1.1.0", @@ -37202,11 +36387,6 @@ "shallow-clone": "^3.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -37309,6 +36489,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -38100,24 +37281,6 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" }, - "cryptiles": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz", - "integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==", - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.x.x" - } - } - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -38470,6 +37633,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -38754,7 +37918,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "delegate": { "version": "3.2.0", @@ -39116,6 +38281,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -39895,7 +39061,8 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -39963,7 +39130,8 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "faker": { "version": "5.5.3", @@ -40011,7 +39179,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -40337,7 +39506,8 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true }, "fork-ts-checker-webpack-plugin": { "version": "4.1.6", @@ -40730,6 +39900,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -40950,7 +40121,8 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true }, "har-validator": { "version": "5.1.5", @@ -41018,33 +40190,11 @@ } } }, - "has-own-property-x": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/has-own-property-x/-/has-own-property-x-3.2.0.tgz", - "integrity": "sha512-HtRQTYpRFz/YVaQ7jh2mU5iorMAxFcML9FNOLMI1f8VNJ2K0hpOlXoi1a+nmVl6oUcGnhd6zYOFAVe7NUFStyQ==", - "requires": { - "cached-constructors-x": "^1.0.0", - "to-object-x": "^1.5.0", - "to-property-key-x": "^2.0.2" - } - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" - }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "requires": { - "has-symbol-support-x": "^1.4.1" - } + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -41239,17 +40389,6 @@ "space-separated-tokens": "^1.0.0" } }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -41278,11 +40417,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -41689,6 +40823,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -41931,11 +41066,6 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, - "infinity-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/infinity-x/-/infinity-x-1.0.2.tgz", - "integrity": "sha512-2Ioz+exrAwlHxFBaDHQIbvUyjKFt0YjIal34/agfzx738aT1zBQwSU5A8Zgb1IQ2r24BtXrkeZZusxE40MyZaQ==" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -42144,18 +41274,6 @@ "call-bind": "^1.0.0" } }, - "is-array-buffer-x": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/is-array-buffer-x/-/is-array-buffer-x-1.7.0.tgz", - "integrity": "sha512-ufSZRMY2WZX5xyNvk0NOZAG7cgi35B/sGQDGqv8w0X7MoQ2GC9vedanJhuYTPaC4PUCqLQsda1w7NF+dPZmAJw==", - "requires": { - "attempt-x": "^1.1.0", - "has-to-string-tag-x": "^1.4.1", - "is-object-like-x": "^1.5.1", - "object-get-own-property-descriptor-x": "^3.2.0", - "to-string-tag-x": "^1.4.1" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -42247,7 +41365,8 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-decimal": { "version": "1.0.4", @@ -42302,23 +41421,6 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, - "is-falsey-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-falsey-x/-/is-falsey-x-1.0.3.tgz", - "integrity": "sha512-RWjusR6LXAhGa0Vus7aD1rwJuJwdJsvG3daAVMDvOAgvGuGm4eilNgoSuXhpv2/2qpLDvioAKTNb3t3XYidCNg==", - "requires": { - "to-boolean-x": "^1.0.2" - } - }, - "is-finite-x": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-finite-x/-/is-finite-x-3.0.4.tgz", - "integrity": "sha512-wdSI5zk/Pl21HzGcLWFoFzuDa8gsgcqhwZGAZryL2eU7RKf7+g+q4jL2gGItrBs/YtspkjOrJ4JxXNZqquoAWA==", - "requires": { - "infinity-x": "^1.0.1", - "is-nan-x": "^1.0.2" - } - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -42330,28 +41432,6 @@ "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", "dev": true }, - "is-function-x": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/is-function-x/-/is-function-x-3.3.0.tgz", - "integrity": "sha512-SreSSU1dlgYaXR5c0mm4qJHKYHIiGiEY+7Cd8/aRLLoMP/VvofD2XcWgBnP833ajpU5XzXbUSpfysnfKZLJFlg==", - "requires": { - "attempt-x": "^1.1.1", - "has-to-string-tag-x": "^1.4.1", - "is-falsey-x": "^1.0.1", - "is-primitive": "^2.0.0", - "normalize-space-x": "^3.0.0", - "replace-comments-x": "^2.0.0", - "to-boolean-x": "^1.0.1", - "to-string-tag-x": "^1.4.2" - }, - "dependencies": { - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - } - } - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -42366,18 +41446,6 @@ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", "dev": true }, - "is-index-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-index-x/-/is-index-x-1.1.0.tgz", - "integrity": "sha512-qULKLMepQLGC8rSVdi8uF2vI4LiDrU9XSDg1D+Aa657GIB7GV1jHpga7uXgQvkt/cpQ5mVBHUFTpSehYSqT6+A==", - "requires": { - "math-clamp-x": "^1.2.0", - "max-safe-integer": "^1.0.1", - "to-integer-x": "^3.0.0", - "to-number-x": "^2.0.0", - "to-string-symbols-supported-x": "^1.0.0" - } - }, "is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -42396,11 +41464,6 @@ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, - "is-nan-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-nan-x/-/is-nan-x-1.0.3.tgz", - "integrity": "sha512-WenNBLVGSZID8shogsB++42vF7gvotCfneXM9KMCAKwNPXa8VfAu/RWwpqvnK7dLOP4Z7uitocb0TZ6rAiOccA==" - }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -42413,15 +41476,6 @@ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, - "is-nil-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/is-nil-x/-/is-nil-x-1.4.2.tgz", - "integrity": "sha512-9aDY7ir7IGb5HlgqL+b38v2YMxf8S7MEHHxjHGzUhijg2crq47RKdxL37bS6dU0VN87wy2IBZP4akgQtIXmyvg==", - "requires": { - "lodash.isnull": "^3.0.0", - "validate.io-undefined": "^1.0.3" - } - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -42445,15 +41499,6 @@ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, - "is-object-like-x": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/is-object-like-x/-/is-object-like-x-1.7.1.tgz", - "integrity": "sha512-89nz+kESAW2Y7udq+PdRX/dZnRN2WP1b19Gdv4OYE1Xjoekn1xf31l0ZPzT40qdPD7I2nveNFm9rxxI0vmnGHA==", - "requires": { - "is-function-x": "^3.3.0", - "is-primitive": "^3.0.0" - } - }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -42501,11 +41546,6 @@ } } }, - "is-primitive": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", - "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==" - }, "is-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", @@ -42558,12 +41598,14 @@ "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -42571,7 +41613,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-unc-path": { "version": "1.0.0", @@ -42654,7 +41697,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -43000,7 +42044,8 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true }, "jsesc": { "version": "2.5.2", @@ -43027,7 +42072,8 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -43038,7 +42084,8 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "json3": { "version": "3.3.3", @@ -43078,6 +42125,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -43509,21 +42557,6 @@ } } }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "requires": { - "immediate": "~3.0.5" - }, - "dependencies": { - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - } - } - }, "linebreak": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.0.2.tgz", @@ -44012,11 +43045,6 @@ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "dev": true }, - "lodash.isnull": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnull/-/lodash.isnull-3.0.0.tgz", - "integrity": "sha1-+vvlnqHcon7teGU0A53YTC4HxW4=" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -44371,28 +43399,6 @@ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==", "dev": true }, - "math-clamp-x": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/math-clamp-x/-/math-clamp-x-1.2.0.tgz", - "integrity": "sha512-tqpjpBcIf9UulApz3EjWXqTZpMlr2vLN9PryC9ghoyCuRmqZaf3JJhPddzgQpJnKLi2QhoFnvKBFtJekAIBSYg==", - "requires": { - "to-number-x": "^2.0.0" - } - }, - "math-sign-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/math-sign-x/-/math-sign-x-3.0.0.tgz", - "integrity": "sha512-OzPas41Pn4d16KHnaXmGxxY3/l3zK4OIXtmIwdhgZsxz4FDDcNnbrABYPg2vGfxIkaT9ezGnzDviRH7RfF44jQ==", - "requires": { - "is-nan-x": "^1.0.1", - "to-number-x": "^2.0.0" - } - }, - "max-safe-integer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz", - "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA=" - }, "md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -44588,12 +43594,14 @@ "mime-db": { "version": "1.46.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "dev": true }, "mime-types": { "version": "2.1.29", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dev": true, "requires": { "mime-db": "1.46.0" } @@ -44898,11 +43906,6 @@ "dev": true, "optional": true }, - "nan-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nan-x/-/nan-x-1.0.2.tgz", - "integrity": "sha512-dndRmy03JQEN+Nh6WjQl7/OstIozeEmrtWe4TE7mEqJ8W8oMD8m2tHjsLPWt//e3hLAeRSbs4pxMyc5pk/nCkQ==" - }, "nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -45208,16 +44211,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-space-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-space-x/-/normalize-space-x-3.0.0.tgz", - "integrity": "sha512-tbCJerqZCCHPst4rRKgsTanLf45fjOyeAU5zE3mhDxJtFJKt66q39g2XArWhXelgTFVib8mNBUm6Wrd0LxYcfQ==", - "requires": { - "cached-constructors-x": "^1.0.0", - "trim-x": "^3.0.0", - "white-space-x": "^3.0.0" - } - }, "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -45420,30 +44413,6 @@ } } }, - "object-get-own-property-descriptor-x": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/object-get-own-property-descriptor-x/-/object-get-own-property-descriptor-x-3.2.0.tgz", - "integrity": "sha512-Z/0fIrptD9YuzN+SNK/1kxAEaBcPQM4gSrtOSMSi9eplnL/AbyQcAyAlreAoAzmBon+DQ1Z+AdhxyQSvav5Fyg==", - "requires": { - "attempt-x": "^1.1.0", - "has-own-property-x": "^3.1.1", - "has-symbol-support-x": "^1.4.1", - "is-falsey-x": "^1.0.0", - "is-index-x": "^1.0.0", - "is-primitive": "^2.0.0", - "is-string": "^1.0.4", - "property-is-enumerable-x": "^1.1.0", - "to-object-x": "^1.4.1", - "to-property-key-x": "^2.0.1" - }, - "dependencies": { - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - } - } - }, "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", @@ -45988,17 +44957,6 @@ "is-hexadecimal": "^1.0.0" } }, - "parse-int-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-int-x/-/parse-int-x-2.0.0.tgz", - "integrity": "sha512-NIMm52gmd1+0qxJK8lV3OZ4zzWpRH1xcz9xCHXl+DNzddwUdS4NEtd7BmTeK7iCIXoaK5e6BoDMHgieH2eNIhg==", - "requires": { - "cached-constructors-x": "^1.0.0", - "nan-x": "^1.0.0", - "to-string-x": "^1.4.2", - "trim-left-x": "^3.0.0" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -46221,7 +45179,8 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, "picomatch": { "version": "2.2.2", @@ -47041,147 +46000,6 @@ } } }, - "pouchdb-ajax": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-ajax/-/pouchdb-ajax-6.4.3.tgz", - "integrity": "sha512-3ySZrbEYjbosXShWFLk3xW8prrrUOG8z5aXKy+6lK/nokqdpqGj9NQX/gffy15VcDswbJyQtKpVQRevQlLuAGA==", - "requires": { - "buffer-from": "0.1.1", - "pouchdb-binary-utils": "6.4.3", - "pouchdb-errors": "6.4.3", - "pouchdb-promise": "6.4.3", - "pouchdb-utils": "6.4.3", - "request": "2.83.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "requires": { - "punycode": "^1.4.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "pouchdb-authentication": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pouchdb-authentication/-/pouchdb-authentication-1.1.3.tgz", - "integrity": "sha512-xzxmqAK6+rtJlVcFwebLBDlY0dDD5aqEb+bT0xStFp3s6HPC1QEa9C1NzkBScNBb8UG2BygTrVRMJzJLTR2LrA==", - "requires": { - "inherits": "2.0.3", - "pouchdb-ajax": "~6.4.0", - "pouchdb-binary-utils": "~6.4.0", - "pouchdb-promise": "~6.4.0", - "pouchdb-utils": "~6.4.0", - "url-join": "4.0.0", - "url-parse": "1.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "pouchdb-binary-utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-6.4.3.tgz", - "integrity": "sha512-eRKH/1eiZwrqNdAR3CL1XIIkq04I9hHIABHwIRboz1LjBSchKmaf4ZDngiWGDvRYT9Gl/MogGDGOk1WRMoV4wg==", - "requires": { - "buffer-from": "0.1.1" - } - }, "pouchdb-browser": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/pouchdb-browser/-/pouchdb-browser-7.2.2.tgz", @@ -47202,26 +46020,6 @@ } } }, - "pouchdb-collections": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-6.4.3.tgz", - "integrity": "sha512-uWb9+hvjiijeyrCeEz/FUND1oj0AQK/f166egBOTofNlAwQLNrJUTn+uJ34b3NODAmKhg7+ZeDVvnl9D2pijuQ==" - }, - "pouchdb-errors": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-6.4.3.tgz", - "integrity": "sha512-EU83ZZJjorwGL9DQZ9HAILY8D+ulX2RYVMtsCfIuzaIJEUrHh/dhSIy5854n42NBOUWug3gFDyO58w5k+64HTQ==", - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, "pouchdb-json": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/pouchdb-json/-/pouchdb-json-7.2.2.tgz", @@ -47259,46 +46057,6 @@ "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz", "integrity": "sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==" }, - "pouchdb-promise": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz", - "integrity": "sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==", - "requires": { - "lie": "3.1.1" - } - }, - "pouchdb-utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-6.4.3.tgz", - "integrity": "sha512-22QXh743YXl/afheeumrUKsO/0Q4Q8bvoboFp/1quXq//BDJa9nv55WUZX0l05t3VPW+nD/pse2FzU9cs3nEag==", - "requires": { - "argsarray": "0.0.1", - "clone-buffer": "1.0.0", - "immediate": "3.0.6", - "inherits": "2.0.3", - "pouchdb-collections": "6.4.3", - "pouchdb-errors": "6.4.3", - "pouchdb-promise": "6.4.3", - "uuid": "3.2.1" - }, - "dependencies": { - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - } - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -47431,15 +46189,6 @@ "xtend": "^4.0.0" } }, - "property-is-enumerable-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/property-is-enumerable-x/-/property-is-enumerable-x-1.1.0.tgz", - "integrity": "sha512-22cKy3w3OpRswU6to9iKWDDlg+F9vF2REcwGlGW23jyLjHb1U/jJEWA44sWupOnkhGfDgotU6Lw+N2oyhNi+5A==", - "requires": { - "to-object-x": "^1.4.1", - "to-property-key-x": "^2.0.1" - } - }, "protractor": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", @@ -47756,11 +46505,6 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -48612,15 +47356,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "replace-comments-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-comments-x/-/replace-comments-x-2.0.0.tgz", - "integrity": "sha512-+vMP4jqU+8HboLWms6YMNEiaZG5hh1oR6ENCnGYDF/UQ7aYiJUK/8tcl3+KZAHRCKKa3gqzrfiarlUBHQSgRlg==", - "requires": { - "require-coercible-to-string-x": "^1.0.0", - "to-string-x": "^1.4.2" - } - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -48674,15 +47409,6 @@ } } }, - "require-coercible-to-string-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/require-coercible-to-string-x/-/require-coercible-to-string-x-1.0.2.tgz", - "integrity": "sha512-GZ3BSCL0n/zhho8ITganW9FGPh0Kxhq71nCjck8Qau/30Wf4Po8a3XpQdzEMFiXCwZ/0m0E3lKSdSG8gkcIofQ==", - "requires": { - "require-object-coercible-x": "^1.4.3", - "to-string-x": "^1.4.5" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -48694,14 +47420,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "require-object-coercible-x": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/require-object-coercible-x/-/require-object-coercible-x-1.4.3.tgz", - "integrity": "sha512-5wEaS+NIiU5HLJQTqBQ+6XHtX7yplUS374j/H/nRDlc7rMWfENqp026jnUHWAOCZ+ekixkXuFHEnTF28oqqVLA==", - "requires": { - "is-nil-x": "^1.4.2" - } - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -48936,7 +47654,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "sane": { "version": "4.1.0", @@ -49921,14 +48640,6 @@ } } }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.x.x" - } - }, "socket.io": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.2.tgz", @@ -50282,6 +48993,7 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -50696,11 +49408,6 @@ "is-regexp": "^1.0.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -51193,39 +49900,11 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "to-boolean-x": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-boolean-x/-/to-boolean-x-1.0.3.tgz", - "integrity": "sha512-kQiMyJUgFprL8J+0CfgJuaSFKJMs3EvFe27/6aj/hVzVZT0HY4aA1QjPldLNxzBmjhLcapp7CctYHuD8QqtS3g==" - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, - "to-integer-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/to-integer-x/-/to-integer-x-3.0.0.tgz", - "integrity": "sha512-794L2Lpwjtynm7RxahJi2YdbRY75gTxUW27TMuN26UgwPkmJb/+HPhkFEFbz+E4vNoiP0dxq5tq5fkXoXLaK/w==", - "requires": { - "is-finite-x": "^3.0.2", - "is-nan-x": "^1.0.1", - "math-sign-x": "^3.0.0", - "to-number-x": "^2.0.0" - } - }, - "to-number-x": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-number-x/-/to-number-x-2.0.0.tgz", - "integrity": "sha512-lGOnCoccUoSzjZ/9Uen8TC4+VFaQcFGhTroWTv2tYWxXgyJV1zqAZ8hEIMkez/Eo790fBMOjidTnQ/OJSCvAoQ==", - "requires": { - "cached-constructors-x": "^1.0.0", - "nan-x": "^1.0.0", - "parse-int-x": "^2.0.0", - "to-primitive-x": "^1.1.0", - "trim-x": "^3.0.0" - } - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -51246,47 +49925,6 @@ } } }, - "to-object-x": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/to-object-x/-/to-object-x-1.5.0.tgz", - "integrity": "sha512-AKn5GQcdWky+s20vjWkt+Wa6y3dxQH3yQyMBhOfBOPldUwqwhgvlqcIg5H092ntNc+TX8/Cxzs1kMHH19pyCnA==", - "requires": { - "cached-constructors-x": "^1.0.0", - "require-object-coercible-x": "^1.4.1" - } - }, - "to-primitive-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/to-primitive-x/-/to-primitive-x-1.1.0.tgz", - "integrity": "sha512-gyMY0gi3wjK3e4MUBKqv9Zl8QGcWguIkaUr2VJmoBEsOpDcpDZSEyljR773eVG4maS48uX7muLkoQoh/BA82OQ==", - "requires": { - "has-symbol-support-x": "^1.4.1", - "is-date-object": "^1.0.1", - "is-function-x": "^3.2.0", - "is-nil-x": "^1.4.1", - "is-primitive": "^2.0.0", - "is-symbol": "^1.0.1", - "require-object-coercible-x": "^1.4.1", - "validate.io-undefined": "^1.0.3" - }, - "dependencies": { - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - } - } - }, - "to-property-key-x": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-property-key-x/-/to-property-key-x-2.0.2.tgz", - "integrity": "sha512-YISLpZFYIazNm0P8hLsKEEUEZ3m8U3+eDysJZqTu3+B9tQp+2TrMpaEGT8Agh4fZ5LSoums60/glNEzk5ozqrg==", - "requires": { - "has-symbol-support-x": "^1.4.1", - "to-primitive-x": "^1.1.0", - "to-string-x": "^1.4.2" - } - }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -51307,34 +49945,6 @@ "is-number": "^7.0.0" } }, - "to-string-symbols-supported-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-string-symbols-supported-x/-/to-string-symbols-supported-x-1.0.2.tgz", - "integrity": "sha512-3MRqhIhSNVDsVAk4M6WNcuBZrAQe54W13xrXX6RzxXS+pA4nj6DQ96RegQS5z9BSNyYbFsBsPvMVDIpP+a/5RA==", - "requires": { - "cached-constructors-x": "^1.0.2", - "has-symbol-support-x": "^1.4.2", - "is-symbol": "^1.0.1" - } - }, - "to-string-tag-x": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/to-string-tag-x/-/to-string-tag-x-1.4.3.tgz", - "integrity": "sha512-5+0EZ6dOVt/XArXmkooxPzWxmOR081HM/uXitUow7h11WYg5pPo15uYqDWuqO7ZY+O3Atn/dG26wcJCK+mFevg==", - "requires": { - "lodash.isnull": "^3.0.0", - "validate.io-undefined": "^1.0.3" - } - }, - "to-string-x": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/to-string-x/-/to-string-x-1.4.5.tgz", - "integrity": "sha512-5xzlZDyDa9BUWNjNzZzHgKQ95PnV7qjvEhbqpFaj1ixaHgfJXOFaa3xdMJ+WLYd4hhaMJaxt8Pt5uKaWXfruXA==", - "requires": { - "cached-constructors-x": "^1.0.0", - "is-symbol": "^1.0.1" - } - }, "toggle-selection": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", @@ -51381,41 +49991,12 @@ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", "dev": true }, - "trim-left-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-left-x/-/trim-left-x-3.0.0.tgz", - "integrity": "sha512-+m6cqkppI+CxQBTwWEZliOHpOBnCArGyMnS1WCLb6IRgukhTkiQu/TNEN5Lj2eM9jk8ewJsc7WxFZfmwNpRXWQ==", - "requires": { - "cached-constructors-x": "^1.0.0", - "require-coercible-to-string-x": "^1.0.0", - "white-space-x": "^3.0.0" - } - }, - "trim-right-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-right-x/-/trim-right-x-3.0.0.tgz", - "integrity": "sha512-iIqEsWEbWVodqdixJHi4FoayJkUxhoL4AvSNGp4FF4FfQKRPGizt8++/RnyC9od75y7P/S6EfONoVqP+NddiKA==", - "requires": { - "cached-constructors-x": "^1.0.0", - "require-coercible-to-string-x": "^1.0.0", - "white-space-x": "^3.0.0" - } - }, "trim-trailing-lines": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", "dev": true }, - "trim-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-x/-/trim-x-3.0.0.tgz", - "integrity": "sha512-w8s38RAUScQ6t3XqMkS75iz5ZkIYLQpVnv2lp3IuTS36JdlVzC54oe6okOf4Wz3UH4rr3XAb2xR3kR5Xei82fw==", - "requires": { - "trim-left-x": "^3.0.0", - "trim-right-x": "^3.0.0" - } - }, "trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -52013,6 +50594,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -52020,7 +50602,8 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true }, "type": { "version": "1.2.0", @@ -52465,11 +51048,6 @@ } } }, - "url-join": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" - }, "url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -52494,15 +51072,6 @@ } } }, - "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", - "requires": { - "querystringify": "~1.0.0", - "requires-port": "~1.0.0" - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -52591,11 +51160,6 @@ "builtins": "^1.0.3" } }, - "validate.io-undefined": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/validate.io-undefined/-/validate.io-undefined-1.0.3.tgz", - "integrity": "sha1-fif8uzFbhB54JDQxiXZxkp4gt/Q=" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -52612,6 +51176,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -54308,11 +52873,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "white-space-x": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/white-space-x/-/white-space-x-3.0.1.tgz", - "integrity": "sha512-BwMFXQNPna/4RsNPOgldVYn+FkEv+lc3wUiFzuaW6Z2DH/oSk1UrRD6SBqDgWQO4JU+aBq3PVuPD9Vz0j7mh0w==" - }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", diff --git a/package.json b/package.json index 6777789db1..0cb56b6dec 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "ngx-markdown": "^11.1.3", "ngx-papaparse": "^5.0.0", "pouchdb-adapter-memory": "^7.2.2", - "pouchdb-authentication": "^1.1.3", "pouchdb-browser": "^7.2.2", "reflect-metadata": "^0.1.13", "reveal": "0.0.4", diff --git a/src/app/core/session/session-service/remote-session.spec.ts b/src/app/core/session/session-service/remote-session.spec.ts new file mode 100644 index 0000000000..d244076b5d --- /dev/null +++ b/src/app/core/session/session-service/remote-session.spec.ts @@ -0,0 +1,73 @@ +import { TestBed } from "@angular/core/testing"; +import { RemoteSession } from "./remote-session"; +import { HttpClient } from "@angular/common/http"; +import { ConnectionState } from "../session-states/connection-state.enum"; +import { of, throwError } from "rxjs"; +import { AppConfig } from "../../app-config/app-config"; +import { SessionType } from "../session-type"; + +describe("RemoteSessionService", () => { + let service: RemoteSession; + let mockHttpClient: jasmine.SpyObj; + + beforeEach(() => { + AppConfig.settings = { + site_name: "test", + session_type: SessionType.mock, + database: { + name: "database", + remote_url: "database_url", + }, + }; + mockHttpClient = jasmine.createSpyObj(["post", "delete"]); + TestBed.configureTestingModule({ + providers: [ + RemoteSession, + { provide: HttpClient, useValue: mockHttpClient }, + ], + }); + service = TestBed.inject(RemoteSession); + }); + + it("should be connected after successful login", async () => { + expect(service.connectionState.getState()).toBe( + ConnectionState.DISCONNECTED + ); + + mockHttpClient.post.and.returnValue(of()); + + await service.login("", ""); + + expect(mockHttpClient.post).toHaveBeenCalled(); + expect(service.connectionState.getState()).toBe(ConnectionState.CONNECTED); + }); + + it("should be offline if login fails", async () => { + mockHttpClient.post.and.returnValue(throwError(new Error())); + + await service.login("", ""); + + expect(service.connectionState.getState()).toBe(ConnectionState.OFFLINE); + }); + + it("should be rejected if login is unauthorized", async () => { + const unauthorizedError = new Error(); + unauthorizedError.name = "unauthorized"; + mockHttpClient.post.and.returnValue(throwError(unauthorizedError)); + + await service.login("", ""); + + expect(service.connectionState.getState()).toBe(ConnectionState.REJECTED); + }); + + it("should disconnect after logout", async () => { + service.connectionState.setState(ConnectionState.CONNECTED); + mockHttpClient.delete.and.returnValue(of()); + + await service.logout(); + + expect(service.connectionState.getState()).toBe( + ConnectionState.DISCONNECTED + ); + }); +}); diff --git a/src/app/core/session/session-service/remote-session.ts b/src/app/core/session/session-service/remote-session.ts index 670fdf1a5c..7f5cb65560 100644 --- a/src/app/core/session/session-service/remote-session.ts +++ b/src/app/core/session/session-service/remote-session.ts @@ -16,14 +16,12 @@ */ import PouchDB from "pouchdb-browser"; -import PouchDBAuthentication from "pouchdb-authentication"; import { AppConfig } from "../../app-config/app-config"; import { Injectable } from "@angular/core"; import { StateHandler } from "../session-states/state-handler"; import { ConnectionState } from "../session-states/connection-state.enum"; - -PouchDB.plugin(PouchDBAuthentication); +import { HttpClient } from "@angular/common/http"; /** * Responsibilities: @@ -34,17 +32,15 @@ PouchDB.plugin(PouchDBAuthentication); @Injectable() export class RemoteSession { /** remote (!) database PouchDB */ - public database: any; + public database: PouchDB.Database; /** state of the remote connection */ - public connectionState: StateHandler = new StateHandler( - ConnectionState.DISCONNECTED - ); + public connectionState = new StateHandler(ConnectionState.DISCONNECTED); /** * Create a RemoteSession and set up connection to the remote database CouchDB server configured in AppConfig. */ - constructor() { + constructor(private httpClient: HttpClient) { const thisRemoteSession = this; this.database = new PouchDB( AppConfig.settings.database.remote_url + AppConfig.settings.database.name, @@ -53,12 +49,8 @@ export class RemoteSession { rejectUnauthorized: false, timeout: 60000, }, - // This is a workaround for PouchDB 7.0.0 with pouchdb-authentication 1.1.3: - // https://github.com/pouchdb-community/pouchdb-authentication/issues/239 - // It is necessary, until this merged PR will be published in PouchDB 7.0.1 - // https://github.com/pouchdb/pouchdb/pull/7395 + // TODO remove connection state and this code fetch(url, opts) { - opts.credentials = "include"; const req = fetch(url, opts); req.then((result) => { if ( @@ -103,16 +95,14 @@ export class RemoteSession { username: string, password: string ): Promise { - const ajaxOpts = { - ajax: { - headers: { - Authorization: "Basic " + window.btoa(username + ":" + password), - }, - }, - }; - try { - await this.database.login(username, password, ajaxOpts); + await this.httpClient + .post( + `${AppConfig.settings.database.remote_url}_session`, + { name: username, password: password }, + { withCredentials: true } + ) + .toPromise(); this.connectionState.setState(ConnectionState.CONNECTED); return ConnectionState.CONNECTED; } catch (error) { @@ -129,8 +119,12 @@ export class RemoteSession { /** * Logout at the remote database. */ - public logout(): void { - this.database.logout(); + public async logout(): Promise { + await this.httpClient + .delete(`${AppConfig.settings.database.remote_url}_session`, { + withCredentials: true, + }) + .toPromise(); this.connectionState.setState(ConnectionState.DISCONNECTED); } } diff --git a/src/app/core/session/session-service/synced-session.service.spec.ts b/src/app/core/session/session-service/synced-session.service.spec.ts index 4cb8b01db3..88f5ef8cc1 100644 --- a/src/app/core/session/session-service/synced-session.service.spec.ts +++ b/src/app/core/session/session-service/synced-session.service.spec.ts @@ -57,7 +57,8 @@ describe("SyncedSessionService", () => { sessionService = new SyncedSessionService( alertService, jasmine.createSpyObj(["error", "warn"]), - entitySchemaService + entitySchemaService, + null ); }); @@ -177,7 +178,8 @@ describe("SyncedSessionService", () => { sessionService = new SyncedSessionService( alertService, jasmine.createSpyObj(["error", "warn"]), - entitySchemaService + entitySchemaService, + null ); // make private members localSession and remoteSession available in the tests localSession = sessionService["_localSession"]; diff --git a/src/app/core/session/session-service/synced-session.service.ts b/src/app/core/session/session-service/synced-session.service.ts index 9b50923c94..2e595919e3 100644 --- a/src/app/core/session/session-service/synced-session.service.ts +++ b/src/app/core/session/session-service/synced-session.service.ts @@ -29,6 +29,7 @@ import { SyncState } from "../session-states/sync-state.enum"; import { User } from "../../user/user"; import { EntitySchemaService } from "../../entity/schema/entity-schema.service"; import { LoggingService } from "../../logging/logging.service"; +import { HttpClient } from "@angular/common/http"; /** * A synced session creates and manages a LocalSession and a RemoteSession @@ -48,11 +49,12 @@ export class SyncedSessionService extends SessionService { constructor( private _alertService: AlertService, private _loggingService: LoggingService, - private _entitySchemaService: EntitySchemaService + private _entitySchemaService: EntitySchemaService, + private _httpClient: HttpClient ) { super(); this._localSession = new LocalSession(this._entitySchemaService); - this._remoteSession = new RemoteSession(); + this._remoteSession = new RemoteSession(this._httpClient); } /** see {@link SessionService} */ diff --git a/src/app/core/session/session.module.ts b/src/app/core/session/session.module.ts index bfaa2fe33e..b0cbe57f4d 100644 --- a/src/app/core/session/session.module.ts +++ b/src/app/core/session/session.module.ts @@ -30,6 +30,7 @@ import { MatCardModule } from "@angular/material/card"; import { MatFormFieldModule } from "@angular/material/form-field"; import { MatInputModule } from "@angular/material/input"; import { RouterModule } from "@angular/router"; +import { HttpClientModule } from "@angular/common/http"; /** * The core session logic handling user login as well as connection and synchronization with the remote database. @@ -49,6 +50,7 @@ import { RouterModule } from "@angular/router"; MatButtonModule, RouterModule, UserModule, + HttpClientModule, ], declarations: [LoginComponent], exports: [LoginComponent], diff --git a/src/app/core/session/session.service.provider.ts b/src/app/core/session/session.service.provider.ts index 5e8ab59815..fd86694856 100644 --- a/src/app/core/session/session.service.provider.ts +++ b/src/app/core/session/session.service.provider.ts @@ -25,20 +25,18 @@ import { LoginState } from "./session-states/login-state.enum"; import { SessionType } from "./session-type"; import { NewLocalSessionService } from "./session-service/new-local-session.service"; import { PouchDatabase } from "../database/pouch-database"; +import { HttpClient } from "@angular/common/http"; /** * Factory method for Angular DI provider of SessionService. * * see [sessionServiceProvider]{@link sessionServiceProvider} for details. - * - * @param alertService - * @param loggingService - * @param entitySchemaService */ export function sessionServiceFactory( alertService: AlertService, loggingService: LoggingService, - entitySchemaService: EntitySchemaService + entitySchemaService: EntitySchemaService, + httpClient: HttpClient ): SessionService { let sessionService: SessionService; switch (AppConfig.settings.session_type) { @@ -56,7 +54,8 @@ export function sessionServiceFactory( sessionService = new SyncedSessionService( alertService, loggingService, - entitySchemaService + entitySchemaService, + httpClient ); break; default: @@ -105,5 +104,5 @@ function updateLoggingServiceWithUserContext(sessionService: SessionService) { export const sessionServiceProvider = { provide: SessionService, useFactory: sessionServiceFactory, - deps: [AlertService, LoggingService, EntitySchemaService], + deps: [AlertService, LoggingService, EntitySchemaService, HttpClient], }; From 7f0c7e78a887df146252f2f9fb1244554835318f Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Mon, 26 Jul 2021 17:18:20 +0200 Subject: [PATCH 06/34] refactor: extract data export logic to own ExportModule and ExportService --- .../children-list.component.spec.ts | 3 +- .../children/children.module.ts | 2 - src/app/core/admin/admin.module.spec.ts | 13 -- src/app/core/admin/admin.module.ts | 11 +- .../admin/services/backup.service.spec.ts | 101 ------------- src/app/core/admin/services/backup.service.ts | 58 +------- .../entity-list/entity-list.component.html | 4 +- .../entity-list/entity-list.component.spec.ts | 5 +- .../entity-list/entity-list.module.ts | 4 +- .../export-data-button.component.html} | 0 .../export-data-button.component.scss} | 0 .../export-data-button.component.spec.ts} | 12 +- .../export-data-button.component.ts} | 16 +- .../export-service/export.service.spec.ts | 138 ++++++++++++++++++ .../export/export-service/export.service.ts | 63 ++++++++ src/app/core/export/export.module.ts | 11 ++ .../features/reporting/reporting.module.ts | 4 +- .../reporting/reporting.component.html | 4 +- 18 files changed, 248 insertions(+), 201 deletions(-) delete mode 100644 src/app/core/admin/admin.module.spec.ts rename src/app/core/{admin/export-data/export-data.component.html => export/export-data-button/export-data-button.component.html} (100%) rename src/app/core/{admin/export-data/export-data.component.scss => export/export-data-button/export-data-button.component.scss} (100%) rename src/app/core/{admin/export-data/export-data.component.spec.ts => export/export-data-button/export-data-button.component.spec.ts} (78%) rename src/app/core/{admin/export-data/export-data.component.ts => export/export-data-button/export-data-button.component.ts} (77%) create mode 100644 src/app/core/export/export-service/export.service.spec.ts create mode 100644 src/app/core/export/export-service/export.service.ts create mode 100644 src/app/core/export/export.module.ts diff --git a/src/app/child-dev-project/children/children-list/children-list.component.spec.ts b/src/app/child-dev-project/children/children-list/children-list.component.spec.ts index 508a583147..0d563e7c6f 100644 --- a/src/app/child-dev-project/children/children-list/children-list.component.spec.ts +++ b/src/app/child-dev-project/children/children-list/children-list.component.spec.ts @@ -8,7 +8,6 @@ import { import { ChildrenListComponent } from "./children-list.component"; import { ChildrenService } from "../children.service"; import { RouterTestingModule } from "@angular/router/testing"; -import { ExportDataComponent } from "../../../core/admin/export-data/export-data.component"; import { SessionService } from "../../../core/session/session-service/session.service"; import { of } from "rxjs"; import { ActivatedRoute, Router } from "@angular/router"; @@ -93,7 +92,7 @@ describe("ChildrenListComponent", () => { mockSessionService.getCurrentUser.and.returnValue(new User("test1")); mockChildrenService.getChildren.and.returnValue(of([])); TestBed.configureTestingModule({ - declarations: [ChildrenListComponent, ExportDataComponent], + declarations: [ChildrenListComponent], imports: [ ChildrenModule, diff --git a/src/app/child-dev-project/children/children.module.ts b/src/app/child-dev-project/children/children.module.ts index 115d4b5ce0..399b2662f6 100644 --- a/src/app/child-dev-project/children/children.module.ts +++ b/src/app/child-dev-project/children/children.module.ts @@ -51,7 +51,6 @@ import { NoRecentNotesDashboardComponent } from "../notes/dashboard-widgets/no-r import { HealthCheckupComponent } from "../health-checkup/health-checkup-component/health-checkup.component"; import { MatDatepickerModule } from "@angular/material/datepicker"; import { PreviousSchoolsComponent } from "../previous-schools/previous-schools.component"; -import { AdminModule } from "../../core/admin/admin.module"; import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; import { RecentNotesDashboardComponent } from "../notes/dashboard-widgets/recent-notes-dashboard/recent-notes-dashboard.component"; import { FormDialogModule } from "../../core/form-dialog/form-dialog.module"; @@ -99,7 +98,6 @@ import { EntityUtilsModule } from "../../core/entity-components/entity-utils/ent SchoolsModule, ReactiveFormsModule, MatDialogModule, - AdminModule, MatListModule, WebdavModule, MatProgressSpinnerModule, diff --git a/src/app/core/admin/admin.module.spec.ts b/src/app/core/admin/admin.module.spec.ts deleted file mode 100644 index 6b425e5788..0000000000 --- a/src/app/core/admin/admin.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { AdminModule } from "./admin.module"; - -describe("AdminModule", () => { - let adminModule: AdminModule; - - beforeEach(() => { - adminModule = new AdminModule(); - }); - - it("should create an instance", () => { - expect(adminModule).toBeTruthy(); - }); -}); diff --git a/src/app/core/admin/admin.module.ts b/src/app/core/admin/admin.module.ts index 949b2b8b27..539e699e8d 100644 --- a/src/app/core/admin/admin.module.ts +++ b/src/app/core/admin/admin.module.ts @@ -17,7 +17,6 @@ import { MatFormFieldModule } from "@angular/material/form-field"; import { MatInputModule } from "@angular/material/input"; import { MatIconModule } from "@angular/material/icon"; import { UserListComponent } from "./user-list/user-list.component"; -import { ExportDataComponent } from "./export-data/export-data.component"; import { BackupService } from "./services/backup.service"; import { MatTooltipModule } from "@angular/material/tooltip"; @@ -43,13 +42,7 @@ import { MatTooltipModule } from "@angular/material/tooltip"; MatIconModule, MatTooltipModule, ], - declarations: [AdminComponent, UserListComponent, ExportDataComponent], - providers: [ - AdminGuard, - ChildPhotoUpdateService, - BackupService, - ExportDataComponent, - ], - exports: [ExportDataComponent], + declarations: [AdminComponent, UserListComponent], + providers: [AdminGuard, ChildPhotoUpdateService, BackupService], }) export class AdminModule {} diff --git a/src/app/core/admin/services/backup.service.spec.ts b/src/app/core/admin/services/backup.service.spec.ts index fec153d0e9..f1d5f20889 100644 --- a/src/app/core/admin/services/backup.service.spec.ts +++ b/src/app/core/admin/services/backup.service.spec.ts @@ -3,10 +3,6 @@ import { TestBed } from "@angular/core/testing"; import { BackupService } from "./backup.service"; import { Database } from "../../database/database"; import { PouchDatabase } from "../../database/pouch-database"; -import { ConfigurableEnumValue } from "../../configurable-enum/configurable-enum.interface"; -import { DatabaseField } from "../../entity/database-field.decorator"; -import { DatabaseEntity } from "../../entity/database-entity.decorator"; -import { Entity } from "../../entity/model/entity"; describe("BackupService", () => { let db: PouchDatabase; @@ -147,101 +143,4 @@ describe("BackupService", () => { delete x._rev; return x; } - - it("exportJson creates the correct json object", () => { - class TestClass { - propertyOne; - propertyTwo; - } - const test = new TestClass(); - test.propertyOne = "Hello"; - test.propertyTwo = "World"; - const expected = JSON.stringify({ - propertyOne: "Hello", - propertyTwo: "World", - }); - const result = service.createJson([test]); - expect(result).toEqual(expected); - }); - - it("exportJson transforms an json array correctly", () => { - class TestClass { - propertyOne; - propertyTwo; - } - const test = new TestClass(); - test.propertyOne = "Hello"; - test.propertyTwo = "World"; - let expected = JSON.stringify({ - propertyOne: "Hello", - propertyTwo: "World", - }); - expected += BackupService.SEPARATOR_ROW; - expected += JSON.stringify({ propertyOne: "Hello", propertyTwo: "World" }); - const result = service.createJson([test, test]); - expect(result).toEqual(expected); - }); - - it("should create a csv string correctly", () => { - class TestClass { - _id; - _rev; - propOne; - propTwo; - } - const test = new TestClass(); - test._id = 1; - test._rev = 2; - test.propOne = "first"; - test.propTwo = "second"; - const expected = - '"_id","_rev","propOne","propTwo"\r\n"1","2","first","second"'; - const result = service.createCsv([test]); - expect(result).toEqual(expected); - }); - - it("should create a csv string correctly with multiple objects", () => { - class TestClass { - _id; - _rev; - propOne; - propTwo; - } - const test = new TestClass(); - test._id = 1; - test._rev = 2; - test.propOne = "first"; - test.propTwo = "second"; - const expected = - '"_id","_rev","propOne","propTwo"\r\n"1","2","first","second"\r\n"1","2","first","second"'; - const result = service.createCsv([test, test]); - expect(result).toEqual(expected); - }); - - it("getCsvExport should transform object properties to their label for export", async () => { - const testEnumValue: ConfigurableEnumValue = { - id: "ID VALUE", - label: "label value", - }; - const testDate = "2020-01-30"; - - @DatabaseEntity("TestEntity") - class TestEntity extends Entity { - @DatabaseField() enumProperty: ConfigurableEnumValue; - @DatabaseField() dateProperty: Date; - } - - const testEntity = new TestEntity(); - testEntity.enumProperty = testEnumValue; - testEntity.dateProperty = new Date(testDate); - - const csvExport = await service.createCsv([testEntity]); - - const rows = csvExport.split(BackupService.SEPARATOR_ROW); - expect(rows).toHaveSize(1 + 1); // includes 1 header line - const columnValues = rows[1].split(BackupService.SEPARATOR_COL); - expect(columnValues).toHaveSize(2 + 1); - expect(columnValues).toContain('"' + testEnumValue.label + '"'); - expect(columnValues).toContain(new Date(testDate).toISOString()); - }); }); diff --git a/src/app/core/admin/services/backup.service.ts b/src/app/core/admin/services/backup.service.ts index 61afeccfa0..5f3e8ff301 100644 --- a/src/app/core/admin/services/backup.service.ts +++ b/src/app/core/admin/services/backup.service.ts @@ -2,7 +2,7 @@ import { Injectable } from "@angular/core"; import { Database } from "../../database/database"; import { User } from "../../user/user"; import { Papa } from "ngx-papaparse"; -import { entityListSortingAccessor } from "../../entity-components/entity-subrecord/entity-subrecord/sorting-accessor"; +import { ExportService } from "../../export/export-service/export.service"; /** * Create and load backups of the database. @@ -16,7 +16,11 @@ export class BackupService { /** CSV column/field separator */ static readonly SEPARATOR_COL = ","; - constructor(private db: Database, private papa: Papa) {} + constructor( + private db: Database, + private papa: Papa, + private exportService: ExportService + ) {} /** * Creates a List of JSON elements separated by `BackupService.SEPARATOR_ROW` holding all elements of the database. @@ -26,22 +30,7 @@ export class BackupService { */ async getJsonExport(): Promise { const results = await this.db.getAll(); - return this.createJson(results); - } - - /** - * Creates a JSON string of the given data. - * - * @param data the data which should be converted to JSON - * @returns string containing all the values stringified elements of the input data - */ - createJson(data): string { - let res = ""; - data.forEach((r) => { - res += JSON.stringify(r) + BackupService.SEPARATOR_ROW; - }); - - return res.trim(); + return this.exportService.createJson(results); } /** @@ -51,38 +40,7 @@ export class BackupService { */ async getCsvExport(): Promise { const results = await this.db.getAll(); - return this.createCsv(results); - } - - /** - * Creates a CSV string of the input data - * - * @param data an array of elements - * @returns string a valid CSV string of the input data - */ - createCsv(data: any[]): string { - // create list of row descriptions for the csv string - const allFields = new Set(); - const exportableData = []; - - data.forEach((element: any) => { - const exportableObj = {}; - Object.keys(element).forEach((key: string) => { - const res = entityListSortingAccessor(element, key); - - if (res.toString().match(/\[object.*\]/) === null) { - allFields.add(key); - exportableObj[key] = res; - } - }); - - exportableData.push(exportableObj); - }); - - return this.papa.unparse( - { data: exportableData, fields: [...new Set(allFields)] }, - { quotes: true, header: true } - ); + return this.exportService.createCsv(results); } /** diff --git a/src/app/core/entity-components/entity-list/entity-list.component.html b/src/app/core/entity-components/entity-list/entity-list.component.html index 5e424849da..99389f2cda 100644 --- a/src/app/core/entity-components/entity-list/entity-list.component.html +++ b/src/app/core/entity-components/entity-list/entity-list.component.html @@ -57,7 +57,7 @@

{{ listName }}

> Add New - {{ listName }} Download CSV - + diff --git a/src/app/core/entity-components/entity-list/entity-list.component.spec.ts b/src/app/core/entity-components/entity-list/entity-list.component.spec.ts index e8f039f9ac..87497a7b35 100644 --- a/src/app/core/entity-components/entity-list/entity-list.component.spec.ts +++ b/src/app/core/entity-components/entity-list/entity-list.component.spec.ts @@ -9,7 +9,6 @@ import { Entity } from "../../entity/model/entity"; import { EntityMapperService } from "../../entity/entity-mapper.service"; import { User } from "../../user/user"; import { SessionService } from "../../session/session-service/session.service"; -import { ExportDataComponent } from "../../admin/export-data/export-data.component"; import { ChildrenListComponent } from "../../../child-dev-project/children/children-list/children-list.component"; import { Child } from "../../../child-dev-project/children/model/child"; import { ConfigService } from "../../config/config.service"; @@ -21,6 +20,7 @@ import { EntitySchemaService } from "../../entity/schema/entity-schema.service"; import { DatabaseField } from "../../entity/database-field.decorator"; import { ReactiveFormsModule } from "@angular/forms"; import { AttendanceService } from "../../../child-dev-project/attendance/attendance.service"; +import { ExportModule } from "../../export/export.module"; describe("EntityListComponent", () => { let component: EntityListComponent; @@ -98,11 +98,12 @@ describe("EntityListComponent", () => { ); TestBed.configureTestingModule({ - declarations: [EntityListComponent, ExportDataComponent], + declarations: [EntityListComponent], imports: [ CommonModule, NoopAnimationsModule, EntityListModule, + ExportModule, Angulartics2Module.forRoot(), ReactiveFormsModule, RouterTestingModule.withRoutes([ diff --git a/src/app/core/entity-components/entity-list/entity-list.module.ts b/src/app/core/entity-components/entity-list/entity-list.module.ts index adcb875918..d357555415 100644 --- a/src/app/core/entity-components/entity-list/entity-list.module.ts +++ b/src/app/core/entity-components/entity-list/entity-list.module.ts @@ -15,7 +15,7 @@ import { MatTableModule } from "@angular/material/table"; import { MatSortModule } from "@angular/material/sort"; import { MatPaginatorModule } from "@angular/material/paginator"; import { FormsModule } from "@angular/forms"; -import { AdminModule } from "../../admin/admin.module"; +import { ExportModule } from "../../export/export.module"; import { ViewModule } from "../../view/view.module"; import { ListFilterComponent } from "./list-filter/list-filter.component"; import { PermissionsModule } from "../../permissions/permissions.module"; @@ -30,7 +30,7 @@ import { EntityFormModule } from "../entity-form/entity-form.module"; FormsModule, MatFormFieldModule, MatSelectModule, - AdminModule, + ExportModule, MatIconModule, Angulartics2Module, MatButtonModule, diff --git a/src/app/core/admin/export-data/export-data.component.html b/src/app/core/export/export-data-button/export-data-button.component.html similarity index 100% rename from src/app/core/admin/export-data/export-data.component.html rename to src/app/core/export/export-data-button/export-data-button.component.html diff --git a/src/app/core/admin/export-data/export-data.component.scss b/src/app/core/export/export-data-button/export-data-button.component.scss similarity index 100% rename from src/app/core/admin/export-data/export-data.component.scss rename to src/app/core/export/export-data-button/export-data-button.component.scss diff --git a/src/app/core/admin/export-data/export-data.component.spec.ts b/src/app/core/export/export-data-button/export-data-button.component.spec.ts similarity index 78% rename from src/app/core/admin/export-data/export-data.component.spec.ts rename to src/app/core/export/export-data-button/export-data-button.component.spec.ts index e7cbbb175f..717573cb4a 100644 --- a/src/app/core/admin/export-data/export-data.component.spec.ts +++ b/src/app/core/export/export-data-button/export-data-button.component.spec.ts @@ -1,24 +1,24 @@ import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { BackupService } from "../services/backup.service"; -import { ExportDataComponent } from "./export-data.component"; +import { BackupService } from "../../admin/services/backup.service"; +import { ExportDataButtonComponent } from "./export-data-button.component"; describe("ExportDataComponent", () => { - let component: ExportDataComponent; - let fixture: ComponentFixture; + let component: ExportDataButtonComponent; + let fixture: ComponentFixture; let mockBackupService: jasmine.SpyObj; beforeEach( waitForAsync(() => { mockBackupService = jasmine.createSpyObj(["createJson", "createCsv"]); TestBed.configureTestingModule({ - declarations: [ExportDataComponent], + declarations: [ExportDataButtonComponent], providers: [{ provide: BackupService, useValue: mockBackupService }], }).compileComponents(); }) ); beforeEach(() => { - fixture = TestBed.createComponent(ExportDataComponent); + fixture = TestBed.createComponent(ExportDataButtonComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/core/admin/export-data/export-data.component.ts b/src/app/core/export/export-data-button/export-data-button.component.ts similarity index 77% rename from src/app/core/admin/export-data/export-data.component.ts rename to src/app/core/export/export-data-button/export-data-button.component.ts index ff126c2105..2b1711a238 100644 --- a/src/app/core/admin/export-data/export-data.component.ts +++ b/src/app/core/export/export-data-button/export-data-button.component.ts @@ -1,15 +1,15 @@ import { Component, Input } from "@angular/core"; -import { BackupService } from "../services/backup.service"; +import { ExportService } from "../export-service/export.service"; /** * Generic export data button that allows the user to download a file of the given data. */ @Component({ - selector: "app-export-data", - templateUrl: "./export-data.component.html", - styleUrls: ["./export-data.component.scss"], + selector: "app-export-data-button", + templateUrl: "./export-data-button.component.html", + styleUrls: ["./export-data-button.component.scss"], }) -export class ExportDataComponent { +export class ExportDataButtonComponent { /** data to be exported */ @Input() data: any = []; @@ -21,7 +21,7 @@ export class ExportDataComponent { @Input() disabled: boolean = false; - constructor(private backupService: BackupService) {} + constructor(private exportService: ExportService) {} /** * Trigger the download of the export file. @@ -46,10 +46,10 @@ export class ExportDataComponent { let result = ""; switch (this.format.toLowerCase()) { case "json": - result = this.backupService.createJson(this.data); + result = this.exportService.createJson(this.data); return new Blob([result], { type: "application/json" }); case "csv": - result = this.backupService.createCsv(this.data); + result = this.exportService.createCsv(this.data); return new Blob([result], { type: "text/csv" }); default: console.warn("Not supported format:", this.format); diff --git a/src/app/core/export/export-service/export.service.spec.ts b/src/app/core/export/export-service/export.service.spec.ts new file mode 100644 index 0000000000..b746d7fcab --- /dev/null +++ b/src/app/core/export/export-service/export.service.spec.ts @@ -0,0 +1,138 @@ +import { TestBed } from "@angular/core/testing"; + +import { ExportService } from "./export.service"; +import { ConfigurableEnumValue } from "../../configurable-enum/configurable-enum.interface"; +import { DatabaseField } from "../../entity/database-field.decorator"; +import { DatabaseEntity } from "../../entity/database-entity.decorator"; +import { Entity } from "../../entity/model/entity"; +import { BackupService } from "../../admin/services/backup.service"; + +describe("ExportService", () => { + let service: ExportService; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ExportService, QueryService], + }); + + service = TestBed.inject(ExportService); + }); + + it("should be created", () => { + expect(service).toBeTruthy(); + }); + + it("should create the correct json object", () => { + class TestClass { + propertyOne; + propertyTwo; + } + const test = new TestClass(); + test.propertyOne = "Hello"; + test.propertyTwo = "World"; + + const result = service.createJson([test]); + + const expected = JSON.stringify({ + propertyOne: "Hello", + propertyTwo: "World", + }); + expect(result).toEqual(expected); + }); + + it("should transform a json array", () => { + class TestClass { + propertyOne; + propertyTwo; + } + const test = new TestClass(); + test.propertyOne = "Hello"; + test.propertyTwo = "World"; + + const result = service.createJson([test, test]); + + let expected = JSON.stringify({ + propertyOne: "Hello", + propertyTwo: "World", + }); + expected += BackupService.SEPARATOR_ROW; + expected += JSON.stringify({ propertyOne: "Hello", propertyTwo: "World" }); + expect(result).toEqual(expected); + }); + + it("should contain a column for every property", async () => { + const docs = [ + { _id: "Test:1", test: 1 }, + { _id: "Test:2", other: 2 }, + ]; + + const csvExport = await service.createCsv(docs); + + const rows = csvExport.split(ExportService.SEPARATOR_ROW); + expect(rows).toHaveSize(2 + 1); // includes 1 header line + expect(rows[0].split(ExportService.SEPARATOR_COL)).toHaveSize(3); + }); + + it("should create a csv string correctly", () => { + class TestClass { + _id; + _rev; + propOne; + propTwo; + } + const test = new TestClass(); + test._id = 1; + test._rev = 2; + test.propOne = "first"; + test.propTwo = "second"; + const expected = + '"_id","_rev","propOne","propTwo"\r\n"1","2","first","second"'; + const result = service.createCsv([test]); + expect(result).toEqual(expected); + }); + + it("should create a csv string correctly with multiple objects", () => { + class TestClass { + _id; + _rev; + propOne; + propTwo; + } + const test = new TestClass(); + test._id = 1; + test._rev = 2; + test.propOne = "first"; + test.propTwo = "second"; + const expected = + '"_id","_rev","propOne","propTwo"\r\n"1","2","first","second"\r\n"1","2","first","second"'; + const result = service.createCsv([test, test]); + expect(result).toEqual(expected); + }); + + it("should transform object properties to their label for export", async () => { + const testEnumValue: ConfigurableEnumValue = { + id: "ID VALUE", + label: "label value", + }; + const testDate = "2020-01-30"; + + @DatabaseEntity("TestEntity") + class TestEntity extends Entity { + @DatabaseField() enumProperty: ConfigurableEnumValue; + @DatabaseField() dateProperty: Date; + } + + const testEntity = new TestEntity(); + testEntity.enumProperty = testEnumValue; + testEntity.dateProperty = new Date(testDate); + + const csvExport = await service.createCsv([testEntity]); + + const rows = csvExport.split(ExportService.SEPARATOR_ROW); + expect(rows).toHaveSize(1 + 1); // includes 1 header line + const columnValues = rows[1].split(ExportService.SEPARATOR_COL); + expect(columnValues).toHaveSize(2 + 1); + expect(columnValues).toContain('"' + testEnumValue.label + '"'); + expect(columnValues).toContain(new Date(testDate).toISOString()); + }); +}); diff --git a/src/app/core/export/export-service/export.service.ts b/src/app/core/export/export-service/export.service.ts new file mode 100644 index 0000000000..c0f1fef331 --- /dev/null +++ b/src/app/core/export/export-service/export.service.ts @@ -0,0 +1,63 @@ +import { Injectable } from "@angular/core"; +import { Papa } from "ngx-papaparse"; +import { entityListSortingAccessor } from "../../entity-components/entity-subrecord/entity-subrecord/sorting-accessor"; + +/** + * Prepare data for export in csv format. + */ +@Injectable({ + providedIn: "root", +}) +export class ExportService { + /** CSV row separator */ + static readonly SEPARATOR_ROW = "\n"; + /** CSV column/field separator */ + static readonly SEPARATOR_COL = ","; + + constructor(private papa: Papa) {} + + /** + * Creates a JSON string of the given data. + * + * @param data the data which should be converted to JSON + * @returns string containing all the values stringified elements of the input data + */ + createJson(data): string { + let res = ""; + data.forEach((r) => { + res += JSON.stringify(r) + ExportService.SEPARATOR_ROW; + }); + + return res.trim(); + } + + /** + * Creates a CSV string of the input data + * + * @param data an array of elements + * @returns string a valid CSV string of the input data + */ + createCsv(data: any[]): string { + const allFields = new Set(); + const exportableData = []; + + data.forEach((element: any) => { + const exportableObj = {}; + Object.keys(element).forEach((key: string) => { + const res = entityListSortingAccessor(element, key); + + if (res?.toString().match(/\[object.*\]/) === null) { + allFields.add(key); + exportableObj[key] = res; + } + }); + + exportableData.push(exportableObj); + }); + + return this.papa.unparse( + { data: exportableData, fields: [...new Set(allFields)] }, + { quotes: true, header: true } + ); + } +} diff --git a/src/app/core/export/export.module.ts b/src/app/core/export/export.module.ts new file mode 100644 index 0000000000..5652554d67 --- /dev/null +++ b/src/app/core/export/export.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { ExportDataButtonComponent } from "./export-data-button/export-data-button.component"; +import { MatButtonModule } from "@angular/material/button"; + +@NgModule({ + declarations: [ExportDataButtonComponent], + imports: [CommonModule, MatButtonModule], + exports: [ExportDataButtonComponent], +}) +export class ExportModule {} diff --git a/src/app/features/reporting/reporting.module.ts b/src/app/features/reporting/reporting.module.ts index 794cbff25b..0b46bbdf1b 100644 --- a/src/app/features/reporting/reporting.module.ts +++ b/src/app/features/reporting/reporting.module.ts @@ -10,7 +10,7 @@ import { MatIconModule } from "@angular/material/icon"; import { MatDatepickerModule } from "@angular/material/datepicker"; import { MatFormFieldModule } from "@angular/material/form-field"; import { FormsModule } from "@angular/forms"; -import { AdminModule } from "../../core/admin/admin.module"; +import { ExportModule } from "../../core/export/export.module"; import { ReportRowComponent } from "./reporting/report-row/report-row.component"; import { MatProgressBarModule } from "@angular/material/progress-bar"; import { MatSelectModule } from "@angular/material/select"; @@ -29,7 +29,7 @@ import { FlexModule } from "@angular/flex-layout"; MatDatepickerModule, MatFormFieldModule, FormsModule, - AdminModule, + ExportModule, MatProgressBarModule, MatSelectModule, FlexModule, diff --git a/src/app/features/reporting/reporting/reporting.component.html b/src/app/features/reporting/reporting/reporting.component.html index 517d05ac27..4579cfdb70 100644 --- a/src/app/features/reporting/reporting/reporting.component.html +++ b/src/app/features/reporting/reporting/reporting.component.html @@ -54,7 +54,7 @@ > Calculate - Download report - + From 2cebde260707789ac08ab692aebc84a253a54693 Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Wed, 28 Jul 2021 18:15:05 +0200 Subject: [PATCH 07/34] feat: make fields included in list exports configurable --- src/app/core/config/config-fix.ts | 5 ++ .../entity-list/EntityListConfig.ts | 6 ++ .../entity-list/entity-list.component.html | 1 + .../export-data-button.component.ts | 12 +++- .../export-service/export-column-config.ts | 14 +++++ .../export-service/export.service.spec.ts | 58 +++++++++++++------ .../export/export-service/export.service.ts | 25 +++++--- 7 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 src/app/core/export/export-service/export-column-config.ts diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts index d2de252a95..dbd0b7bf03 100644 --- a/src/app/core/config/config-fix.ts +++ b/src/app/core/config/config-fix.ts @@ -645,6 +645,11 @@ export const defaultJsonConfig = { "type", "assignedTo" ], + "exportConfig": [ + { label: "Title", key: "title" }, + { label: "Type", key: "type" }, + { label: "Assigned users", key: "assignedTo" } + ] } }, "view:recurring-activity/:id": { diff --git a/src/app/core/entity-components/entity-list/EntityListConfig.ts b/src/app/core/entity-components/entity-list/EntityListConfig.ts index fdf1f5207d..73dcf7bfed 100644 --- a/src/app/core/entity-components/entity-list/EntityListConfig.ts +++ b/src/app/core/entity-components/entity-list/EntityListConfig.ts @@ -1,6 +1,7 @@ import { Entity } from "../../entity/model/entity"; import { FilterSelectionOption } from "../../filter/filter-selection/filter-selection"; import { FormFieldConfig } from "../entity-form/entity-form/FormConfig"; +import { ExportColumnConfig } from "../../export/export-service/export-column-config"; export interface EntityListConfig { title: string; @@ -17,6 +18,11 @@ export interface EntityListConfig { * Default is no filters. */ filters?: FilterConfig[]; + + /** + * Optional config defining what fields are included in exports. + */ + exportConfig?: ExportColumnConfig[]; } export interface ColumnGroupsConfig { diff --git a/src/app/core/entity-components/entity-list/entity-list.component.html b/src/app/core/entity-components/entity-list/entity-list.component.html index 99389f2cda..d8a058aa28 100644 --- a/src/app/core/entity-components/entity-list/entity-list.component.html +++ b/src/app/core/entity-components/entity-list/entity-list.component.html @@ -59,6 +59,7 @@

{{ listName }}

{ beforeEach(() => { TestBed.configureTestingModule({ - providers: [ExportService, QueryService], + providers: [ExportService], }); service = TestBed.inject(ExportService); @@ -91,22 +91,41 @@ describe("ExportService", () => { expect(result).toEqual(expected); }); - it("should create a csv string correctly with multiple objects", () => { - class TestClass { - _id; - _rev; - propOne; - propTwo; - } - const test = new TestClass(); - test._id = 1; - test._rev = 2; - test.propOne = "first"; - test.propTwo = "second"; - const expected = - '"_id","_rev","propOne","propTwo"\r\n"1","2","first","second"\r\n"1","2","first","second"'; - const result = service.createCsv([test, test]); - expect(result).toEqual(expected); + it("should export all properties", async () => { + const testObject1 = { + name: "foo", + age: 12, + }; + const testObject2 = { + name: "bar", + age: 15, + extra: true, + }; + + const csvResult = await service.createCsv([testObject1, testObject2]); + + expect(csvResult).toBe( + '"name","age","extra"\r\n"foo","12",\r\n"bar","15","1"' + ); + }); + + it("should export only properties mentioned in config", async () => { + const testObject1 = { + name: "foo", + age: 12, + }; + const testObject2 = { + name: "bar", + age: 15, + extra: true, + }; + + const csvResult = await service.createCsv( + [testObject1, testObject2], + [{ label: "test name", key: "name" }] + ); + + expect(csvResult).toBe('"test name"\r\n"foo"\r\n"bar"'); }); it("should transform object properties to their label for export", async () => { @@ -120,19 +139,22 @@ describe("ExportService", () => { class TestEntity extends Entity { @DatabaseField() enumProperty: ConfigurableEnumValue; @DatabaseField() dateProperty: Date; + @DatabaseField() boolProperty: boolean; } const testEntity = new TestEntity(); testEntity.enumProperty = testEnumValue; testEntity.dateProperty = new Date(testDate); + testEntity.boolProperty = true; const csvExport = await service.createCsv([testEntity]); const rows = csvExport.split(ExportService.SEPARATOR_ROW); expect(rows).toHaveSize(1 + 1); // includes 1 header line const columnValues = rows[1].split(ExportService.SEPARATOR_COL); - expect(columnValues).toHaveSize(2 + 1); + expect(columnValues).toHaveSize(3 + 1); expect(columnValues).toContain('"' + testEnumValue.label + '"'); expect(columnValues).toContain(new Date(testDate).toISOString()); + expect(columnValues).toContain('"1"'); // true => "1" }); }); diff --git a/src/app/core/export/export-service/export.service.ts b/src/app/core/export/export-service/export.service.ts index c0f1fef331..c069a68bd5 100644 --- a/src/app/core/export/export-service/export.service.ts +++ b/src/app/core/export/export-service/export.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@angular/core"; import { Papa } from "ngx-papaparse"; import { entityListSortingAccessor } from "../../entity-components/entity-subrecord/entity-subrecord/sorting-accessor"; +import { ExportColumnConfig } from "./export-column-config"; /** * Prepare data for export in csv format. @@ -35,28 +36,36 @@ export class ExportService { * Creates a CSV string of the input data * * @param data an array of elements + * @param config (Optional) config specifying which fields should be exported * @returns string a valid CSV string of the input data */ - createCsv(data: any[]): string { + createCsv(data: any[], config?: ExportColumnConfig[]): string { const allFields = new Set(); const exportableData = []; data.forEach((element: any) => { const exportableObj = {}; - Object.keys(element).forEach((key: string) => { - const res = entityListSortingAccessor(element, key); - if (res?.toString().match(/\[object.*\]/) === null) { - allFields.add(key); - exportableObj[key] = res; + const currentRowConfig = + config ?? + Object.keys(element).map((key) => ({ key: key } as ExportColumnConfig)); + for (const columnConfig of currentRowConfig) { + const label = columnConfig.label ?? columnConfig.key; + const value = entityListSortingAccessor(element, columnConfig.key); + if (value?.toString().match(/\[object.*\]/) !== null) { + // skip object values that cannot be converted to a meaningful string + continue; } - }); + + exportableObj[label] = value; + allFields.add(label); + } exportableData.push(exportableObj); }); return this.papa.unparse( - { data: exportableData, fields: [...new Set(allFields)] }, + { data: exportableData, fields: [...allFields] }, { quotes: true, header: true } ); } From 89c6b3c4a74d2825359d73c9c03dbd102e3f29ac Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Tue, 3 Aug 2021 10:46:26 +0200 Subject: [PATCH 08/34] refactor: include optional prefix parameter in query-service toEntity to avoid explicit ":addPrefix" calls --- .../features/reporting/query.service.spec.ts | 24 +++++++++++++++++++ src/app/features/reporting/query.service.ts | 7 +++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/app/features/reporting/query.service.spec.ts b/src/app/features/reporting/query.service.spec.ts index 82b393251c..5aa89d4d09 100644 --- a/src/app/features/reporting/query.service.spec.ts +++ b/src/app/features/reporting/query.service.spec.ts @@ -442,4 +442,28 @@ describe("QueryService", () => { expect(eventsWithNotes).toContain(note1); expect(eventsWithNotes).toContain(note2); }); + + it("should do addPrefix as part of toEntities if optional parameter is given", async () => { + const queryWithAddPrefix = ` + ${School.ENTITY_TYPE}:toArray[*privateSchool=true] + :getRelated(${ChildSchoolRelation.ENTITY_TYPE}, schoolId) + .childId:addPrefix(${Child.ENTITY_TYPE}):toEntities.name`; + const queryWithoutAddPrefix = ` + ${School.ENTITY_TYPE}:toArray[*privateSchool=true] + :getRelated(${ChildSchoolRelation.ENTITY_TYPE}, schoolId) + .childId:toEntities(${Child.ENTITY_TYPE}).name`; + + const resultWithAddPrefix = await service.queryData( + queryWithAddPrefix, + null, + null + ); + const resultWithoutAddPrefix = await service.queryData( + queryWithoutAddPrefix, + null, + null + ); + + expect(resultWithoutAddPrefix).toEqual(resultWithAddPrefix); + }); }); diff --git a/src/app/features/reporting/query.service.ts b/src/app/features/reporting/query.service.ts index 2cd635ddb5..3451e5ab5c 100644 --- a/src/app/features/reporting/query.service.ts +++ b/src/app/features/reporting/query.service.ts @@ -154,9 +154,14 @@ export class QueryService { /** * Turns a list of ids (with the entity prefix) into a list of entities * @param ids the array of ids with entity prefix + * @param entityPrefix (Optional) entity type prefix that should be added to the given ids where prefix is still missing * @returns a list of entity objects */ - toEntities(ids: string[]): Entity[] { + toEntities(ids: string[], entityPrefix?: string): Entity[] { + if (entityPrefix) { + ids = this.addPrefix(ids, entityPrefix); + } + return ids.map((id) => { const prefix = id.split(":")[0]; return this.entities[prefix][id]; From 1546f53fd9cf66b31075d5ed452539007ee1a00e Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Tue, 3 Aug 2021 20:10:48 +0200 Subject: [PATCH 09/34] fix: create exports in valid json format closes #469 --- .../core/admin/admin/admin.component.spec.ts | 4 +- src/app/core/admin/admin/admin.component.ts | 8 ++-- .../admin/services/backup.service.spec.ts | 42 +++++++------------ src/app/core/admin/services/backup.service.ts | 9 +--- .../export-service/export.service.spec.ts | 33 +++------------ .../export/export-service/export.service.ts | 7 +--- 6 files changed, 29 insertions(+), 74 deletions(-) diff --git a/src/app/core/admin/admin/admin.component.spec.ts b/src/app/core/admin/admin/admin.component.spec.ts index 3e36b05b26..51f19e6583 100644 --- a/src/app/core/admin/admin/admin.component.spec.ts +++ b/src/app/core/admin/admin/admin.component.spec.ts @@ -170,8 +170,8 @@ describe("AdminComponent", () => { })); it("should open dialog and call backup service when loading backup", fakeAsync(() => { - const mockFileReader = createFileReaderMock(); - mockBackupService.getJsonExport.and.returnValue(Promise.resolve("")); + const mockFileReader = createFileReaderMock("[]"); + mockBackupService.getJsonExport.and.returnValue(Promise.resolve("[]")); createDialogMock(); component.loadBackup(null); diff --git a/src/app/core/admin/admin/admin.component.ts b/src/app/core/admin/admin/admin.component.ts index 79a8b0b61d..90422c7f54 100644 --- a/src/app/core/admin/admin/admin.component.ts +++ b/src/app/core/admin/admin/admin.component.ts @@ -129,11 +129,9 @@ export class AdminComponent implements OnInit { const dialogRef = this.confirmationDialog.openDialog( $localize`Overwrite complete database?`, - $localize`Are you sure you want to restore this backup? This will delete all ${ - restorePoint.split("\n").length - } existing records in the database, restoring ${ - newData.split("\n").length - } records from the loaded file.` + $localize`Are you sure you want to restore this backup? This will + delete all ${JSON.parse(restorePoint).length} existing records, + restoring ${JSON.parse(newData).length} records from the loaded file.` ); dialogRef.afterClosed().subscribe(async (confirmed) => { diff --git a/src/app/core/admin/services/backup.service.spec.ts b/src/app/core/admin/services/backup.service.spec.ts index f1d5f20889..e8ec8af91e 100644 --- a/src/app/core/admin/services/backup.service.spec.ts +++ b/src/app/core/admin/services/backup.service.spec.ts @@ -3,6 +3,7 @@ import { TestBed } from "@angular/core/testing"; import { BackupService } from "./backup.service"; import { Database } from "../../database/database"; import { PouchDatabase } from "../../database/pouch-database"; +import { ExportService } from "../../export/export-service/export.service"; describe("BackupService", () => { let db: PouchDatabase; @@ -46,7 +47,9 @@ describe("BackupService", () => { const jsonExport = await service.getJsonExport(); - expect(jsonExport.split(BackupService.SEPARATOR_ROW)).toHaveSize(2); + expect(jsonExport).toBe( + `[{"test":1,"_id":"Test:1","_rev":"${res[0]._rev}"},{"test":2,"_id":"Test:2","_rev":"${res[1]._rev}"}]` + ); }); it("getJsonExport | clearDatabase | importJson should restore all records", async () => { @@ -77,36 +80,23 @@ describe("BackupService", () => { const csvExport = await service.getCsvExport(); - expect(csvExport.split(BackupService.SEPARATOR_ROW)).toHaveSize(2 + 1); // includes 1 header line - }); - - it("getCsvExport should contain a column for every property", async () => { - await db.put({ _id: "Test:1", test: 1 }); - await db.put({ _id: "Test:2", other: 2 }); - const res = await db.getAll(); - expect(res).toHaveSize(2); - - const csvExport = await service.getCsvExport(); - - const rows = csvExport.split(BackupService.SEPARATOR_ROW); - expect(rows).toHaveSize(2 + 1); // includes 1 header line - expect(rows[0].split(BackupService.SEPARATOR_COL)).toHaveSize(3 + 1); // includes _rev + expect(csvExport.split(ExportService.SEPARATOR_ROW)).toHaveSize(2 + 1); // includes 1 header line }); it("importCsv should add records", async () => { const csv = "_id" + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "test" + - BackupService.SEPARATOR_ROW + + ExportService.SEPARATOR_ROW + '"Test:1"' + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "1" + - BackupService.SEPARATOR_ROW + + ExportService.SEPARATOR_ROW + '"Test:2"' + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "2" + - BackupService.SEPARATOR_ROW; + ExportService.SEPARATOR_ROW; await service.importCsv(csv, true); @@ -121,14 +111,14 @@ describe("BackupService", () => { it("importCsv should not add empty properties to records", async () => { const csv = "_id" + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "other" + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "test" + - BackupService.SEPARATOR_ROW + + ExportService.SEPARATOR_ROW + '"Test:1"' + - BackupService.SEPARATOR_COL + - BackupService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + + ExportService.SEPARATOR_COL + "1"; await service.importCsv(csv); diff --git a/src/app/core/admin/services/backup.service.ts b/src/app/core/admin/services/backup.service.ts index 5f3e8ff301..bdcde1569c 100644 --- a/src/app/core/admin/services/backup.service.ts +++ b/src/app/core/admin/services/backup.service.ts @@ -11,11 +11,6 @@ import { ExportService } from "../../export/export-service/export.service"; providedIn: "root", }) export class BackupService { - /** CSV row separator */ - static readonly SEPARATOR_ROW = "\n"; - /** CSV column/field separator */ - static readonly SEPARATOR_COL = ","; - constructor( private db: Database, private papa: Papa, @@ -66,8 +61,8 @@ export class BackupService { * @param forceUpdate should existing objects be overridden? Default false */ async importJson(json, forceUpdate = false): Promise { - for (const stringRecord of json.split(BackupService.SEPARATOR_ROW)) { - const record = JSON.parse(stringRecord); + const documents = JSON.parse(json); + for (const record of documents) { // Remove _rev so CouchDB treats it as a new rather than a updated document delete record._rev; await this.db.put(record, forceUpdate); diff --git a/src/app/core/export/export-service/export.service.spec.ts b/src/app/core/export/export-service/export.service.spec.ts index 7326c33adb..e159c5bd56 100644 --- a/src/app/core/export/export-service/export.service.spec.ts +++ b/src/app/core/export/export-service/export.service.spec.ts @@ -5,7 +5,6 @@ import { ConfigurableEnumValue } from "../../configurable-enum/configurable-enum import { DatabaseField } from "../../entity/database-field.decorator"; import { DatabaseEntity } from "../../entity/database-entity.decorator"; import { Entity } from "../../entity/model/entity"; -import { BackupService } from "../../admin/services/backup.service"; describe("ExportService", () => { let service: ExportService; @@ -22,25 +21,7 @@ describe("ExportService", () => { expect(service).toBeTruthy(); }); - it("should create the correct json object", () => { - class TestClass { - propertyOne; - propertyTwo; - } - const test = new TestClass(); - test.propertyOne = "Hello"; - test.propertyTwo = "World"; - - const result = service.createJson([test]); - - const expected = JSON.stringify({ - propertyOne: "Hello", - propertyTwo: "World", - }); - expect(result).toEqual(expected); - }); - - it("should transform a json array", () => { + it("should export to json array", () => { class TestClass { propertyOne; propertyTwo; @@ -51,13 +32,9 @@ describe("ExportService", () => { const result = service.createJson([test, test]); - let expected = JSON.stringify({ - propertyOne: "Hello", - propertyTwo: "World", - }); - expected += BackupService.SEPARATOR_ROW; - expected += JSON.stringify({ propertyOne: "Hello", propertyTwo: "World" }); - expect(result).toEqual(expected); + expect(result).toEqual( + '[{"propertyOne":"Hello","propertyTwo":"World"},{"propertyOne":"Hello","propertyTwo":"World"}]' + ); }); it("should contain a column for every property", async () => { @@ -91,7 +68,7 @@ describe("ExportService", () => { expect(result).toEqual(expected); }); - it("should export all properties", async () => { + it("should export all properties if no config is provided", async () => { const testObject1 = { name: "foo", age: 12, diff --git a/src/app/core/export/export-service/export.service.ts b/src/app/core/export/export-service/export.service.ts index c069a68bd5..71a59d5662 100644 --- a/src/app/core/export/export-service/export.service.ts +++ b/src/app/core/export/export-service/export.service.ts @@ -24,12 +24,7 @@ export class ExportService { * @returns string containing all the values stringified elements of the input data */ createJson(data): string { - let res = ""; - data.forEach((r) => { - res += JSON.stringify(r) + ExportService.SEPARATOR_ROW; - }); - - return res.trim(); + return JSON.stringify(data); } /** From 8710e65f28cd8cc51a064986405232e4269f2642 Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Wed, 4 Aug 2021 11:53:53 +0200 Subject: [PATCH 10/34] fix: export boolean as true/false rather than as number --- .../entity-subrecord/entity-subrecord/sorting-accessor.ts | 6 +++--- src/app/core/export/export-service/export.service.spec.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/core/entity-components/entity-subrecord/entity-subrecord/sorting-accessor.ts b/src/app/core/entity-components/entity-subrecord/entity-subrecord/sorting-accessor.ts index 1ddc624164..9e374eb628 100644 --- a/src/app/core/entity-components/entity-subrecord/entity-subrecord/sorting-accessor.ts +++ b/src/app/core/entity-components/entity-subrecord/entity-subrecord/sorting-accessor.ts @@ -12,10 +12,10 @@ export function entityListSortingAccessor(data: Object, sortingHeader: string) { "label" in data[sortingHeader] ) { return data[sortingHeader].label; - } else if (data[sortingHeader] instanceof Date) { - return data[sortingHeader]; - } else { + } else if (typeof data[sortingHeader] === "string") { return tryNumber(data[sortingHeader]); + } else { + return data[sortingHeader]; } } diff --git a/src/app/core/export/export-service/export.service.spec.ts b/src/app/core/export/export-service/export.service.spec.ts index e159c5bd56..ed14ff51ce 100644 --- a/src/app/core/export/export-service/export.service.spec.ts +++ b/src/app/core/export/export-service/export.service.spec.ts @@ -82,7 +82,7 @@ describe("ExportService", () => { const csvResult = await service.createCsv([testObject1, testObject2]); expect(csvResult).toBe( - '"name","age","extra"\r\n"foo","12",\r\n"bar","15","1"' + '"name","age","extra"\r\n"foo","12",\r\n"bar","15","true"' ); }); @@ -132,6 +132,6 @@ describe("ExportService", () => { expect(columnValues).toHaveSize(3 + 1); expect(columnValues).toContain('"' + testEnumValue.label + '"'); expect(columnValues).toContain(new Date(testDate).toISOString()); - expect(columnValues).toContain('"1"'); // true => "1" + expect(columnValues).toContain('"true"'); }); }); From f0a0a2f81ad2bb368e9d859352e0275d9649d2b4 Mon Sep 17 00:00:00 2001 From: Simon <33730997+TheSlimvReal@users.noreply.github.com> Date: Wed, 4 Aug 2021 12:07:51 +0200 Subject: [PATCH 11/34] fix(core): forward requests to base assets folder in i18n subfolders (#936) fixes #926 --- build/default.conf | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build/default.conf b/build/default.conf index 141a9d51b7..d38723fd83 100644 --- a/build/default.conf +++ b/build/default.conf @@ -6,12 +6,20 @@ server { #access_log /var/log/nginx/host.access.log main; root /usr/share/nginx/html; - location ^~ /de { + + # Catch requests to the (locale) assets folder and add fallback to super-folder + # E.g. if '/en-US/assets/config.json' doesn't exist, try '/assets/config.json' + location ~* ^/.+/assets/(.+)$ { + # $1 refers to everything after 'assets/' + try_files $uri /assets/$1 =404; + } + + location /de { index index.html index.htm; try_files $uri $uri/ /de/index.html; } - location ^~ /en { + location /en { index index.html index.htm; try_files $uri $uri/ /en-US/index.html; } From 5fd685695425d72e0fb8a8088143efc0f9d1f579 Mon Sep 17 00:00:00 2001 From: kirtijadhav <83791155+kirtijadhav@users.noreply.github.com> Date: Sat, 7 Aug 2021 06:34:26 +0200 Subject: [PATCH 12/34] fix: Tooltips open when clicking the question mark on mobile devices fixes #891 --- src/app/core/config/config-fix.ts | 20 +++++------ .../edit-configurable-enum.component.html | 7 +--- .../entity-form/entity-form.module.ts | 6 ++++ .../entity-form/entity-form.component.html | 33 ++++++++++++------- .../entity-form/entity-form.component.scss | 4 +++ .../edit-long-text.component.html | 6 ---- .../edit-text/edit-text.component.html | 6 ---- 7 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts index dbd0b7bf03..e2bd05617c 100644 --- a/src/app/core/config/config-fix.ts +++ b/src/app/core/config/config-fix.ts @@ -602,16 +602,16 @@ export const defaultJsonConfig = { component: "HistoricalDataComponent", config: [ "date", - "isMotivatedDuringClass" , - "isParticipatingInClass", - "isInteractingWithOthers", - "doesHomework", - "isOnTime", - "asksQuestions", - "listens", - "canWorkOnBoard", - "isConcentrated", - "doesNotDisturb", + {id: "isMotivatedDuringClass", visibleFrom: "lg" }, + {id: "isParticipatingInClass", visibleFrom: "lg" }, + {id: "isInteractingWithOthers", visibleFrom: "lg" }, + {id: "doesHomework", visibleFrom: "lg" }, + {id: "isOnTime", visibleFrom: "lg" }, + {id: "asksQuestions", visibleFrom: "lg" }, + {id: "listens", visibleFrom: "lg" }, + {id: "canWorkOnBoard", visibleFrom: "lg" }, + {id: "isConcentrated", visibleFrom: "lg" }, + {id: "doesNotDisturb", visibleFrom: "lg" }, ] } ] diff --git a/src/app/core/configurable-enum/edit-configurable-enum/edit-configurable-enum.component.html b/src/app/core/configurable-enum/edit-configurable-enum/edit-configurable-enum.component.html index f4b3c1d632..b208f491af 100644 --- a/src/app/core/configurable-enum/edit-configurable-enum/edit-configurable-enum.component.html +++ b/src/app/core/configurable-enum/edit-configurable-enum/edit-configurable-enum.component.html @@ -7,10 +7,5 @@ {{ o.label }} - + diff --git a/src/app/core/entity-components/entity-form/entity-form.module.ts b/src/app/core/entity-components/entity-form/entity-form.module.ts index 6819f3585f..072959356f 100644 --- a/src/app/core/entity-components/entity-form/entity-form.module.ts +++ b/src/app/core/entity-components/entity-form/entity-form.module.ts @@ -6,6 +6,9 @@ import { MatButtonModule } from "@angular/material/button"; import { FlexModule } from "@angular/flex-layout"; import { ViewModule } from "../../view/view.module"; import { PermissionsModule } from "../../permissions/permissions.module"; +import { MatIconModule } from "@angular/material/icon"; +import { MatTooltipModule } from "@angular/material/tooltip"; +import { MatFormFieldModule } from "@angular/material/form-field"; @NgModule({ declarations: [EntityFormComponent], @@ -15,6 +18,9 @@ import { PermissionsModule } from "../../permissions/permissions.module"; FlexModule, ViewModule, PermissionsModule, + MatIconModule, + MatTooltipModule, + MatFormFieldModule, ], providers: [EntityFormService], exports: [EntityFormComponent], diff --git a/src/app/core/entity-components/entity-form/entity-form/entity-form.component.html b/src/app/core/entity-components/entity-form/entity-form/entity-form.component.html index b4ee057a16..98eb8e2c3e 100644 --- a/src/app/core/entity-components/entity-form/entity-form/entity-form.component.html +++ b/src/app/core/entity-components/entity-form/entity-form/entity-form.component.html @@ -6,18 +6,27 @@ fxLayout.sm="row wrap" >
-
- - +
+
+ + +
+
diff --git a/src/app/core/entity-components/entity-form/entity-form/entity-form.component.scss b/src/app/core/entity-components/entity-form/entity-form/entity-form.component.scss index 23aed4d2ea..f95ec42686 100644 --- a/src/app/core/entity-components/entity-form/entity-form/entity-form.component.scss +++ b/src/app/core/entity-components/entity-form/entity-form/entity-form.component.scss @@ -1,3 +1,7 @@ .edit-button { margin-left: 10px; } +.form-field { + display: inline-block; + margin-left: 20px; +} diff --git a/src/app/core/entity-components/entity-utils/dynamic-form-components/edit-long-text/edit-long-text.component.html b/src/app/core/entity-components/entity-utils/dynamic-form-components/edit-long-text/edit-long-text.component.html index a9fa8eea4e..e4daf3c9a4 100644 --- a/src/app/core/entity-components/entity-utils/dynamic-form-components/edit-long-text/edit-long-text.component.html +++ b/src/app/core/entity-components/entity-utils/dynamic-form-components/edit-long-text/edit-long-text.component.html @@ -1,10 +1,4 @@ -