From e7c7037a14289b726241cee21764986275dcc5be Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 26 Aug 2022 18:09:28 +0200 Subject: [PATCH] Add eslint-plugin-rxjs & rxjs-angular (#3373) --- .eslintignore | 5 + .eslintrc.json | 13 +- .gitignore | 1 + .prettierignore | 1 + .vscode/settings.json | 3 + .../session-syncer.spec.ts | 2 +- .../session-sync-observable/session-syncer.ts | 20 +- .../popup/accounts/two-factor.component.ts | 1 + apps/browser/src/popup/app.component.ts | 3 +- .../src/popup/send/send-add-edit.component.ts | 2 + .../src/popup/send/send-type.component.ts | 1 + .../settings/folder-add-edit.component.ts | 2 + .../src/popup/settings/settings.component.ts | 2 + .../src/popup/vault/add-edit.component.ts | 2 + .../src/popup/vault/attachments.component.ts | 2 + .../src/popup/vault/ciphers.component.ts | 1 + .../src/popup/vault/collections.component.ts | 3 + .../popup/vault/password-history.component.ts | 2 + .../src/popup/vault/share.component.ts | 3 + .../src/popup/vault/vault-filter.component.ts | 1 + .../src/popup/vault/vault-select.component.ts | 2 + .../browser/src/popup/vault/view.component.ts | 1 + .../src/services/folders/folder.service.ts | 2 +- .../src/app/accounts/lock.component.ts | 1 + .../src/app/accounts/login.component.ts | 3 + .../src/app/accounts/settings.component.ts | 2 + .../src/app/accounts/two-factor.component.ts | 5 + apps/desktop/src/app/app.component.ts | 8 +- .../app/layout/account-switcher.component.ts | 2 + .../src/app/layout/search/search.component.ts | 3 + apps/desktop/src/app/send/send.component.ts | 1 + .../src/app/vault/ciphers.component.ts | 2 + apps/desktop/src/app/vault/vault.component.ts | 14 + apps/web/src/app/accounts/login.component.ts | 2 + .../src/app/accounts/register.component.ts | 2 + apps/web/src/app/accounts/sso.component.ts | 2 + .../trial-initiation.component.ts | 2 + .../src/app/accounts/two-factor.component.ts | 3 + .../accounts/verify-email-token.component.ts | 2 + .../verify-recover-delete.component.ts | 2 + apps/web/src/app/app.component.ts | 2 +- .../src/app/common/base.accept.component.ts | 1 + .../src/app/common/base.people.component.ts | 1 + apps/web/src/app/layouts/navbar.component.ts | 1 + .../layouts/organization-layout.component.ts | 1 + .../manage/collections.component.ts | 6 + .../organizations/manage/events.component.ts | 2 + .../organizations/manage/groups.component.ts | 6 + .../organizations/manage/manage.component.ts | 2 + .../organizations/manage/people.component.ts | 10 + .../manage/policies.component.ts | 4 + .../settings/account.component.ts | 3 + .../organization-billing.component.ts | 2 + .../organization-subscription.component.ts | 3 + .../settings/settings.component.ts | 2 + .../settings/two-factor-setup.component.ts | 3 + ...families-for-enterprise-setup.component.ts | 4 + .../exposed-passwords-report.component.ts | 2 + .../import-export/org-export.component.ts | 2 + .../import-export/org-import.component.ts | 2 + .../inactive-two-factor-report.component.ts | 2 + .../reused-passwords-report.component.ts | 2 + .../organizations/tools/tools.component.ts | 2 + .../unsecured-websites-report.component.ts | 2 + .../tools/weak-passwords-report.component.ts | 2 + .../organizations/vault/vault.component.ts | 10 + .../reports/pages/cipher-report.component.ts | 3 + .../app/reports/reports-layout.component.ts | 1 + apps/web/src/app/send/access.component.ts | 2 + apps/web/src/app/send/send.component.ts | 2 + .../settings/create-organization.component.ts | 2 + .../emergency-access-view.component.ts | 2 + .../settings/emergency-access.component.ts | 5 + .../web/src/app/settings/payment.component.ts | 2 +- .../src/app/settings/tax-info.component.ts | 2 + .../settings/two-factor-setup.component.ts | 6 + .../src/app/vault/bulk-actions.component.ts | 5 + .../vault-filter/vault-filter.component.ts | 2 + apps/web/src/app/vault/vault.component.ts | 14 + .../organizations/manage/scim.component.ts | 2 + .../app/organizations/manage/sso.component.ts | 4 + .../providers/clients/clients.component.ts | 4 + .../clients/create-organization.component.ts | 2 + .../app/providers/manage/events.component.ts | 2 + .../app/providers/manage/manage.component.ts | 2 + .../app/providers/manage/people.component.ts | 3 + .../providers/providers-layout.component.ts | 2 + .../providers/settings/account.component.ts | 2 + .../providers/settings/settings.component.ts | 2 + .../app/providers/setup/setup.component.ts | 2 + .../src/components/generator.component.ts | 1 + libs/angular/src/components/lock.component.ts | 1 + .../src/components/set-password.component.ts | 1 + .../settings/vault-timeout-input.component.ts | 1 + libs/angular/src/components/sso.component.ts | 1 + .../components/user-verification.component.ts | 2 + .../src/services/environment.service.ts | 12 +- .../src/services/folder/folder.service.ts | 30 +- libs/common/src/services/state.service.ts | 28 +- package-lock.json | 513 ++++++++++++++++++ package.json | 9 +- tsconfig.eslint.json | 31 ++ 102 files changed, 866 insertions(+), 49 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 tsconfig.eslint.json diff --git a/.eslintignore b/.eslintignore index 2dff9d9aeb..930b468de8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,6 @@ **/build **/dist +**/coverage .angular **/node_modules @@ -21,3 +22,7 @@ apps/web/src/theme.js apps/web/tailwind.config.js apps/cli/config/config.js + +tailwind.config.js +libs/components/tailwind.config.base.js +libs/components/tailwind.config.js diff --git a/.eslintrc.json b/.eslintrc.json index 161bc9ec74..7245952160 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,13 +4,19 @@ "browser": true, "webextensions": true }, - "plugins": ["@typescript-eslint"], + "plugins": ["@typescript-eslint", "rxjs", "rxjs-angular"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": ["./tsconfig.eslint.json"], + "sourceType": "module" + }, "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:import/recommended", "plugin:import/typescript", - "prettier" + "prettier", + "plugin:rxjs/recommended" ], "rules": { "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled @@ -50,6 +56,7 @@ ], "pathGroupsExcludedImportTypes": ["builtin"] } - ] + ], + "rxjs-angular/prefer-takeuntil": "error" } } diff --git a/.gitignore b/.gitignore index 2e389245b2..0774f26cc3 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ coverage # Storybook documentation.json +.eslintcache diff --git a/.prettierignore b/.prettierignore index 0a23f5ce73..8790a1e73f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,6 +3,7 @@ **/dist **/coverage .angular +documentation.json # External libraries / auto synced locales apps/browser/src/_locales diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..fe586d49e9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["Popout", "Reprompt", "takeuntil"] +} diff --git a/apps/browser/src/decorators/session-sync-observable/session-syncer.spec.ts b/apps/browser/src/decorators/session-sync-observable/session-syncer.spec.ts index 40ba412cd4..f2df60ad7a 100644 --- a/apps/browser/src/decorators/session-sync-observable/session-syncer.spec.ts +++ b/apps/browser/src/decorators/session-sync-observable/session-syncer.spec.ts @@ -29,7 +29,7 @@ describe("session syncer", () => { afterEach(() => { jest.resetAllMocks(); - behaviorSubject.unsubscribe(); + behaviorSubject.complete(); }); describe("constructor", () => { diff --git a/apps/browser/src/decorators/session-sync-observable/session-syncer.ts b/apps/browser/src/decorators/session-sync-observable/session-syncer.ts index 80eb07289f..0c97b983f7 100644 --- a/apps/browser/src/decorators/session-sync-observable/session-syncer.ts +++ b/apps/browser/src/decorators/session-sync-observable/session-syncer.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject, Subscription } from "rxjs"; +import { BehaviorSubject, concatMap, Subscription } from "rxjs"; import { Utils } from "@bitwarden/common/misc/utils"; @@ -41,13 +41,17 @@ export class SessionSyncer { // This may be a memory leak. // There is no good time to unsubscribe from this observable. Hopefully Manifest V3 clears memory from temporary // contexts. If so, this is handled by destruction of the context. - this.subscription = this.behaviorSubject.subscribe(async (next) => { - if (this.ignoreNextUpdate) { - this.ignoreNextUpdate = false; - return; - } - await this.updateSession(next); - }); + this.subscription = this.behaviorSubject + .pipe( + concatMap(async (next) => { + if (this.ignoreNextUpdate) { + this.ignoreNextUpdate = false; + return; + } + await this.updateSession(next); + }) + ) + .subscribe(); } private listenForUpdates() { diff --git a/apps/browser/src/popup/accounts/two-factor.component.ts b/apps/browser/src/popup/accounts/two-factor.component.ts index 01e4490962..0a0bbcaec8 100644 --- a/apps/browser/src/popup/accounts/two-factor.component.ts +++ b/apps/browser/src/popup/accounts/two-factor.component.ts @@ -109,6 +109,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { } } + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.sso === "true") { super.onSuccessfulLogin = () => { diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index 7524aec22d..f1a69a6d6f 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -35,7 +35,7 @@ export class AppComponent implements OnInit, OnDestroy { private lastActivity: number = null; private activeUserId: string; - private destroy$: Subject = new Subject(); + private destroy$ = new Subject(); constructor( private toastrService: ToastrService, @@ -132,6 +132,7 @@ export class AppComponent implements OnInit, OnDestroy { BrowserApi.messageListener("app.component", (window as any).bitwardenPopupMainMessageListener); + // eslint-disable-next-line rxjs/no-async-subscribe this.router.events.pipe(takeUntil(this.destroy$)).subscribe(async (event) => { if (event instanceof NavigationEnd) { const url = event.urlAfterRedirects || event.url || ""; diff --git a/apps/browser/src/popup/send/send-add-edit.component.ts b/apps/browser/src/popup/send/send-add-edit.component.ts index 1877549ba6..c04e180dbf 100644 --- a/apps/browser/src/popup/send/send-add-edit.component.ts +++ b/apps/browser/src/popup/send/send-add-edit.component.ts @@ -19,6 +19,7 @@ import { PopupUtilsService } from "../services/popup-utils.service"; selector: "app-send-add-edit", templateUrl: "send-add-edit.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SendAddEditComponent extends BaseAddEditComponent { // Options header showOptions = false; @@ -98,6 +99,7 @@ export class SendAddEditComponent extends BaseAddEditComponent { this.isUnsupportedMac = this.platformUtilsService.isChrome() && window?.navigator?.appVersion.includes("Mac OS X 11"); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.sendId) { this.sendId = params.sendId; diff --git a/apps/browser/src/popup/send/send-type.component.ts b/apps/browser/src/popup/send/send-type.component.ts index 36e0dce89a..3e4054bf72 100644 --- a/apps/browser/src/popup/send/send-type.component.ts +++ b/apps/browser/src/popup/send/send-type.component.ts @@ -70,6 +70,7 @@ export class SendTypeComponent extends BaseSendComponent { async ngOnInit() { // Let super class finish await super.ngOnInit(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (this.applySavedState) { this.state = await this.stateService.getBrowserSendTypeComponentState(); diff --git a/apps/browser/src/popup/settings/folder-add-edit.component.ts b/apps/browser/src/popup/settings/folder-add-edit.component.ts index c601292bb8..8ff8ba3b1a 100644 --- a/apps/browser/src/popup/settings/folder-add-edit.component.ts +++ b/apps/browser/src/popup/settings/folder-add-edit.component.ts @@ -13,6 +13,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti selector: "app-folder-add-edit", templateUrl: "folder-add-edit.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class FolderAddEditComponent extends BaseFolderAddEditComponent { constructor( folderService: FolderService, @@ -27,6 +28,7 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.folderId) { this.folderId = params.folderId; diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts index f691128311..e91e8e47d4 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -37,6 +37,7 @@ const RateUrls = { selector: "app-settings", templateUrl: "settings.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SettingsComponent implements OnInit { @ViewChild("vaultTimeoutActionSelect", { read: ElementRef, static: true }) vaultTimeoutActionSelectRef: ElementRef; @@ -102,6 +103,7 @@ export class SettingsComponent implements OnInit { this.vaultTimeout.setValue(timeout); } this.previousVaultTimeout = this.vaultTimeout.value; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.vaultTimeout.valueChanges.subscribe(async (value) => { await this.saveVaultTimeout(value); }); diff --git a/apps/browser/src/popup/vault/add-edit.component.ts b/apps/browser/src/popup/vault/add-edit.component.ts index bed1d30d6b..f5062051c2 100644 --- a/apps/browser/src/popup/vault/add-edit.component.ts +++ b/apps/browser/src/popup/vault/add-edit.component.ts @@ -27,6 +27,7 @@ import { PopupUtilsService } from "../services/popup-utils.service"; selector: "app-vault-add-edit", templateUrl: "add-edit.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AddEditComponent extends BaseAddEditComponent { currentUris: string[]; showAttachments = true; @@ -72,6 +73,7 @@ export class AddEditComponent extends BaseAddEditComponent { async ngOnInit() { await super.ngOnInit(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.cipherId) { this.cipherId = params.cipherId; diff --git a/apps/browser/src/popup/vault/attachments.component.ts b/apps/browser/src/popup/vault/attachments.component.ts index ab868f6130..a8dc7a5278 100644 --- a/apps/browser/src/popup/vault/attachments.component.ts +++ b/apps/browser/src/popup/vault/attachments.component.ts @@ -17,6 +17,7 @@ import { StateService } from "@bitwarden/common/abstractions/state.service"; selector: "app-vault-attachments", templateUrl: "attachments.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AttachmentsComponent extends BaseAttachmentsComponent { openedAttachmentsInPopup: boolean; @@ -46,6 +47,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { this.cipherId = params.cipherId; await this.init(); diff --git a/apps/browser/src/popup/vault/ciphers.component.ts b/apps/browser/src/popup/vault/ciphers.component.ts index c6a63846dd..4346ad7a66 100644 --- a/apps/browser/src/popup/vault/ciphers.component.ts +++ b/apps/browser/src/popup/vault/ciphers.component.ts @@ -80,6 +80,7 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On this.searchTypeSearch = !this.platformUtilsService.isSafari(); this.showOrganizations = await this.organizationService.hasOrganizations(); this.vaultFilter = this.vaultFilterService.getVaultFilter(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (this.applySavedState) { this.state = await this.stateService.getBrowserCipherComponentState(); diff --git a/apps/browser/src/popup/vault/collections.component.ts b/apps/browser/src/popup/vault/collections.component.ts index 286a585e8f..13e529ce73 100644 --- a/apps/browser/src/popup/vault/collections.component.ts +++ b/apps/browser/src/popup/vault/collections.component.ts @@ -14,6 +14,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti selector: "app-vault-collections", templateUrl: "collections.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CollectionsComponent extends BaseCollectionsComponent { constructor( collectionService: CollectionService, @@ -28,9 +29,11 @@ export class CollectionsComponent extends BaseCollectionsComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.onSavedCollections.subscribe(() => { this.back(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { this.cipherId = params.cipherId; await this.load(); diff --git a/apps/browser/src/popup/vault/password-history.component.ts b/apps/browser/src/popup/vault/password-history.component.ts index 83a5a12d5a..6210986927 100644 --- a/apps/browser/src/popup/vault/password-history.component.ts +++ b/apps/browser/src/popup/vault/password-history.component.ts @@ -12,6 +12,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti selector: "app-password-history", templateUrl: "password-history.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class PasswordHistoryComponent extends BasePasswordHistoryComponent { constructor( cipherService: CipherService, @@ -24,6 +25,7 @@ export class PasswordHistoryComponent extends BasePasswordHistoryComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.cipherId) { this.cipherId = params.cipherId; diff --git a/apps/browser/src/popup/vault/share.component.ts b/apps/browser/src/popup/vault/share.component.ts index a57a1a6398..bfff215533 100644 --- a/apps/browser/src/popup/vault/share.component.ts +++ b/apps/browser/src/popup/vault/share.component.ts @@ -14,6 +14,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti selector: "app-vault-share", templateUrl: "share.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ShareComponent extends BaseShareComponent { constructor( collectionService: CollectionService, @@ -36,9 +37,11 @@ export class ShareComponent extends BaseShareComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.onSharedCipher.subscribe(() => { this.router.navigate(["view-cipher", { cipherId: this.cipherId }]); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { this.cipherId = params.cipherId; await this.load(); diff --git a/apps/browser/src/popup/vault/vault-filter.component.ts b/apps/browser/src/popup/vault/vault-filter.component.ts index 65645b35aa..603c5a031e 100644 --- a/apps/browser/src/popup/vault/vault-filter.component.ts +++ b/apps/browser/src/popup/vault/vault-filter.component.ts @@ -114,6 +114,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy { }); const restoredScopeState = await this.restoreState(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { this.state = await this.browserStateService.getBrowserGroupingComponentState(); if (this.state?.searchText) { diff --git a/apps/browser/src/popup/vault/vault-select.component.ts b/apps/browser/src/popup/vault/vault-select.component.ts index 90870984b0..d12463f2c1 100644 --- a/apps/browser/src/popup/vault/vault-select.component.ts +++ b/apps/browser/src/popup/vault/vault-select.component.ts @@ -47,6 +47,7 @@ import { VaultFilterService } from "../../services/vaultFilter.service"; ]), ], }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class VaultSelectComponent implements OnInit { @Output() onVaultSelectionChanged = new EventEmitter(); @@ -168,6 +169,7 @@ export class VaultSelectComponent implements OnInit { this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(), this.overlayRef.detachments() + // eslint-disable-next-line rxjs-angular/prefer-takeuntil ).subscribe(() => { this.close(); }); diff --git a/apps/browser/src/popup/vault/view.component.ts b/apps/browser/src/popup/vault/view.component.ts index 0655212e6f..e43b86e6b8 100644 --- a/apps/browser/src/popup/vault/view.component.ts +++ b/apps/browser/src/popup/vault/view.component.ts @@ -88,6 +88,7 @@ export class ViewComponent extends BaseViewComponent { ngOnInit() { this.inPopout = this.popupUtilsService.inPopout(window); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.cipherId) { this.cipherId = params.cipherId; diff --git a/apps/browser/src/services/folders/folder.service.ts b/apps/browser/src/services/folders/folder.service.ts index f97b9d0d0b..a3a6a4d8ba 100644 --- a/apps/browser/src/services/folders/folder.service.ts +++ b/apps/browser/src/services/folders/folder.service.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from "rxjs/internal/BehaviorSubject"; +import { BehaviorSubject } from "rxjs"; import { Folder } from "@bitwarden/common/models/domain/folder"; import { FolderView } from "@bitwarden/common/models/view/folderView"; diff --git a/apps/desktop/src/app/accounts/lock.component.ts b/apps/desktop/src/app/accounts/lock.component.ts index e7e5c33715..08c73c78b8 100644 --- a/apps/desktop/src/app/accounts/lock.component.ts +++ b/apps/desktop/src/app/accounts/lock.component.ts @@ -69,6 +69,7 @@ export class LockComponent extends BaseLockComponent { const forcePasswordReset = await this.stateService.getForcePasswordReset(); this.successRoute = forcePasswordReset === true ? this.unAuthenicatedUrl : this.authenicatedUrl; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.route.queryParams.subscribe((params) => { if (this.supportsBiometric && params.promptBiometric && autoPromptBiometric) { setTimeout(async () => { diff --git a/apps/desktop/src/app/accounts/login.component.ts b/apps/desktop/src/app/accounts/login.component.ts index 22731b21f2..c0bce046c8 100644 --- a/apps/desktop/src/app/accounts/login.component.ts +++ b/apps/desktop/src/app/accounts/login.component.ts @@ -102,13 +102,16 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy { this.environmentModal ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil modal.onShown.subscribe(() => { this.showingModal = true; }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil modal.onClosed.subscribe(() => { this.showingModal = false; }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onSaved.subscribe(() => { modal.close(); }); diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index fe69c82054..0fd9f99d57 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -24,6 +24,7 @@ import { DeleteAccountComponent } from "./delete-account.component"; selector: "app-settings", templateUrl: "settings.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SettingsComponent implements OnInit { vaultTimeoutAction: string; pin: boolean = null; @@ -178,6 +179,7 @@ export class SettingsComponent implements OnInit { this.vaultTimeout.setValue(await this.stateService.getVaultTimeout()); this.vaultTimeoutAction = await this.stateService.getVaultTimeoutAction(); this.previousVaultTimeout = this.vaultTimeout.value; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.vaultTimeout.valueChanges.pipe(debounceTime(500)).subscribe(() => { this.saveVaultTimeoutOptions(); }); diff --git a/apps/desktop/src/app/accounts/two-factor.component.ts b/apps/desktop/src/app/accounts/two-factor.component.ts index d281841f2c..b5dd8df0c7 100644 --- a/apps/desktop/src/app/accounts/two-factor.component.ts +++ b/apps/desktop/src/app/accounts/two-factor.component.ts @@ -21,6 +21,7 @@ import { TwoFactorOptionsComponent } from "./two-factor-options.component"; selector: "app-two-factor", templateUrl: "two-factor.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TwoFactorComponent extends BaseTwoFactorComponent { @ViewChild("twoFactorOptions", { read: ViewContainerRef, static: true }) twoFactorOptionsModal: ViewContainerRef; @@ -67,18 +68,22 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { this.twoFactorOptionsModal ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil modal.onShown.subscribe(() => { this.showingModal = true; }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil modal.onClosed.subscribe(() => { this.showingModal = false; }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe childComponent.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => { modal.close(); this.selectedProviderType = provider; await this.init(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onRecoverSelected.subscribe(() => { modal.close(); }); diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts index c9f39c895e..29cefbe02d 100644 --- a/apps/desktop/src/app/app.component.ts +++ b/apps/desktop/src/app/app.component.ts @@ -98,7 +98,7 @@ export class AppComponent implements OnInit, OnDestroy { private isIdle = false; private activeUserId: string = null; - private destroy$: Subject = new Subject(); + private destroy$ = new Subject(); constructor( private broadcasterService: BroadcasterService, @@ -377,10 +377,12 @@ export class AppComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onSaved.subscribe(() => { this.modal.close(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); @@ -396,11 +398,13 @@ export class AppComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe childComponent.onSavedFolder.subscribe(async () => { this.modal.close(); this.syncService.fullSync(false); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); @@ -415,6 +419,7 @@ export class AppComponent implements OnInit, OnDestroy { (comp) => (comp.comingFromAddEdit = false) ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); @@ -539,6 +544,7 @@ export class AppComponent implements OnInit, OnDestroy { [this.modal] = await this.modalService.openViewRef(type, ref); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); diff --git a/apps/desktop/src/app/layout/account-switcher.component.ts b/apps/desktop/src/app/layout/account-switcher.component.ts index ecb25d481b..08ae7026b8 100644 --- a/apps/desktop/src/app/layout/account-switcher.component.ts +++ b/apps/desktop/src/app/layout/account-switcher.component.ts @@ -48,6 +48,7 @@ export class SwitcherAccount extends Account { ]), ], }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AccountSwitcherComponent implements OnInit { isOpen = false; accounts: { [userId: string]: SwitcherAccount } = {}; @@ -84,6 +85,7 @@ export class AccountSwitcherComponent implements OnInit { ) {} async ngOnInit(): Promise { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.stateService.accounts.subscribe(async (accounts: { [userId: string]: Account }) => { for (const userId in accounts) { accounts[userId].profile.authenticationStatus = await this.authService.getAuthStatus( diff --git a/apps/desktop/src/app/layout/search/search.component.ts b/apps/desktop/src/app/layout/search/search.component.ts index 6f5f7a69fd..36e17c676a 100644 --- a/apps/desktop/src/app/layout/search/search.component.ts +++ b/apps/desktop/src/app/layout/search/search.component.ts @@ -17,16 +17,19 @@ export class SearchComponent implements OnInit, OnDestroy { private activeAccountSubscription: Subscription; constructor(private searchBarService: SearchBarService, private stateService: StateService) { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.searchBarService.state$.subscribe((state) => { this.state = state; }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.searchText.valueChanges.subscribe((value) => { this.searchBarService.setSearchText(value); }); } ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.activeAccountSubscription = this.stateService.activeAccount$.subscribe((value) => { this.searchBarService.setSearchText(""); this.searchText.patchValue(""); diff --git a/apps/desktop/src/app/send/send.component.ts b/apps/desktop/src/app/send/send.component.ts index d8b68d842c..0717734f37 100644 --- a/apps/desktop/src/app/send/send.component.ts +++ b/apps/desktop/src/app/send/send.component.ts @@ -56,6 +56,7 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro policyService, logService ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.searchBarService.searchText$.subscribe((searchText) => { this.searchText = searchText; this.searchTextChanged(); diff --git a/apps/desktop/src/app/vault/ciphers.component.ts b/apps/desktop/src/app/vault/ciphers.component.ts index 30fcbd270b..8039a93843 100644 --- a/apps/desktop/src/app/vault/ciphers.component.ts +++ b/apps/desktop/src/app/vault/ciphers.component.ts @@ -10,10 +10,12 @@ import { SearchBarService } from "../layout/search/search-bar.service"; selector: "app-vault-ciphers", templateUrl: "ciphers.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CiphersComponent extends BaseCiphersComponent { constructor(searchService: SearchService, searchBarService: SearchBarService) { super(searchService); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil searchBarService.searchText$.subscribe((searchText) => { this.searchText = searchText; this.search(200); diff --git a/apps/desktop/src/app/vault/vault.component.ts b/apps/desktop/src/app/vault/vault.component.ts index 3907f7b4af..3deae9fc72 100644 --- a/apps/desktop/src/app/vault/vault.component.ts +++ b/apps/desktop/src/app/vault/vault.component.ts @@ -216,6 +216,7 @@ export class VaultComponent implements OnInit, OnDestroy { } async load() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { if (params.cipherId) { const cipherView = new CipherView(); @@ -458,9 +459,12 @@ export class VaultComponent implements OnInit, OnDestroy { this.modal = modal; let madeAttachmentChanges = false; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onUploadedAttachment.subscribe(() => (madeAttachmentChanges = true)); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onDeletedAttachment.subscribe(() => (madeAttachmentChanges = true)); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.modal.onClosed.subscribe(async () => { this.modal = null; if (madeAttachmentChanges) { @@ -482,11 +486,13 @@ export class VaultComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe childComponent.onSharedCipher.subscribe(async () => { this.modal.close(); this.viewCipher(cipher); await this.ciphersComponent.refresh(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.modal.onClosed.subscribe(async () => { this.modal = null; }); @@ -504,10 +510,12 @@ export class VaultComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onSavedCollections.subscribe(() => { this.modal.close(); this.viewCipher(cipher); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.modal.onClosed.subscribe(async () => { this.modal = null; }); @@ -524,6 +532,7 @@ export class VaultComponent implements OnInit, OnDestroy { (comp) => (comp.cipherId = cipher.id) ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.modal.onClosed.subscribe(async () => { this.modal = null; }); @@ -596,6 +605,7 @@ export class VaultComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil childComponent.onSelected.subscribe((value: string) => { this.modal.close(); if (loginType) { @@ -608,6 +618,7 @@ export class VaultComponent implements OnInit, OnDestroy { } }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); @@ -629,15 +640,18 @@ export class VaultComponent implements OnInit, OnDestroy { ); this.modal = modal; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe childComponent.onSavedFolder.subscribe(async (folder: FolderView) => { this.modal.close(); await this.vaultFilterComponent.reloadCollectionsAndFolders(this.activeFilter); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe childComponent.onDeletedFolder.subscribe(async (folder: FolderView) => { this.modal.close(); await this.vaultFilterComponent.reloadCollectionsAndFolders(this.activeFilter); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.modal.onClosed.subscribe(() => { this.modal = null; }); diff --git a/apps/web/src/app/accounts/login.component.ts b/apps/web/src/app/accounts/login.component.ts index 30b09246b0..6a13ff3233 100644 --- a/apps/web/src/app/accounts/login.component.ts +++ b/apps/web/src/app/accounts/login.component.ts @@ -26,6 +26,7 @@ import { RouterService, StateService } from "../core"; selector: "app-login", templateUrl: "login.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class LoginComponent extends BaseLoginComponent { showResetPasswordAutoEnrollWarning = false; enforcedPasswordPolicyOptions: MasterPasswordPolicyOptions; @@ -68,6 +69,7 @@ export class LoginComponent extends BaseLoginComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.email != null && qParams.email.indexOf("@") > -1) { this.email = qParams.email; diff --git a/apps/web/src/app/accounts/register.component.ts b/apps/web/src/app/accounts/register.component.ts index 3f5ce3bf7d..4e700ca4d4 100644 --- a/apps/web/src/app/accounts/register.component.ts +++ b/apps/web/src/app/accounts/register.component.ts @@ -27,6 +27,7 @@ import { RouterService } from "../core"; selector: "app-register", templateUrl: "register.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class RegisterComponent extends BaseRegisterComponent { email = ""; showCreateOrgMessage = false; @@ -70,6 +71,7 @@ export class RegisterComponent extends BaseRegisterComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.route.queryParams.pipe(first()).subscribe((qParams) => { this.referenceData = new ReferenceEventRequest(); if (qParams.email != null && qParams.email.indexOf("@") > -1) { diff --git a/apps/web/src/app/accounts/sso.component.ts b/apps/web/src/app/accounts/sso.component.ts index 35a9458cd4..111d5f2a36 100644 --- a/apps/web/src/app/accounts/sso.component.ts +++ b/apps/web/src/app/accounts/sso.component.ts @@ -17,6 +17,7 @@ import { StateService } from "@bitwarden/common/abstractions/state.service"; selector: "app-sso", templateUrl: "sso.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SsoComponent extends BaseSsoComponent { constructor( authService: AuthService, @@ -50,6 +51,7 @@ export class SsoComponent extends BaseSsoComponent { async ngOnInit() { super.ngOnInit(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.identifier != null) { this.identifier = qParams.identifier; diff --git a/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.ts b/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.ts index 45f4815f47..00bbc6e236 100644 --- a/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.ts +++ b/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.ts @@ -24,6 +24,7 @@ import { VerticalStepperComponent } from "./vertical-stepper/vertical-stepper.co selector: "app-trial", templateUrl: "trial-initiation.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TrialInitiationComponent implements OnInit { email = ""; org = ""; @@ -76,6 +77,7 @@ export class TrialInitiationComponent implements OnInit { ) {} async ngOnInit(): Promise { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.route.queryParams.pipe(first()).subscribe((qParams) => { this.referenceData = new ReferenceEventRequest(); if (qParams.email != null && qParams.email.indexOf("@") > -1) { diff --git a/apps/web/src/app/accounts/two-factor.component.ts b/apps/web/src/app/accounts/two-factor.component.ts index 1d9b19af21..5ebf3ea02e 100644 --- a/apps/web/src/app/accounts/two-factor.component.ts +++ b/apps/web/src/app/accounts/two-factor.component.ts @@ -22,6 +22,7 @@ import { TwoFactorOptionsComponent } from "./two-factor-options.component"; selector: "app-two-factor", templateUrl: "two-factor.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TwoFactorComponent extends BaseTwoFactorComponent { @ViewChild("twoFactorOptions", { read: ViewContainerRef, static: true }) twoFactorOptionsModal: ViewContainerRef; @@ -63,11 +64,13 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { TwoFactorOptionsComponent, this.twoFactorOptionsModal, (comp) => { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => { modal.close(); this.selectedProviderType = provider; await this.init(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onRecoverSelected.subscribe(() => { modal.close(); }); diff --git a/apps/web/src/app/accounts/verify-email-token.component.ts b/apps/web/src/app/accounts/verify-email-token.component.ts index 90983f7cf0..c0ebfa78d7 100644 --- a/apps/web/src/app/accounts/verify-email-token.component.ts +++ b/apps/web/src/app/accounts/verify-email-token.component.ts @@ -13,6 +13,7 @@ import { VerifyEmailRequest } from "@bitwarden/common/models/request/verifyEmail selector: "app-verify-email-token", templateUrl: "verify-email-token.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class VerifyEmailTokenComponent implements OnInit { constructor( private router: Router, @@ -25,6 +26,7 @@ export class VerifyEmailTokenComponent implements OnInit { ) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.userId != null && qParams.token != null) { try { diff --git a/apps/web/src/app/accounts/verify-recover-delete.component.ts b/apps/web/src/app/accounts/verify-recover-delete.component.ts index 3deadbd4d4..7139e4d10e 100644 --- a/apps/web/src/app/accounts/verify-recover-delete.component.ts +++ b/apps/web/src/app/accounts/verify-recover-delete.component.ts @@ -12,6 +12,7 @@ import { VerifyDeleteRecoverRequest } from "@bitwarden/common/models/request/ver selector: "app-verify-recover-delete", templateUrl: "verify-recover-delete.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class VerifyRecoverDeleteComponent implements OnInit { email: string; formPromise: Promise; @@ -29,6 +30,7 @@ export class VerifyRecoverDeleteComponent implements OnInit { ) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.userId != null && qParams.token != null && qParams.email != null) { this.userId = qParams.userId; diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index ef80dc5e73..ae9107ea0e 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -215,7 +215,7 @@ export class AppComponent implements OnDestroy, OnInit { ngOnDestroy() { this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); this.destroy$.next(); - this.destroy$.unsubscribe(); + this.destroy$.complete(); } private async logOut(expired: boolean) { diff --git a/apps/web/src/app/common/base.accept.component.ts b/apps/web/src/app/common/base.accept.component.ts index 907d7410f8..dcca9e061c 100644 --- a/apps/web/src/app/common/base.accept.component.ts +++ b/apps/web/src/app/common/base.accept.component.ts @@ -29,6 +29,7 @@ export abstract class BaseAcceptComponent implements OnInit { abstract unauthedHandler(qParams: Params): Promise; ngOnInit() { + // eslint-disable-next-line rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { let error = this.requiredParameters.some((e) => qParams?.[e] == null || qParams[e] === ""); let errorMessage: string = null; diff --git a/apps/web/src/app/common/base.people.component.ts b/apps/web/src/app/common/base.people.component.ts index 47737a4b0b..6b9370ae81 100644 --- a/apps/web/src/app/common/base.people.component.ts +++ b/apps/web/src/app/common/base.people.component.ts @@ -343,6 +343,7 @@ export abstract class BasePeopleComponent< comp.name = this.userNamePipe.transform(user); comp.userId = user != null ? user.userId : null; comp.publicKey = publicKey; + // eslint-disable-next-line rxjs/no-async-subscribe comp.onConfirmedUser.subscribe(async () => { try { comp.formPromise = confirmUser(publicKey); diff --git a/apps/web/src/app/layouts/navbar.component.ts b/apps/web/src/app/layouts/navbar.component.ts index c5a6b03cad..bbd4644bdb 100644 --- a/apps/web/src/app/layouts/navbar.component.ts +++ b/apps/web/src/app/layouts/navbar.component.ts @@ -18,6 +18,7 @@ import { canAccessOrgAdmin } from "../organizations/navigation-permissions"; selector: "app-navbar", templateUrl: "navbar.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class NavbarComponent implements OnInit { selfHosted = false; name: string; diff --git a/apps/web/src/app/organizations/layouts/organization-layout.component.ts b/apps/web/src/app/organizations/layouts/organization-layout.component.ts index d5a0a668da..7d89b14a8b 100644 --- a/apps/web/src/app/organizations/layouts/organization-layout.component.ts +++ b/apps/web/src/app/organizations/layouts/organization-layout.component.ts @@ -31,6 +31,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy { ngOnInit() { document.body.classList.remove("layout_frontend"); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.params.subscribe(async (params: any) => { this.organizationId = params.organizationId; await this.load(); diff --git a/apps/web/src/app/organizations/manage/collections.component.ts b/apps/web/src/app/organizations/manage/collections.component.ts index e935e7b10b..04867a4eab 100644 --- a/apps/web/src/app/organizations/manage/collections.component.ts +++ b/apps/web/src/app/organizations/manage/collections.component.ts @@ -27,6 +27,7 @@ import { EntityUsersComponent } from "./entity-users.component"; selector: "app-org-manage-collections", templateUrl: "collections.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CollectionsComponent implements OnInit { @ViewChild("addEdit", { read: ViewContainerRef, static: true }) addEditModalRef: ViewContainerRef; @ViewChild("usersTemplate", { read: ViewContainerRef, static: true }) @@ -59,9 +60,11 @@ export class CollectionsComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.searchText = qParams.search; }); @@ -131,10 +134,12 @@ export class CollectionsComponent implements OnInit { comp.collectionId = collection != null ? collection.id : null; comp.canSave = canCreate || canEdit; comp.canDelete = canDelete; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSavedCollection.subscribe(() => { modal.close(); this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeletedCollection.subscribe(() => { modal.close(); this.removeCollection(collection); @@ -183,6 +188,7 @@ export class CollectionsComponent implements OnInit { comp.entityId = collection.id; comp.entityName = collection.name; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onEditedUsers.subscribe(() => { this.load(); modal.close(); diff --git a/apps/web/src/app/organizations/manage/events.component.ts b/apps/web/src/app/organizations/manage/events.component.ts index e16d7c4b6d..6573543d0d 100644 --- a/apps/web/src/app/organizations/manage/events.component.ts +++ b/apps/web/src/app/organizations/manage/events.component.ts @@ -20,6 +20,7 @@ import { EventService } from "../../core"; selector: "app-org-events", templateUrl: "events.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class EventsComponent extends BaseEventsComponent implements OnInit { exportFileName = "org-events"; organizationId: string; @@ -52,6 +53,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; this.organization = await this.organizationService.get(this.organizationId); diff --git a/apps/web/src/app/organizations/manage/groups.component.ts b/apps/web/src/app/organizations/manage/groups.component.ts index d09acfae30..419e3ab641 100644 --- a/apps/web/src/app/organizations/manage/groups.component.ts +++ b/apps/web/src/app/organizations/manage/groups.component.ts @@ -18,6 +18,7 @@ import { GroupAddEditComponent } from "./group-add-edit.component"; selector: "app-org-groups", templateUrl: "groups.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class GroupsComponent implements OnInit { @ViewChild("addEdit", { read: ViewContainerRef, static: true }) addEditModalRef: ViewContainerRef; @ViewChild("usersTemplate", { read: ViewContainerRef, static: true }) @@ -45,9 +46,11 @@ export class GroupsComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.searchText = qParams.search; }); @@ -88,10 +91,12 @@ export class GroupsComponent implements OnInit { (comp) => { comp.organizationId = this.organizationId; comp.groupId = group != null ? group.id : null; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSavedGroup.subscribe(() => { modal.close(); this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeletedGroup.subscribe(() => { modal.close(); this.removeGroup(group); @@ -139,6 +144,7 @@ export class GroupsComponent implements OnInit { comp.entityId = group.id; comp.entityName = group.name; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onEditedUsers.subscribe(() => { modal.close(); }); diff --git a/apps/web/src/app/organizations/manage/manage.component.ts b/apps/web/src/app/organizations/manage/manage.component.ts index f9026f5570..f1e2509259 100644 --- a/apps/web/src/app/organizations/manage/manage.component.ts +++ b/apps/web/src/app/organizations/manage/manage.component.ts @@ -8,12 +8,14 @@ import { Organization } from "@bitwarden/common/models/domain/organization"; selector: "app-org-manage", templateUrl: "manage.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ManageComponent implements OnInit { organization: Organization; constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); }); diff --git a/apps/web/src/app/organizations/manage/people.component.ts b/apps/web/src/app/organizations/manage/people.component.ts index 63028e0cad..8487760249 100644 --- a/apps/web/src/app/organizations/manage/people.component.ts +++ b/apps/web/src/app/organizations/manage/people.component.ts @@ -43,6 +43,7 @@ import { UserGroupsComponent } from "./user-groups.component"; selector: "app-org-people", templateUrl: "people.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class PeopleComponent extends BasePeopleComponent implements OnInit @@ -112,6 +113,7 @@ export class PeopleComponent } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; const organization = await this.organizationService.get(this.organizationId); @@ -138,6 +140,7 @@ export class PeopleComponent await this.load(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.searchText = qParams.search; if (qParams.viewEvents != null) { @@ -237,18 +240,22 @@ export class PeopleComponent comp.organizationId = this.organizationId; comp.organizationUserId = user != null ? user.id : null; comp.usesKeyConnector = user?.usesKeyConnector; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSavedUser.subscribe(() => { modal.close(); this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeletedUser.subscribe(() => { modal.close(); this.removeUser(user); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onRevokedUser.subscribe(() => { modal.close(); this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onRestoredUser.subscribe(() => { modal.close(); this.load(); @@ -265,6 +272,7 @@ export class PeopleComponent comp.name = this.userNamePipe.transform(user); comp.organizationId = this.organizationId; comp.organizationUserId = user != null ? user.id : null; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSavedUser.subscribe(() => { modal.close(); }); @@ -389,6 +397,7 @@ export class PeopleComponent comp.organizationId = this.organizationId; comp.id = user != null ? user.id : null; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onPasswordReset.subscribe(() => { modal.close(); this.load(); @@ -427,6 +436,7 @@ export class PeopleComponent // Workaround to handle closing the modal shortly after it has been opened let close = false; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil modal.onShown.subscribe(() => { if (close) { modal.close(); diff --git a/apps/web/src/app/organizations/manage/policies.component.ts b/apps/web/src/app/organizations/manage/policies.component.ts index 17cc3b7bbe..b9f11322de 100644 --- a/apps/web/src/app/organizations/manage/policies.component.ts +++ b/apps/web/src/app/organizations/manage/policies.component.ts @@ -18,6 +18,7 @@ import { PolicyEditComponent } from "./policy-edit.component"; selector: "app-org-policies", templateUrl: "policies.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class PoliciesComponent implements OnInit { @ViewChild("editTemplate", { read: ViewContainerRef, static: true }) editModalRef: ViewContainerRef; @@ -40,6 +41,7 @@ export class PoliciesComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; this.organization = await this.organizationService.get(this.organizationId); @@ -48,6 +50,7 @@ export class PoliciesComponent implements OnInit { await this.load(); // Handle policies component launch from Event message + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.policyId != null) { const policyIdFromEvents: string = qParams.policyId; @@ -85,6 +88,7 @@ export class PoliciesComponent implements OnInit { comp.policy = policy; comp.organizationId = this.organizationId; comp.policiesEnabledMap = this.policiesEnabledMap; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSavedPolicy.subscribe(() => { modal.close(); this.load(); diff --git a/apps/web/src/app/organizations/settings/account.component.ts b/apps/web/src/app/organizations/settings/account.component.ts index 9893fa73cf..e689d530e0 100644 --- a/apps/web/src/app/organizations/settings/account.component.ts +++ b/apps/web/src/app/organizations/settings/account.component.ts @@ -24,6 +24,7 @@ import { DeleteOrganizationComponent } from "./delete-organization.component"; selector: "app-org-account", templateUrl: "account.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AccountComponent { @ViewChild("deleteOrganizationTemplate", { read: ViewContainerRef, static: true }) deleteModalRef: ViewContainerRef; @@ -62,6 +63,7 @@ export class AccountComponent { async ngOnInit() { this.selfHosted = this.platformUtilsService.isSelfHost(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; this.canManageBilling = ( @@ -118,6 +120,7 @@ export class AccountComponent { this.deleteModalRef, (comp) => { comp.organizationId = this.organizationId; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSuccess.subscribe(() => { this.router.navigate(["/"]); }); diff --git a/apps/web/src/app/organizations/settings/organization-billing.component.ts b/apps/web/src/app/organizations/settings/organization-billing.component.ts index c77a4e8b95..7cb05dc60d 100644 --- a/apps/web/src/app/organizations/settings/organization-billing.component.ts +++ b/apps/web/src/app/organizations/settings/organization-billing.component.ts @@ -14,6 +14,7 @@ import { BillingResponse } from "@bitwarden/common/models/response/billingRespon selector: "app-org-billing", templateUrl: "./organization-billing.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class OrganizationBillingComponent implements OnInit { loading = false; firstLoaded = false; @@ -39,6 +40,7 @@ export class OrganizationBillingComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); diff --git a/apps/web/src/app/organizations/settings/organization-subscription.component.ts b/apps/web/src/app/organizations/settings/organization-subscription.component.ts index 779b982d4e..cf80ff2af1 100644 --- a/apps/web/src/app/organizations/settings/organization-subscription.component.ts +++ b/apps/web/src/app/organizations/settings/organization-subscription.component.ts @@ -26,6 +26,7 @@ import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component"; selector: "app-org-subscription", templateUrl: "organization-subscription.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class OrganizationSubscriptionComponent implements OnInit { @ViewChild("setupBillingSyncTemplate", { read: ViewContainerRef, static: true }) setupBillingSyncModalRef: ViewContainerRef; @@ -72,6 +73,7 @@ export class OrganizationSubscriptionComponent implements OnInit { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); @@ -187,6 +189,7 @@ export class OrganizationSubscriptionComponent implements OnInit { comp.hasBillingToken = this.hasBillingSyncToken; } ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe ref.onClosed.subscribe(async () => { await this.load(); }); diff --git a/apps/web/src/app/organizations/settings/settings.component.ts b/apps/web/src/app/organizations/settings/settings.component.ts index 2a4f798c7f..318608524b 100644 --- a/apps/web/src/app/organizations/settings/settings.component.ts +++ b/apps/web/src/app/organizations/settings/settings.component.ts @@ -8,6 +8,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti selector: "app-org-settings", templateUrl: "settings.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SettingsComponent { access2fa = false; showBilling: boolean; @@ -19,6 +20,7 @@ export class SettingsComponent { ) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { const organization = await this.organizationService.get(params.organizationId); this.showBilling = !this.platformUtilsService.isSelfHost() && organization.canManageBilling; diff --git a/apps/web/src/app/organizations/settings/two-factor-setup.component.ts b/apps/web/src/app/organizations/settings/two-factor-setup.component.ts index c3684aa420..be82b0a86b 100644 --- a/apps/web/src/app/organizations/settings/two-factor-setup.component.ts +++ b/apps/web/src/app/organizations/settings/two-factor-setup.component.ts @@ -18,6 +18,7 @@ import { TwoFactorSetupComponent as BaseTwoFactorSetupComponent } from "../../se selector: "app-two-factor-setup", templateUrl: "../../settings/two-factor-setup.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent { constructor( apiService: ApiService, @@ -43,6 +44,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await super.ngOnInit(); @@ -55,6 +57,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent { const duoComp = await this.openModal(this.duoModalRef, TwoFactorDuoComponent); duoComp.type = TwoFactorProviderType.OrganizationDuo; duoComp.organizationId = this.organizationId; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil duoComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.OrganizationDuo); }); diff --git a/apps/web/src/app/organizations/sponsorships/families-for-enterprise-setup.component.ts b/apps/web/src/app/organizations/sponsorships/families-for-enterprise-setup.component.ts index ea8c90d7ef..8420fd9122 100644 --- a/apps/web/src/app/organizations/sponsorships/families-for-enterprise-setup.component.ts +++ b/apps/web/src/app/organizations/sponsorships/families-for-enterprise-setup.component.ts @@ -22,6 +22,7 @@ import { DeleteOrganizationComponent } from "../settings/delete-organization.com selector: "families-for-enterprise-setup", templateUrl: "families-for-enterprise-setup.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class FamiliesForEnterpriseSetupComponent implements OnInit { @ViewChild(OrganizationPlansComponent, { static: false }) set organizationPlansComponent(value: OrganizationPlansComponent) { @@ -32,6 +33,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit { value.plan = PlanType.FamiliesAnnually; value.product = ProductType.Families; value.acceptingSponsorship = true; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil value.onSuccess.subscribe(this.onOrganizationCreateSuccess.bind(this)); } @@ -63,6 +65,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit { async ngOnInit() { document.body.classList.remove("layout_frontend"); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { const error = qParams.token == null; if (error) { @@ -130,6 +133,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit { (comp) => { comp.organizationId = organizationId; comp.deleteOrganizationRequestType = "InvalidFamiliesForEnterprise"; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSuccess.subscribe(() => { this.router.navigate(["/"]); }); diff --git a/apps/web/src/app/organizations/tools/exposed-passwords-report.component.ts b/apps/web/src/app/organizations/tools/exposed-passwords-report.component.ts index d34e757d74..00c2ce2e3f 100644 --- a/apps/web/src/app/organizations/tools/exposed-passwords-report.component.ts +++ b/apps/web/src/app/organizations/tools/exposed-passwords-report.component.ts @@ -18,6 +18,7 @@ import { ExposedPasswordsReportComponent as BaseExposedPasswordsReportComponent selector: "app-org-exposed-passwords-report", templateUrl: "../../reports/pages/exposed-passwords-report.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ExposedPasswordsReportComponent extends BaseExposedPasswordsReportComponent { manageableCiphers: Cipher[]; @@ -42,6 +43,7 @@ export class ExposedPasswordsReportComponent extends BaseExposedPasswordsReportC } ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); this.manageableCiphers = await this.cipherService.getAll(); diff --git a/apps/web/src/app/organizations/tools/import-export/org-export.component.ts b/apps/web/src/app/organizations/tools/import-export/org-export.component.ts index 79f9254231..c2803cab9b 100644 --- a/apps/web/src/app/organizations/tools/import-export/org-export.component.ts +++ b/apps/web/src/app/organizations/tools/import-export/org-export.component.ts @@ -19,6 +19,7 @@ import { ExportComponent } from "../../../tools/import-export/export.component"; selector: "app-org-export", templateUrl: "../../../tools/import-export/export.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class OrganizationExportComponent extends ExportComponent { constructor( cryptoService: CryptoService, @@ -48,6 +49,7 @@ export class OrganizationExportComponent extends ExportComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; }); diff --git a/apps/web/src/app/organizations/tools/import-export/org-import.component.ts b/apps/web/src/app/organizations/tools/import-export/org-import.component.ts index 504163a76f..5d24a2cfd4 100644 --- a/apps/web/src/app/organizations/tools/import-export/org-import.component.ts +++ b/apps/web/src/app/organizations/tools/import-export/org-import.component.ts @@ -14,6 +14,7 @@ import { ImportComponent } from "../../../tools/import-export/import.component"; selector: "app-org-import", templateUrl: "../../../tools/import-export/import.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class OrganizationImportComponent extends ImportComponent { organizationName: string; @@ -31,6 +32,7 @@ export class OrganizationImportComponent extends ImportComponent { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; this.successNavigate = ["organizations", this.organizationId, "vault"]; diff --git a/apps/web/src/app/organizations/tools/inactive-two-factor-report.component.ts b/apps/web/src/app/organizations/tools/inactive-two-factor-report.component.ts index 56e9625511..80fe51d32d 100644 --- a/apps/web/src/app/organizations/tools/inactive-two-factor-report.component.ts +++ b/apps/web/src/app/organizations/tools/inactive-two-factor-report.component.ts @@ -17,6 +17,7 @@ import { InactiveTwoFactorReportComponent as BaseInactiveTwoFactorReportComponen selector: "app-inactive-two-factor-report", templateUrl: "../../reports/pages/inactive-two-factor-report.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class InactiveTwoFactorReportComponent extends BaseInactiveTwoFactorReportComponent { constructor( cipherService: CipherService, @@ -39,6 +40,7 @@ export class InactiveTwoFactorReportComponent extends BaseInactiveTwoFactorRepor } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); await super.ngOnInit(); diff --git a/apps/web/src/app/organizations/tools/reused-passwords-report.component.ts b/apps/web/src/app/organizations/tools/reused-passwords-report.component.ts index 1f97546cf3..98a62cd83a 100644 --- a/apps/web/src/app/organizations/tools/reused-passwords-report.component.ts +++ b/apps/web/src/app/organizations/tools/reused-passwords-report.component.ts @@ -17,6 +17,7 @@ import { ReusedPasswordsReportComponent as BaseReusedPasswordsReportComponent } selector: "app-reused-passwords-report", templateUrl: "../../reports/pages/reused-passwords-report.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ReusedPasswordsReportComponent extends BaseReusedPasswordsReportComponent { manageableCiphers: Cipher[]; @@ -33,6 +34,7 @@ export class ReusedPasswordsReportComponent extends BaseReusedPasswordsReportCom } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); this.manageableCiphers = await this.cipherService.getAll(); diff --git a/apps/web/src/app/organizations/tools/tools.component.ts b/apps/web/src/app/organizations/tools/tools.component.ts index cfff58a682..249e5cd2ca 100644 --- a/apps/web/src/app/organizations/tools/tools.component.ts +++ b/apps/web/src/app/organizations/tools/tools.component.ts @@ -9,6 +9,7 @@ import { Organization } from "@bitwarden/common/models/domain/organization"; selector: "app-org-tools", templateUrl: "tools.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ToolsComponent { organization: Organization; accessReports = false; @@ -21,6 +22,7 @@ export class ToolsComponent { ) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); // TODO: Maybe we want to just make sure they are not on a free plan? Just compare useTotp for now diff --git a/apps/web/src/app/organizations/tools/unsecured-websites-report.component.ts b/apps/web/src/app/organizations/tools/unsecured-websites-report.component.ts index f636303bb0..b1e99c50fc 100644 --- a/apps/web/src/app/organizations/tools/unsecured-websites-report.component.ts +++ b/apps/web/src/app/organizations/tools/unsecured-websites-report.component.ts @@ -16,6 +16,7 @@ import { UnsecuredWebsitesReportComponent as BaseUnsecuredWebsitesReportComponen selector: "app-unsecured-websites-report", templateUrl: "../../reports/pages/unsecured-websites-report.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class UnsecuredWebsitesReportComponent extends BaseUnsecuredWebsitesReportComponent { constructor( cipherService: CipherService, @@ -30,6 +31,7 @@ export class UnsecuredWebsitesReportComponent extends BaseUnsecuredWebsitesRepor } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); await super.ngOnInit(); diff --git a/apps/web/src/app/organizations/tools/weak-passwords-report.component.ts b/apps/web/src/app/organizations/tools/weak-passwords-report.component.ts index 306b861f36..9b5d95b637 100644 --- a/apps/web/src/app/organizations/tools/weak-passwords-report.component.ts +++ b/apps/web/src/app/organizations/tools/weak-passwords-report.component.ts @@ -18,6 +18,7 @@ import { WeakPasswordsReportComponent as BaseWeakPasswordsReportComponent } from selector: "app-weak-passwords-report", templateUrl: "../../reports/pages/weak-passwords-report.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class WeakPasswordsReportComponent extends BaseWeakPasswordsReportComponent { manageableCiphers: Cipher[]; @@ -42,6 +43,7 @@ export class WeakPasswordsReportComponent extends BaseWeakPasswordsReportCompone } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organization = await this.organizationService.get(params.organizationId); this.manageableCiphers = await this.cipherService.getAll(); diff --git a/apps/web/src/app/organizations/vault/vault.component.ts b/apps/web/src/app/organizations/vault/vault.component.ts index 953a05f3d8..c25e565e78 100644 --- a/apps/web/src/app/organizations/vault/vault.component.ts +++ b/apps/web/src/app/organizations/vault/vault.component.ts @@ -86,11 +86,13 @@ export class VaultComponent implements OnInit, OnDestroy { ? "trashCleanupWarningSelfHosted" : "trashCleanupWarning" ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params: any) => { this.organization = await this.organizationService.get(params.organizationId); this.vaultFilterComponent.organization = this.organization; this.ciphersComponent.organization = this.organization; + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.ciphersComponent.searchText = this.vaultFilterComponent.searchText = qParams.search; if (!this.organization.canViewAllCollections) { @@ -126,6 +128,7 @@ export class VaultComponent implements OnInit, OnDestroy { } } + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.subscribe(async (params) => { const cipherId = getCipherIdFromParams(params); if (cipherId) { @@ -191,11 +194,14 @@ export class VaultComponent implements OnInit, OnDestroy { (comp) => { comp.organization = this.organization; comp.cipherId = cipher.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onUploadedAttachment.subscribe(() => (madeAttachmentChanges = true)); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeletedAttachment.subscribe(() => (madeAttachmentChanges = true)); } ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe modal.onClosed.subscribe(async () => { if (madeAttachmentChanges) { await this.ciphersComponent.refresh(); @@ -217,6 +223,7 @@ export class VaultComponent implements OnInit, OnDestroy { } comp.organization = this.organization; comp.cipherId = cipher.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedCollections.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -258,14 +265,17 @@ export class VaultComponent implements OnInit, OnDestroy { (comp) => { comp.organization = this.organization; comp.cipherId = cipherId; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onDeletedCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onRestoredCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); diff --git a/apps/web/src/app/reports/pages/cipher-report.component.ts b/apps/web/src/app/reports/pages/cipher-report.component.ts index 9179c04371..44d7cae619 100644 --- a/apps/web/src/app/reports/pages/cipher-report.component.ts +++ b/apps/web/src/app/reports/pages/cipher-report.component.ts @@ -53,14 +53,17 @@ export class CipherReportComponent { } comp.cipherId = cipher == null ? null : cipher.id; + // eslint-disable-next-line rxjs/no-async-subscribe comp.onSavedCipher.subscribe(async () => { modal.close(); await this.load(); }); + // eslint-disable-next-line rxjs/no-async-subscribe comp.onDeletedCipher.subscribe(async () => { modal.close(); await this.load(); }); + // eslint-disable-next-line rxjs/no-async-subscribe comp.onRestoredCipher.subscribe(async () => { modal.close(); await this.load(); diff --git a/apps/web/src/app/reports/reports-layout.component.ts b/apps/web/src/app/reports/reports-layout.component.ts index 3d3fee2904..7bfe912c1a 100644 --- a/apps/web/src/app/reports/reports-layout.component.ts +++ b/apps/web/src/app/reports/reports-layout.component.ts @@ -14,6 +14,7 @@ export class ReportsLayoutComponent implements OnDestroy { constructor(router: Router) { this.subscription = router.events .pipe(filter((event) => event instanceof NavigationEnd)) + // eslint-disable-next-line rxjs-angular/prefer-takeuntil .subscribe((event) => { this.homepage = (event as NavigationEnd).url == "/reports"; }); diff --git a/apps/web/src/app/send/access.component.ts b/apps/web/src/app/send/access.component.ts index 707a5bef63..7f4c6bbab8 100644 --- a/apps/web/src/app/send/access.component.ts +++ b/apps/web/src/app/send/access.component.ts @@ -22,6 +22,7 @@ import { SendAccessView } from "@bitwarden/common/models/view/sendAccessView"; selector: "app-send-access", templateUrl: "access.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AccessComponent implements OnInit { send: SendAccessView; sendType = SendType; @@ -72,6 +73,7 @@ export class AccessComponent implements OnInit { } ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.params.subscribe(async (params) => { this.id = params.sendId; this.key = params.key; diff --git a/apps/web/src/app/send/send.component.ts b/apps/web/src/app/send/send.component.ts index 4024f7c18f..2719d90456 100644 --- a/apps/web/src/app/send/send.component.ts +++ b/apps/web/src/app/send/send.component.ts @@ -85,10 +85,12 @@ export class SendComponent extends BaseSendComponent { this.sendAddEditModalRef, (comp) => { comp.sendId = send == null ? null : send.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedSend.subscribe(async () => { modal.close(); await this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onDeletedSend.subscribe(async () => { modal.close(); await this.load(); diff --git a/apps/web/src/app/settings/create-organization.component.ts b/apps/web/src/app/settings/create-organization.component.ts index fc6caf815a..6cae85c940 100644 --- a/apps/web/src/app/settings/create-organization.component.ts +++ b/apps/web/src/app/settings/create-organization.component.ts @@ -11,6 +11,7 @@ import { OrganizationPlansComponent } from "./organization-plans.component"; selector: "app-create-organization", templateUrl: "create-organization.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CreateOrganizationComponent implements OnInit { @ViewChild(OrganizationPlansComponent, { static: true }) orgPlansComponent: OrganizationPlansComponent; @@ -18,6 +19,7 @@ export class CreateOrganizationComponent implements OnInit { constructor(private route: ActivatedRoute) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.plan === "families") { this.orgPlansComponent.plan = PlanType.FamiliesAnnually; diff --git a/apps/web/src/app/settings/emergency-access-view.component.ts b/apps/web/src/app/settings/emergency-access-view.component.ts index acdf6e43e2..f40113a5ad 100644 --- a/apps/web/src/app/settings/emergency-access-view.component.ts +++ b/apps/web/src/app/settings/emergency-access-view.component.ts @@ -18,6 +18,7 @@ import { EmergencyAddEditComponent } from "./emergency-add-edit.component"; selector: "emergency-access-view", templateUrl: "emergency-access-view.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class EmergencyAccessViewComponent implements OnInit { @ViewChild("cipherAddEdit", { read: ViewContainerRef, static: true }) cipherAddEditModalRef: ViewContainerRef; @@ -38,6 +39,7 @@ export class EmergencyAccessViewComponent implements OnInit { ) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.route.params.subscribe((qParams) => { if (qParams.id == null) { return this.router.navigate(["settings/emergency-access"]); diff --git a/apps/web/src/app/settings/emergency-access.component.ts b/apps/web/src/app/settings/emergency-access.component.ts index fec4ea59df..a5fe4099b0 100644 --- a/apps/web/src/app/settings/emergency-access.component.ts +++ b/apps/web/src/app/settings/emergency-access.component.ts @@ -27,6 +27,7 @@ import { EmergencyAccessTakeoverComponent } from "./emergency-access-takeover.co selector: "emergency-access", templateUrl: "emergency-access.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class EmergencyAccessComponent implements OnInit { @ViewChild("addEdit", { read: ViewContainerRef, static: true }) addEditModalRef: ViewContainerRef; @ViewChild("takeoverTemplate", { read: ViewContainerRef, static: true }) @@ -84,10 +85,12 @@ export class EmergencyAccessComponent implements OnInit { comp.name = this.userNamePipe.transform(details); comp.emergencyAccessId = details?.id; comp.readOnly = !this.canAccessPremium; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onSaved.subscribe(() => { modal.close(); this.load(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeleted.subscribe(() => { modal.close(); this.remove(details); @@ -132,6 +135,7 @@ export class EmergencyAccessComponent implements OnInit { comp.name = this.userNamePipe.transform(contact); comp.emergencyAccessId = contact.id; comp.userId = contact?.granteeId; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onConfirmed.subscribe(async () => { modal.close(); @@ -264,6 +268,7 @@ export class EmergencyAccessComponent implements OnInit { comp.email = details.email; comp.emergencyAccessId = details != null ? details.id : null; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDone.subscribe(() => { modal.close(); this.platformUtilsService.showToast( diff --git a/apps/web/src/app/settings/payment.component.ts b/apps/web/src/app/settings/payment.component.ts index a4de1521c3..d0f4407b35 100644 --- a/apps/web/src/app/settings/payment.component.ts +++ b/apps/web/src/app/settings/payment.component.ts @@ -27,7 +27,7 @@ export class PaymentComponent implements OnInit, OnDestroy { @Input() hideCredit = false; @Input() trialFlow = false; - private destroy$: Subject = new Subject(); + private destroy$ = new Subject(); bank: any = { routing_number: null, diff --git a/apps/web/src/app/settings/tax-info.component.ts b/apps/web/src/app/settings/tax-info.component.ts index d88349465c..216a0d030a 100644 --- a/apps/web/src/app/settings/tax-info.component.ts +++ b/apps/web/src/app/settings/tax-info.component.ts @@ -18,6 +18,7 @@ type TaxInfoView = Omit & { selector: "app-tax-info", templateUrl: "tax-info.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TaxInfoComponent { @Input() trialFlow = false; @Output() onCountryChanged = new EventEmitter(); @@ -56,6 +57,7 @@ export class TaxInfoComponent { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; if (this.organizationId) { diff --git a/apps/web/src/app/settings/two-factor-setup.component.ts b/apps/web/src/app/settings/two-factor-setup.component.ts index 35c8a0f16d..13e3cbecea 100644 --- a/apps/web/src/app/settings/two-factor-setup.component.ts +++ b/apps/web/src/app/settings/two-factor-setup.component.ts @@ -25,6 +25,7 @@ import { TwoFactorYubiKeyComponent } from "./two-factor-yubikey.component"; selector: "app-two-factor-setup", templateUrl: "two-factor-setup.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class TwoFactorSetupComponent implements OnInit { @ViewChild("recoveryTemplate", { read: ViewContainerRef, static: true }) recoveryModalRef: ViewContainerRef; @@ -116,6 +117,7 @@ export class TwoFactorSetupComponent implements OnInit { this.authenticatorModalRef, TwoFactorAuthenticatorComponent ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil authComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.Authenticator); }); @@ -123,6 +125,7 @@ export class TwoFactorSetupComponent implements OnInit { } case TwoFactorProviderType.Yubikey: { const yubiComp = await this.openModal(this.yubikeyModalRef, TwoFactorYubiKeyComponent); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil yubiComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.Yubikey); }); @@ -130,6 +133,7 @@ export class TwoFactorSetupComponent implements OnInit { } case TwoFactorProviderType.Duo: { const duoComp = await this.openModal(this.duoModalRef, TwoFactorDuoComponent); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil duoComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.Duo); }); @@ -137,6 +141,7 @@ export class TwoFactorSetupComponent implements OnInit { } case TwoFactorProviderType.Email: { const emailComp = await this.openModal(this.emailModalRef, TwoFactorEmailComponent); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil emailComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.Email); }); @@ -147,6 +152,7 @@ export class TwoFactorSetupComponent implements OnInit { this.webAuthnModalRef, TwoFactorWebAuthnComponent ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil webAuthnComp.onUpdated.subscribe((enabled: boolean) => { this.updateStatus(enabled, TwoFactorProviderType.WebAuthn); }); diff --git a/apps/web/src/app/vault/bulk-actions.component.ts b/apps/web/src/app/vault/bulk-actions.component.ts index 3b1fff1c3d..7f81ef0a5a 100644 --- a/apps/web/src/app/vault/bulk-actions.component.ts +++ b/apps/web/src/app/vault/bulk-actions.component.ts @@ -17,6 +17,7 @@ import { CiphersComponent } from "./ciphers.component"; selector: "app-vault-bulk-actions", templateUrl: "bulk-actions.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class BulkActionsComponent { @Input() ciphersComponent: CiphersComponent; @Input() deleted: boolean; @@ -60,6 +61,7 @@ export class BulkActionsComponent { comp.permanent = this.deleted; comp.cipherIds = selectedIds; comp.organization = this.organization; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onDeleted.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -88,6 +90,7 @@ export class BulkActionsComponent { this.bulkRestoreModalRef, (comp) => { comp.cipherIds = selectedIds; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onRestored.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -116,6 +119,7 @@ export class BulkActionsComponent { this.bulkShareModalRef, (comp) => { comp.ciphers = selectedCiphers; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onShared.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -144,6 +148,7 @@ export class BulkActionsComponent { this.bulkMoveModalRef, (comp) => { comp.cipherIds = selectedIds; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onMoved.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); diff --git a/apps/web/src/app/vault/vault-filter/vault-filter.component.ts b/apps/web/src/app/vault/vault-filter/vault-filter.component.ts index dfb30a601c..aaa2c839a9 100644 --- a/apps/web/src/app/vault/vault-filter/vault-filter.component.ts +++ b/apps/web/src/app/vault/vault-filter/vault-filter.component.ts @@ -8,6 +8,7 @@ import { VaultFilterService } from "./shared/vault-filter.service"; selector: "./app-vault-filter", templateUrl: "vault-filter.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class VaultFilterComponent extends BaseVaultFilterComponent { @Output() onSearchTextChanged = new EventEmitter(); @@ -22,6 +23,7 @@ export class VaultFilterComponent extends BaseVaultFilterComponent { async ngOnInit() { await super.ngOnInit(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.vaultFilterService.collapsedFilterNodes$.subscribe((nodes) => { this.collapsedFilterNodes = nodes; }); diff --git a/apps/web/src/app/vault/vault.component.ts b/apps/web/src/app/vault/vault.component.ts index a9f09083ef..4430328dd3 100644 --- a/apps/web/src/app/vault/vault.component.ts +++ b/apps/web/src/app/vault/vault.component.ts @@ -97,6 +97,7 @@ export class VaultComponent implements OnInit, OnDestroy { : "trashCleanupWarning" ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { await this.syncService.fullSync(false); const canAccessPremium = await this.stateService.getCanAccessPremium(); @@ -120,6 +121,7 @@ export class VaultComponent implements OnInit, OnDestroy { } await this.ciphersComponent.reload(); + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.subscribe(async (params) => { const cipherId = getCipherIdFromParams(params); if (cipherId) { @@ -221,12 +223,16 @@ export class VaultComponent implements OnInit, OnDestroy { this.attachmentsModalRef, (comp) => { comp.cipherId = cipher.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onUploadedAttachment.subscribe(() => (madeAttachmentChanges = true)); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onDeletedAttachment.subscribe(() => (madeAttachmentChanges = true)); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil comp.onReuploadedAttachment.subscribe(() => (madeAttachmentChanges = true)); } ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe modal.onClosed.subscribe(async () => { if (madeAttachmentChanges) { await this.ciphersComponent.refresh(); @@ -241,6 +247,7 @@ export class VaultComponent implements OnInit, OnDestroy { this.shareModalRef, (comp) => { comp.cipherId = cipher.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSharedCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -255,6 +262,7 @@ export class VaultComponent implements OnInit, OnDestroy { this.collectionsModalRef, (comp) => { comp.cipherId = cipher.id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedCollections.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); @@ -269,6 +277,7 @@ export class VaultComponent implements OnInit, OnDestroy { this.folderAddEditModalRef, (comp) => { comp.folderId = null; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedFolder.subscribe(async () => { modal.close(); await this.filterComponent.reloadCollectionsAndFolders(this.activeFilter); @@ -283,10 +292,12 @@ export class VaultComponent implements OnInit, OnDestroy { this.folderAddEditModalRef, (comp) => { comp.folderId = folderId; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedFolder.subscribe(async () => { modal.close(); await this.filterComponent.reloadCollectionsAndFolders(this.activeFilter); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onDeletedFolder.subscribe(async () => { modal.close(); await this.filterComponent.reloadCollectionsAndFolders(this.activeFilter); @@ -334,14 +345,17 @@ export class VaultComponent implements OnInit, OnDestroy { this.cipherAddEditModalRef, (comp) => { comp.cipherId = id; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onSavedCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onDeletedCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); }); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onRestoredCipher.subscribe(async () => { modal.close(); await this.ciphersComponent.refresh(); diff --git a/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.ts b/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.ts index 103ca0c80f..fcd3046696 100644 --- a/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.ts +++ b/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.ts @@ -20,6 +20,7 @@ import { OrganizationConnectionResponse } from "@bitwarden/common/models/respons selector: "app-org-manage-scim", templateUrl: "scim.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ScimComponent implements OnInit { loading = true; organizationId: string; @@ -45,6 +46,7 @@ export class ScimComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); diff --git a/bitwarden_license/bit-web/src/app/organizations/manage/sso.component.ts b/bitwarden_license/bit-web/src/app/organizations/manage/sso.component.ts index 99978b022b..16da7cb7b5 100644 --- a/bitwarden_license/bit-web/src/app/organizations/manage/sso.component.ts +++ b/bitwarden_license/bit-web/src/app/organizations/manage/sso.component.ts @@ -29,6 +29,7 @@ const defaultSigningAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha2 selector: "app-org-manage-sso", templateUrl: "sso.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SsoComponent implements OnInit { readonly ssoType = SsoType; @@ -153,6 +154,7 @@ export class SsoComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.ssoConfigForm.get("configType").valueChanges.subscribe((newType: SsoType) => { if (newType === SsoType.OpenIdConnect) { this.openIdForm.enable(); @@ -168,10 +170,12 @@ export class SsoComponent implements OnInit { this.samlForm .get("spSigningBehavior") + // eslint-disable-next-line rxjs-angular/prefer-takeuntil .valueChanges.subscribe(() => this.samlForm.get("idpX509PublicCert").updateValueAndValidity() ); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.organizationId = params.organizationId; await this.load(); diff --git a/bitwarden_license/bit-web/src/app/providers/clients/clients.component.ts b/bitwarden_license/bit-web/src/app/providers/clients/clients.component.ts index 5d48dafd57..697b2ac357 100644 --- a/bitwarden_license/bit-web/src/app/providers/clients/clients.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/clients/clients.component.ts @@ -30,6 +30,7 @@ const DisallowedPlanTypes = [ @Component({ templateUrl: "clients.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ClientsComponent implements OnInit { @ViewChild("add", { read: ViewContainerRef, static: true }) addModalRef: ViewContainerRef; @@ -64,11 +65,13 @@ export class ClientsComponent implements OnInit { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.providerId = params.providerId; await this.load(); + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.searchText = qParams.search; }); @@ -136,6 +139,7 @@ export class ClientsComponent implements OnInit { (comp) => { comp.providerId = this.providerId; comp.organizations = this.addableOrganizations; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe comp.onAddedOrganization.subscribe(async () => { try { await this.load(); diff --git a/bitwarden_license/bit-web/src/app/providers/clients/create-organization.component.ts b/bitwarden_license/bit-web/src/app/providers/clients/create-organization.component.ts index f04af8ad2f..79aafff50e 100644 --- a/bitwarden_license/bit-web/src/app/providers/clients/create-organization.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/clients/create-organization.component.ts @@ -7,6 +7,7 @@ import { OrganizationPlansComponent } from "src/app/settings/organization-plans. selector: "app-create-organization", templateUrl: "create-organization.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CreateOrganizationComponent implements OnInit { @ViewChild(OrganizationPlansComponent, { static: true }) orgPlansComponent: OrganizationPlansComponent; @@ -16,6 +17,7 @@ export class CreateOrganizationComponent implements OnInit { constructor(private route: ActivatedRoute) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.providerId = params.providerId; }); diff --git a/bitwarden_license/bit-web/src/app/providers/manage/events.component.ts b/bitwarden_license/bit-web/src/app/providers/manage/events.component.ts index b6273805e3..6806f156fe 100644 --- a/bitwarden_license/bit-web/src/app/providers/manage/events.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/manage/events.component.ts @@ -18,6 +18,7 @@ import { EventService } from "src/app/core"; selector: "provider-events", templateUrl: "events.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class EventsComponent extends BaseEventsComponent implements OnInit { exportFileName = "provider-events"; providerId: string; @@ -49,6 +50,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit { } async ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.providerId = params.providerId; const provider = await this.providerService.get(this.providerId); diff --git a/bitwarden_license/bit-web/src/app/providers/manage/manage.component.ts b/bitwarden_license/bit-web/src/app/providers/manage/manage.component.ts index 84173e6386..21c3562b61 100644 --- a/bitwarden_license/bit-web/src/app/providers/manage/manage.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/manage/manage.component.ts @@ -8,6 +8,7 @@ import { Provider } from "@bitwarden/common/models/domain/provider"; selector: "provider-manage", templateUrl: "manage.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ManageComponent implements OnInit { provider: Provider; accessEvents = false; @@ -15,6 +16,7 @@ export class ManageComponent implements OnInit { constructor(private route: ActivatedRoute, private providerService: ProviderService) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.provider = await this.providerService.get(params.providerId); this.accessEvents = this.provider.useEvents; diff --git a/bitwarden_license/bit-web/src/app/providers/manage/people.component.ts b/bitwarden_license/bit-web/src/app/providers/manage/people.component.ts index e0dc9923c4..2847009028 100644 --- a/bitwarden_license/bit-web/src/app/providers/manage/people.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/manage/people.component.ts @@ -34,6 +34,7 @@ import { UserAddEditComponent } from "./user-add-edit.component"; selector: "provider-people", templateUrl: "people.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class PeopleComponent extends BasePeopleComponent implements OnInit @@ -87,6 +88,7 @@ export class PeopleComponent } ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { this.providerId = params.providerId; const provider = await this.providerService.get(this.providerId); @@ -100,6 +102,7 @@ export class PeopleComponent await this.load(); + /* eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe */ this.route.queryParams.pipe(first()).subscribe(async (qParams) => { this.searchText = qParams.search; if (qParams.viewEvents != null) { diff --git a/bitwarden_license/bit-web/src/app/providers/providers-layout.component.ts b/bitwarden_license/bit-web/src/app/providers/providers-layout.component.ts index 09472e851e..fbd5ad0677 100644 --- a/bitwarden_license/bit-web/src/app/providers/providers-layout.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/providers-layout.component.ts @@ -8,6 +8,7 @@ import { Provider } from "@bitwarden/common/models/domain/provider"; selector: "providers-layout", templateUrl: "providers-layout.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class ProvidersLayoutComponent { provider: Provider; private providerId: string; @@ -16,6 +17,7 @@ export class ProvidersLayoutComponent { ngOnInit() { document.body.classList.remove("layout_frontend"); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.params.subscribe(async (params) => { this.providerId = params.providerId; await this.load(); diff --git a/bitwarden_license/bit-web/src/app/providers/settings/account.component.ts b/bitwarden_license/bit-web/src/app/providers/settings/account.component.ts index 44214afb41..4359cd9fb4 100644 --- a/bitwarden_license/bit-web/src/app/providers/settings/account.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/settings/account.component.ts @@ -13,6 +13,7 @@ import { ProviderResponse } from "@bitwarden/common/models/response/provider/pro selector: "provider-account", templateUrl: "account.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class AccountComponent { selfHosted = false; loading = true; @@ -33,6 +34,7 @@ export class AccountComponent { async ngOnInit() { this.selfHosted = this.platformUtilsService.isSelfHost(); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.parent.params.subscribe(async (params) => { this.providerId = params.providerId; try { diff --git a/bitwarden_license/bit-web/src/app/providers/settings/settings.component.ts b/bitwarden_license/bit-web/src/app/providers/settings/settings.component.ts index ad416bd9c4..e2b96f4ce4 100644 --- a/bitwarden_license/bit-web/src/app/providers/settings/settings.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/settings/settings.component.ts @@ -7,10 +7,12 @@ import { ProviderService } from "@bitwarden/common/abstractions/provider.service selector: "provider-settings", templateUrl: "settings.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SettingsComponent { constructor(private route: ActivatedRoute, private providerService: ProviderService) {} ngOnInit() { + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.parent.params.subscribe(async (params) => { await this.providerService.get(params.providerId); }); diff --git a/bitwarden_license/bit-web/src/app/providers/setup/setup.component.ts b/bitwarden_license/bit-web/src/app/providers/setup/setup.component.ts index 7bb71c7e02..4919cb7e9e 100644 --- a/bitwarden_license/bit-web/src/app/providers/setup/setup.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/setup/setup.component.ts @@ -14,6 +14,7 @@ import { ProviderSetupRequest } from "@bitwarden/common/models/request/provider/ selector: "provider-setup", templateUrl: "setup.component.html", }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class SetupComponent implements OnInit { loading = true; authed = false; @@ -38,6 +39,7 @@ export class SetupComponent implements OnInit { ngOnInit() { document.body.classList.remove("layout_frontend"); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { const error = qParams.providerId == null || qParams.email == null || qParams.token == null; diff --git a/libs/angular/src/components/generator.component.ts b/libs/angular/src/components/generator.component.ts index 90e5864dcb..41bcb98ad1 100644 --- a/libs/angular/src/components/generator.component.ts +++ b/libs/angular/src/components/generator.component.ts @@ -80,6 +80,7 @@ export class GeneratorComponent implements OnInit { } async ngOnInit() { + // eslint-disable-next-line rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { const passwordOptionsResponse = await this.passwordGenerationService.getOptions(); this.passwordOptions = passwordOptionsResponse[0]; diff --git a/libs/angular/src/components/lock.component.ts b/libs/angular/src/components/lock.component.ts index 2b2c1dbaef..63ed0e9f1d 100644 --- a/libs/angular/src/components/lock.component.ts +++ b/libs/angular/src/components/lock.component.ts @@ -58,6 +58,7 @@ export class LockComponent implements OnInit, OnDestroy { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs/no-async-subscribe this.activeAccountSubscription = this.stateService.activeAccount$.subscribe(async () => { await this.load(); }); diff --git a/libs/angular/src/components/set-password.component.ts b/libs/angular/src/components/set-password.component.ts index a41ccdfb60..36792a3f37 100644 --- a/libs/angular/src/components/set-password.component.ts +++ b/libs/angular/src/components/set-password.component.ts @@ -66,6 +66,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { await this.syncService.fullSync(true); this.syncLoading = false; + // eslint-disable-next-line rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.identifier != null) { this.identifier = qParams.identifier; diff --git a/libs/angular/src/components/settings/vault-timeout-input.component.ts b/libs/angular/src/components/settings/vault-timeout-input.component.ts index 6f620e5c3b..8b5b8c2476 100644 --- a/libs/angular/src/components/settings/vault-timeout-input.component.ts +++ b/libs/angular/src/components/settings/vault-timeout-input.component.ts @@ -66,6 +66,7 @@ export class VaultTimeoutInputComponent implements ControlValueAccessor, Validat this.validatorChange(); } + // eslint-disable-next-line rxjs/no-async-subscribe this.form.valueChanges.subscribe(async (value) => { this.onChange(this.getVaultTimeout(value)); }); diff --git a/libs/angular/src/components/sso.component.ts b/libs/angular/src/components/sso.component.ts index 2a1a3b9c52..f0f63c279a 100644 --- a/libs/angular/src/components/sso.component.ts +++ b/libs/angular/src/components/sso.component.ts @@ -53,6 +53,7 @@ export class SsoComponent { ) {} async ngOnInit() { + // eslint-disable-next-line rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (qParams) => { if (qParams.code != null && qParams.state != null) { const codeVerifier = await this.stateService.getSsoCodeVerifier(); diff --git a/libs/angular/src/components/user-verification.component.ts b/libs/angular/src/components/user-verification.component.ts index 04af868b34..198a214c49 100644 --- a/libs/angular/src/components/user-verification.component.ts +++ b/libs/angular/src/components/user-verification.component.ts @@ -30,6 +30,7 @@ import { Verification } from "@bitwarden/common/types/verification"; ]), ], }) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil export class UserVerificationComponent implements ControlValueAccessor, OnInit { usesKeyConnector = false; disableRequestOTP = false; @@ -48,6 +49,7 @@ export class UserVerificationComponent implements ControlValueAccessor, OnInit { this.usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector(); this.processChanges(this.secret.value); + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.secret.valueChanges.subscribe((secret: string) => this.processChanges(secret)); } diff --git a/libs/common/src/services/environment.service.ts b/libs/common/src/services/environment.service.ts index 1d62d471ad..d79b2b189d 100644 --- a/libs/common/src/services/environment.service.ts +++ b/libs/common/src/services/environment.service.ts @@ -1,4 +1,4 @@ -import { Observable, Subject } from "rxjs"; +import { concatMap, Observable, Subject } from "rxjs"; import { EnvironmentService as EnvironmentServiceAbstraction, @@ -22,9 +22,13 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { private scimUrl: string = null; constructor(private stateService: StateService) { - this.stateService.activeAccount$.subscribe(async () => { - await this.setUrlsFromStorage(); - }); + this.stateService.activeAccount$ + .pipe( + concatMap(async () => { + await this.setUrlsFromStorage(); + }) + ) + .subscribe(); } hasBaseUrl() { diff --git a/libs/common/src/services/folder/folder.service.ts b/libs/common/src/services/folder/folder.service.ts index 9b3647a8d6..09a305c02f 100644 --- a/libs/common/src/services/folder/folder.service.ts +++ b/libs/common/src/services/folder/folder.service.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, concatMap } from "rxjs"; import { CipherService } from "../../abstractions/cipher.service"; import { CryptoService } from "../../abstractions/crypto.service"; @@ -25,21 +25,25 @@ export class FolderService implements InternalFolderServiceAbstraction { private cipherService: CipherService, private stateService: StateService ) { - this.stateService.activeAccountUnlocked$.subscribe(async (unlocked) => { - if (Utils.global.bitwardenContainerService == null) { - return; - } + this.stateService.activeAccountUnlocked$ + .pipe( + concatMap(async (unlocked) => { + if (Utils.global.bitwardenContainerService == null) { + return; + } - if (!unlocked) { - this._folders.next([]); - this._folderViews.next([]); - return; - } + if (!unlocked) { + this._folders.next([]); + this._folderViews.next([]); + return; + } - const data = await this.stateService.getEncryptedFolders(); + const data = await this.stateService.getEncryptedFolders(); - await this.updateObservables(data); - }); + await this.updateObservables(data); + }) + ) + .subscribe(); } async clearCache(): Promise { diff --git a/libs/common/src/services/state.service.ts b/libs/common/src/services/state.service.ts index 24a2e630e3..3e007911cf 100644 --- a/libs/common/src/services/state.service.ts +++ b/libs/common/src/services/state.service.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, concatMap } from "rxjs"; import { LogService } from "../abstractions/log.service"; import { StateService as StateServiceAbstraction } from "../abstractions/state.service"; @@ -76,18 +76,22 @@ export class StateService< protected useAccountCache: boolean = true ) { // If the account gets changed, verify the new account is unlocked - this.activeAccountSubject.subscribe(async (userId) => { - if (userId == null && this.activeAccountUnlockedSubject.getValue() == false) { - return; - } else if (userId == null) { - this.activeAccountUnlockedSubject.next(false); - } + this.activeAccountSubject + .pipe( + concatMap(async (userId) => { + if (userId == null && this.activeAccountUnlockedSubject.getValue() == false) { + return; + } else if (userId == null) { + this.activeAccountUnlockedSubject.next(false); + } - // FIXME: This should be refactored into AuthService or a similar service, - // as checking for the existance of the crypto key is a low level - // implementation detail. - this.activeAccountUnlockedSubject.next((await this.getCryptoMasterKey()) != null); - }); + // FIXME: This should be refactored into AuthService or a similar service, + // as checking for the existance of the crypto key is a low level + // implementation detail. + this.activeAccountUnlockedSubject.next((await this.getCryptoMasterKey()) != null); + }) + ) + .subscribe(); } async init(): Promise { diff --git a/package-lock.json b/package-lock.json index 60dfc237cb..564d98e469 100644 --- a/package-lock.json +++ b/package-lock.json @@ -131,6 +131,8 @@ "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.26.0", + "eslint-plugin-rxjs": "^5.0.2", + "eslint-plugin-rxjs-angular": "^2.0.0", "gulp": "^4.0.2", "gulp-filter": "^7.0.0", "gulp-if": "^3.0.0", @@ -13351,6 +13353,123 @@ } } }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.35.1.tgz", + "integrity": "sha512-nF7JD9alMkhEx50QYDUdP8koeHtldnm7EfZkr68ikkc87ffFBIPkH3dqoWyOeQeIiJicB0uHzpMXKR6PP+1Jbg==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.35.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz", + "integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.35.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/parser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", @@ -15662,6 +15781,17 @@ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", "dev": true }, + "node_modules/bent": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/bent/-/bent-7.3.12.tgz", + "integrity": "sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==", + "dev": true, + "dependencies": { + "bytesish": "^0.4.1", + "caseless": "~0.12.0", + "is-stream": "^2.0.0" + } + }, "node_modules/better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -16470,6 +16600,12 @@ "node": ">= 0.8" } }, + "node_modules/bytesish": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/bytesish/-/bytesish-0.4.4.tgz", + "integrity": "sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==", + "dev": true + }, "node_modules/cacache": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.1.tgz", @@ -16715,6 +16851,12 @@ "node": ">=4" } }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, "node_modules/ccount": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", @@ -17505,6 +17647,15 @@ "node": ">= 10" } }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -21338,6 +21489,21 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-etc": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-etc/-/eslint-etc-5.2.0.tgz", + "integrity": "sha512-Gcm/NMa349FOXb1PEEfNMMyIANuorIc2/mI5Vfu1zENNsz+FBVhF62uY6gPUCigm/xDOc8JOnl+71WGnlzlDag==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "tsutils": "^3.17.1", + "tsutils-etc": "^1.4.1" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": "^4.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", @@ -21584,6 +21750,56 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/eslint-plugin-rxjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-rxjs/-/eslint-plugin-rxjs-5.0.2.tgz", + "integrity": "sha512-Q2wsEHWInhZ3uz5df+YbD4g/NPQqAeYHjJuEsxqgVS+XAsYCuVE2pj9kADdMFy4GsQy2jt7KP+TOrnq1i6bI5Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "common-tags": "^1.8.0", + "decamelize": "^5.0.0", + "eslint-etc": "^5.1.0", + "requireindex": "~1.2.0", + "rxjs-report-usage": "^1.0.4", + "tslib": "^2.0.0", + "tsutils": "^3.0.0", + "tsutils-etc": "^1.4.1" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": "^4.0.0" + } + }, + "node_modules/eslint-plugin-rxjs-angular": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-rxjs-angular/-/eslint-plugin-rxjs-angular-2.0.0.tgz", + "integrity": "sha512-MalcYcEHOK2NT+avWSI1PsUilwGx6cprMQdw9jJRlCTkIvsUvCGFD1eTqQKVImwkK8+te732v9VsP/XcXlKZqA==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "common-tags": "^1.8.0", + "eslint-etc": "^5.0.0", + "requireindex": "~1.2.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": "^4.0.0" + } + }, + "node_modules/eslint-plugin-rxjs/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -36707,6 +36923,15 @@ "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", "dev": true }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -37055,6 +37280,66 @@ "tslib": "^2.1.0" } }, + "node_modules/rxjs-report-usage": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/rxjs-report-usage/-/rxjs-report-usage-1.0.6.tgz", + "integrity": "sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.10.3", + "@babel/traverse": "^7.10.3", + "@babel/types": "^7.10.3", + "bent": "~7.3.6", + "chalk": "~4.1.0", + "glob": "~7.2.0", + "prompts": "~2.4.2" + }, + "bin": { + "rxjs-report-usage": "bin/rxjs-report-usage" + } + }, + "node_modules/rxjs-report-usage/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rxjs-report-usage/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rxjs-report-usage/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -40466,6 +40751,24 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/tsutils-etc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tsutils-etc/-/tsutils-etc-1.4.1.tgz", + "integrity": "sha512-6UPYgc7OXcIW5tFxlsZF3OVSBvDInl/BkS3Xsu64YITXk7WrnWTVByKWPCThFDBp5gl5IGHOzGMdQuDCE7OL4g==", + "dev": true, + "dependencies": { + "@types/yargs": "^17.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "ts-flags": "bin/ts-flags", + "ts-kind": "bin/ts-kind" + }, + "peerDependencies": { + "tsutils": "^3.0.0", + "typescript": "^4.0.0" + } + }, "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -52912,6 +53215,72 @@ "tsutils": "^3.21.0" } }, + "@typescript-eslint/experimental-utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.35.1.tgz", + "integrity": "sha512-nF7JD9alMkhEx50QYDUdP8koeHtldnm7EfZkr68ikkc87ffFBIPkH3dqoWyOeQeIiJicB0uHzpMXKR6PP+1Jbg==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.35.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" + } + }, + "@typescript-eslint/types": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz", + "integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.35.1", + "eslint-visitor-keys": "^3.3.0" + } + } + } + }, "@typescript-eslint/parser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", @@ -54711,6 +55080,17 @@ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", "dev": true }, + "bent": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/bent/-/bent-7.3.12.tgz", + "integrity": "sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==", + "dev": true, + "requires": { + "bytesish": "^0.4.1", + "caseless": "~0.12.0", + "is-stream": "^2.0.0" + } + }, "better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -55374,6 +55754,12 @@ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true }, + "bytesish": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/bytesish/-/bytesish-0.4.4.tgz", + "integrity": "sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==", + "dev": true + }, "cacache": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.1.tgz", @@ -55562,6 +55948,12 @@ "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, "ccount": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", @@ -56155,6 +56547,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -59163,6 +59561,17 @@ "dev": true, "requires": {} }, + "eslint-etc": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-etc/-/eslint-etc-5.2.0.tgz", + "integrity": "sha512-Gcm/NMa349FOXb1PEEfNMMyIANuorIc2/mI5Vfu1zENNsz+FBVhF62uY6gPUCigm/xDOc8JOnl+71WGnlzlDag==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "tsutils": "^3.17.1", + "tsutils-etc": "^1.4.1" + } + }, "eslint-import-resolver-node": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", @@ -59368,6 +59777,44 @@ } } }, + "eslint-plugin-rxjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-rxjs/-/eslint-plugin-rxjs-5.0.2.tgz", + "integrity": "sha512-Q2wsEHWInhZ3uz5df+YbD4g/NPQqAeYHjJuEsxqgVS+XAsYCuVE2pj9kADdMFy4GsQy2jt7KP+TOrnq1i6bI5Q==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "common-tags": "^1.8.0", + "decamelize": "^5.0.0", + "eslint-etc": "^5.1.0", + "requireindex": "~1.2.0", + "rxjs-report-usage": "^1.0.4", + "tslib": "^2.0.0", + "tsutils": "^3.0.0", + "tsutils-etc": "^1.4.1" + }, + "dependencies": { + "decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true + } + } + }, + "eslint-plugin-rxjs-angular": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-rxjs-angular/-/eslint-plugin-rxjs-angular-2.0.0.tgz", + "integrity": "sha512-MalcYcEHOK2NT+avWSI1PsUilwGx6cprMQdw9jJRlCTkIvsUvCGFD1eTqQKVImwkK8+te732v9VsP/XcXlKZqA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "common-tags": "^1.8.0", + "eslint-etc": "^5.0.0", + "requireindex": "~1.2.0", + "tslib": "^2.0.0" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -70942,6 +71389,12 @@ "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", "dev": true }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -71216,6 +71669,56 @@ "tslib": "^2.1.0" } }, + "rxjs-report-usage": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/rxjs-report-usage/-/rxjs-report-usage-1.0.6.tgz", + "integrity": "sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==", + "dev": true, + "requires": { + "@babel/parser": "^7.10.3", + "@babel/traverse": "^7.10.3", + "@babel/types": "^7.10.3", + "bent": "~7.3.6", + "chalk": "~4.1.0", + "glob": "~7.2.0", + "prompts": "~2.4.2" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -73926,6 +74429,16 @@ } } }, + "tsutils-etc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tsutils-etc/-/tsutils-etc-1.4.1.tgz", + "integrity": "sha512-6UPYgc7OXcIW5tFxlsZF3OVSBvDInl/BkS3Xsu64YITXk7WrnWTVByKWPCThFDBp5gl5IGHOzGMdQuDCE7OL4g==", + "dev": true, + "requires": { + "@types/yargs": "^17.0.0", + "yargs": "^17.0.0" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", diff --git a/package.json b/package.json index 4a3ed190cd..e8fd522d67 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,9 @@ "homepage": "https://bitwarden.com", "scripts": { "prepare": "husky install", - "lint": "eslint . && prettier --check .", - "lint:fix": "eslint . --fix", + "lint": "eslint . --cache --cache-strategy content && prettier --check .", + "lint:fix": "eslint . --cache --cache-strategy content --fix", + "lint:clear": "rimraf .eslintcache", "prettier": "prettier --write .", "test": "jest", "test:watch": "jest --clearCache && jest --watch", @@ -94,6 +95,8 @@ "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.26.0", + "eslint-plugin-rxjs": "^5.0.2", + "eslint-plugin-rxjs-angular": "^2.0.0", "gulp": "^4.0.2", "gulp-filter": "^7.0.0", "gulp-if": "^3.0.0", @@ -198,7 +201,7 @@ }, "lint-staged": { "*": "prettier --ignore-unknown --write", - "*.ts": "eslint --fix" + "*.ts": "eslint --cache --cache-strategy content --fix" }, "engines": { "node": "~16", diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 0000000000..cf7bbd7c96 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "pretty": true, + "moduleResolution": "node", + "noImplicitAny": true, + "target": "ES6", + "module": "commonjs", + "lib": ["es5", "es6", "es7", "dom"], + "sourceMap": true, + "declaration": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "declarationDir": "dist/types", + "outDir": "dist", + "baseUrl": ".", + "paths": { + "@bitwarden/common/*": ["./libs/common/src/*"], + "@bitwarden/angular/*": ["./libs/angular/src/*"], + "@bitwarden/electron/*": ["./libs/electron/src/*"], + "@bitwarden/node/*": ["./libs/node/src/*"], + "@bitwarden/components": ["./libs/components/src"] + }, + "plugins": [ + { + "transform": "typescript-transform-paths" + } + ] + }, + "include": ["apps/**/*", "libs/**/*", "bitwarden_license/**/*"] +}