diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts index 14a218c7141..d95e8333dca 100644 --- a/apps/cli/src/commands/edit.command.ts +++ b/apps/cli/src/commands/edit.command.ts @@ -186,15 +186,15 @@ export class EditCommand { return Response.notFound(); } - let folderView = await folder.decrypt(); + const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId)); + let folderView = await folder.decrypt(userKey); folderView = FolderExport.toView(req, folderView); - const userKey = await this.keyService.getUserKey(activeUserId); const encFolder = await this.folderService.encrypt(folderView, userKey); try { const folder = await this.folderApiService.save(encFolder, activeUserId); const updatedFolder = new Folder(folder); - const decFolder = await updatedFolder.decrypt(); + const decFolder = await updatedFolder.decrypt(userKey); const res = new FolderResponse(decFolder); return Response.success(res); } catch (e) { diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 93e711d748f..35816b56fb2 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -417,10 +417,11 @@ export class GetCommand extends DownloadCommand { private async getFolder(id: string) { let decFolder: FolderView = null; const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); + const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId)); if (Utils.isGuid(id)) { const folder = await this.folderService.getFromState(id, activeUserId); if (folder != null) { - decFolder = await folder.decrypt(); + decFolder = await folder.decrypt(userKey); } } else if (id.trim() !== "") { let folders = await this.folderService.getAllDecryptedFromState(activeUserId); diff --git a/apps/cli/src/platform/services/cli-sdk-load.service.ts b/apps/cli/src/platform/services/cli-sdk-load.service.ts index 638e64a8214..13a4c19d51d 100644 --- a/apps/cli/src/platform/services/cli-sdk-load.service.ts +++ b/apps/cli/src/platform/services/cli-sdk-load.service.ts @@ -3,6 +3,8 @@ import * as sdk from "@bitwarden/sdk-internal"; export class CliSdkLoadService extends SdkLoadService { async load(): Promise { + // CLI uses stdout for user interaction / automations so we cannot log info / debug here. + SdkLoadService.logLevel = sdk.LogLevel.Error; const module = await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm"); (sdk as any).init(module); } diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 5602c593942..d826766dc65 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -181,12 +181,12 @@ export class CreateCommand { private async createFolder(req: FolderExport) { const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); - const userKey = await this.keyService.getUserKey(activeUserId); + const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId)); const folder = await this.folderService.encrypt(FolderExport.toView(req), userKey); try { const folderData = await this.folderApiService.save(folder, activeUserId); const newFolder = new Folder(folderData); - const decFolder = await newFolder.decrypt(); + const decFolder = await newFolder.decrypt(userKey); const res = new FolderResponse(decFolder); return Response.success(res); } catch (e) { diff --git a/apps/desktop/src/app/layout/desktop-layout.component.html b/apps/desktop/src/app/layout/desktop-layout.component.html index 94b9201ae21..7f8bd265102 100644 --- a/apps/desktop/src/app/layout/desktop-layout.component.html +++ b/apps/desktop/src/app/layout/desktop-layout.component.html @@ -1,4 +1,4 @@ - + diff --git a/apps/desktop/src/scss/migration.scss b/apps/desktop/src/scss/migration.scss new file mode 100644 index 00000000000..e3078158283 --- /dev/null +++ b/apps/desktop/src/scss/migration.scss @@ -0,0 +1,15 @@ +/** + * Desktop UI Migration + * + * These are temporary styles during the desktop ui migration. + **/ + +/** + * This removes any padding applied by the bit-layout to content. + * This should be revisited once the table is migrated, and again once drawers are migrated. + **/ +bit-layout { + #main-content { + padding: 0 0 0 0; + } +} diff --git a/apps/desktop/src/scss/styles.scss b/apps/desktop/src/scss/styles.scss index c579e6acdc0..b4082afd38c 100644 --- a/apps/desktop/src/scss/styles.scss +++ b/apps/desktop/src/scss/styles.scss @@ -15,5 +15,6 @@ @import "left-nav.scss"; @import "loading.scss"; @import "plugins.scss"; +@import "migration.scss"; @import "../../../../libs/angular/src/scss/icons.scss"; @import "../../../../libs/components/src/multi-select/scss/bw.theme"; diff --git a/libs/common/spec/utils.ts b/libs/common/spec/utils.ts index db9a7e0842c..f3e81d71ce2 100644 --- a/libs/common/spec/utils.ts +++ b/libs/common/spec/utils.ts @@ -2,7 +2,10 @@ // @ts-strict-ignore import { mock, MockProxy } from "jest-mock-extended"; +import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; +import { ContainerService } from "@bitwarden/common/platform/services/container.service"; +import { KeyService } from "@bitwarden/key-management"; import { EncryptionType } from "../src/platform/enums"; import { Utils } from "../src/platform/misc/utils"; @@ -29,6 +32,7 @@ export function BuildTestObject( export function mockEnc(s: string): MockProxy { const mocked = mock(); + mocked.decryptedValue = s; mocked.decrypt.mockResolvedValue(s); return mocked; @@ -77,4 +81,14 @@ export const mockFromSdk = (stub: any) => { return `${stub}_fromSdk`; }; +export const mockContainerService = () => { + const keyService = mock(); + const encryptService = mock(); + encryptService.decryptString.mockImplementation(async (encStr, _key) => { + return encStr.decryptedValue; + }); + (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); + return (window as any).bitwardenContainerService; +}; + export { trackEmissions, awaitAsync } from "@bitwarden/core-test-utils"; diff --git a/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts b/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts index fb443d61777..946b9894d2b 100644 --- a/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts +++ b/libs/common/src/platform/abstractions/sdk/sdk-load.service.ts @@ -1,4 +1,4 @@ -import { init_sdk } from "@bitwarden/sdk-internal"; +import { init_sdk, LogLevel } from "@bitwarden/sdk-internal"; // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used in docs import type { SdkService } from "./sdk.service"; @@ -10,6 +10,7 @@ export class SdkLoadFailedError extends Error { } export abstract class SdkLoadService { + protected static logLevel: LogLevel = LogLevel.Info; private static markAsReady: () => void; private static markAsFailed: (error: unknown) => void; @@ -41,7 +42,7 @@ export abstract class SdkLoadService { async loadAndInit(): Promise { try { await this.load(); - init_sdk(); + init_sdk(SdkLoadService.logLevel); SdkLoadService.markAsReady(); } catch (error) { SdkLoadService.markAsFailed(error); diff --git a/libs/common/src/platform/models/domain/domain-base.ts b/libs/common/src/platform/models/domain/domain-base.ts index a144353f5bc..382ed5fea76 100644 --- a/libs/common/src/platform/models/domain/domain-base.ts +++ b/libs/common/src/platform/models/domain/domain-base.ts @@ -73,14 +73,13 @@ export default class Domain { domain: DomainEncryptableKeys, viewModel: ViewEncryptableKeys, props: EncryptableKeys[], - orgId: string | null, key: SymmetricCryptoKey | null = null, objectContext: string = "No Domain Context", ): Promise { for (const prop of props) { viewModel[prop] = (await domain[prop]?.decrypt( - orgId, + null, key, `Property: ${prop as string}; ObjectContext: ${objectContext}`, )) ?? null; diff --git a/libs/common/src/tools/send/models/domain/send-access.spec.ts b/libs/common/src/tools/send/models/domain/send-access.spec.ts index 597208d517c..686236bff8e 100644 --- a/libs/common/src/tools/send/models/domain/send-access.spec.ts +++ b/libs/common/src/tools/send/models/domain/send-access.spec.ts @@ -1,6 +1,6 @@ import { mock } from "jest-mock-extended"; -import { mockEnc } from "../../../../../spec"; +import { mockContainerService, mockEnc } from "../../../../../spec"; import { SendType } from "../../enums/send-type"; import { SendAccessResponse } from "../response/send-access.response"; @@ -23,6 +23,8 @@ describe("SendAccess", () => { expirationDate: new Date("2022-01-31T12:00:00.000Z"), creatorIdentifier: "creatorIdentifier", } as SendAccessResponse; + + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/tools/send/models/domain/send-access.ts b/libs/common/src/tools/send/models/domain/send-access.ts index 2251e8e5a5a..68d1af7b57e 100644 --- a/libs/common/src/tools/send/models/domain/send-access.ts +++ b/libs/common/src/tools/send/models/domain/send-access.ts @@ -54,7 +54,7 @@ export class SendAccess extends Domain { async decrypt(key: SymmetricCryptoKey): Promise { const model = new SendAccessView(this); - await this.decryptObj(this, model, ["name"], null, key); + await this.decryptObj(this, model, ["name"], key); switch (this.type) { case SendType.File: diff --git a/libs/common/src/tools/send/models/domain/send-file.spec.ts b/libs/common/src/tools/send/models/domain/send-file.spec.ts index 44a84cdc639..f60767e9bdf 100644 --- a/libs/common/src/tools/send/models/domain/send-file.spec.ts +++ b/libs/common/src/tools/send/models/domain/send-file.spec.ts @@ -1,4 +1,4 @@ -import { mockEnc } from "../../../../../spec"; +import { mockContainerService, mockEnc } from "../../../../../spec"; import { SendFileData } from "../data/send-file.data"; import { SendFile } from "./send-file"; @@ -39,6 +39,7 @@ describe("SendFile", () => { }); it("Decrypt", async () => { + mockContainerService(); const sendFile = new SendFile(); sendFile.id = "id"; sendFile.size = "1100"; diff --git a/libs/common/src/tools/send/models/domain/send-file.ts b/libs/common/src/tools/send/models/domain/send-file.ts index 228f4ee81ca..d01f30a1905 100644 --- a/libs/common/src/tools/send/models/domain/send-file.ts +++ b/libs/common/src/tools/send/models/domain/send-file.ts @@ -38,7 +38,6 @@ export class SendFile extends Domain { this, new SendFileView(this), ["fileName"], - null, key, ); } diff --git a/libs/common/src/tools/send/models/domain/send-text.spec.ts b/libs/common/src/tools/send/models/domain/send-text.spec.ts index 6af143ec594..bac2687c897 100644 --- a/libs/common/src/tools/send/models/domain/send-text.spec.ts +++ b/libs/common/src/tools/send/models/domain/send-text.spec.ts @@ -1,4 +1,4 @@ -import { mockEnc } from "../../../../../spec"; +import { mockContainerService, mockEnc } from "../../../../../spec"; import { SendTextData } from "../data/send-text.data"; import { SendText } from "./send-text"; @@ -11,6 +11,8 @@ describe("SendText", () => { text: "encText", hidden: false, }; + + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/tools/send/models/domain/send-text.ts b/libs/common/src/tools/send/models/domain/send-text.ts index 321810292ad..34a0be52dcb 100644 --- a/libs/common/src/tools/send/models/domain/send-text.ts +++ b/libs/common/src/tools/send/models/domain/send-text.ts @@ -30,13 +30,7 @@ export class SendText extends Domain { } decrypt(key: SymmetricCryptoKey): Promise { - return this.decryptObj( - this, - new SendTextView(this), - ["text"], - null, - key, - ); + return this.decryptObj(this, new SendTextView(this), ["text"], key); } static fromJSON(obj: Jsonify) { diff --git a/libs/common/src/tools/send/models/domain/send.spec.ts b/libs/common/src/tools/send/models/domain/send.spec.ts index d465aa97924..dc9ca7d3444 100644 --- a/libs/common/src/tools/send/models/domain/send.spec.ts +++ b/libs/common/src/tools/send/models/domain/send.spec.ts @@ -6,7 +6,7 @@ import { emptyGuid, UserId } from "@bitwarden/common/types/guid"; // eslint-disable-next-line no-restricted-imports import { KeyService } from "@bitwarden/key-management"; -import { makeStaticByteArray, mockEnc } from "../../../../../spec"; +import { makeStaticByteArray, mockContainerService, mockEnc } from "../../../../../spec"; import { EncryptService } from "../../../../key-management/crypto/abstractions/encrypt.service"; import { SymmetricCryptoKey } from "../../../../platform/models/domain/symmetric-crypto-key"; import { ContainerService } from "../../../../platform/services/container.service"; @@ -43,6 +43,8 @@ describe("Send", () => { disabled: false, hideEmail: true, }; + + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/tools/send/models/domain/send.ts b/libs/common/src/tools/send/models/domain/send.ts index 48129d4314a..2bf16de8a44 100644 --- a/libs/common/src/tools/send/models/domain/send.ts +++ b/libs/common/src/tools/send/models/domain/send.ts @@ -89,7 +89,7 @@ export class Send extends Domain { model.key = await encryptService.decryptBytes(this.key, sendKeyEncryptionKey); model.cryptoKey = await keyService.makeSendKey(model.key); - await this.decryptObj(this, model, ["name", "notes"], null, model.cryptoKey); + await this.decryptObj(this, model, ["name", "notes"], model.cryptoKey); switch (this.type) { case SendType.File: diff --git a/libs/common/src/vault/models/domain/attachment.spec.ts b/libs/common/src/vault/models/domain/attachment.spec.ts index 77bb3eda38d..3c97e3b4213 100644 --- a/libs/common/src/vault/models/domain/attachment.spec.ts +++ b/libs/common/src/vault/models/domain/attachment.spec.ts @@ -4,12 +4,10 @@ import { mock, MockProxy } from "jest-mock-extended"; // eslint-disable-next-line no-restricted-imports import { KeyService } from "@bitwarden/key-management"; -import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec"; +import { makeStaticByteArray, mockContainerService, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; -import { ContainerService } from "../../../platform/services/container.service"; -import { OrgKey, UserKey } from "../../../types/key"; import { AttachmentData } from "../../models/data/attachment.data"; import { Attachment } from "../../models/domain/attachment"; @@ -70,10 +68,9 @@ describe("Attachment", () => { let encryptService: MockProxy; beforeEach(() => { - keyService = mock(); - encryptService = mock(); - - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); + const containerService = mockContainerService(); + keyService = containerService.keyService as MockProxy; + encryptService = containerService.encryptService as MockProxy; }); it("expected output", async () => { @@ -85,14 +82,13 @@ describe("Attachment", () => { attachment.key = mockEnc("key"); attachment.fileName = mockEnc("fileName"); - const userKey = new SymmetricCryptoKey(makeStaticByteArray(64)); - keyService.getUserKey.mockResolvedValue(userKey as UserKey); encryptService.decryptFileData.mockResolvedValue(makeStaticByteArray(32)); encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - const view = await attachment.decrypt(null); + const userKey = new SymmetricCryptoKey(makeStaticByteArray(64)); + const view = await attachment.decrypt(userKey); expect(view).toEqual({ id: "id", @@ -116,31 +112,11 @@ describe("Attachment", () => { it("uses the provided key without depending on KeyService", async () => { const providedKey = mock(); - await attachment.decrypt(null, "", providedKey); + await attachment.decrypt(providedKey, ""); expect(keyService.getUserKey).not.toHaveBeenCalled(); expect(encryptService.unwrapSymmetricKey).toHaveBeenCalledWith(attachment.key, providedKey); }); - - it("gets an organization key if required", async () => { - const orgKey = mock(); - keyService.getOrgKey.calledWith("orgId").mockResolvedValue(orgKey); - - await attachment.decrypt("orgId", "", null); - - expect(keyService.getOrgKey).toHaveBeenCalledWith("orgId"); - expect(encryptService.unwrapSymmetricKey).toHaveBeenCalledWith(attachment.key, orgKey); - }); - - it("gets the user's decryption key if required", async () => { - const userKey = mock(); - keyService.getUserKey.mockResolvedValue(userKey); - - await attachment.decrypt(null, "", null); - - expect(keyService.getUserKey).toHaveBeenCalled(); - expect(encryptService.unwrapSymmetricKey).toHaveBeenCalledWith(attachment.key, userKey); - }); }); }); diff --git a/libs/common/src/vault/models/domain/attachment.ts b/libs/common/src/vault/models/domain/attachment.ts index 7b43af9be55..d9dfa128028 100644 --- a/libs/common/src/vault/models/domain/attachment.ts +++ b/libs/common/src/vault/models/domain/attachment.ts @@ -1,6 +1,5 @@ import { Jsonify } from "type-fest"; -import { OrgKey, UserKey } from "@bitwarden/common/types/key"; import { Attachment as SdkAttachment } from "@bitwarden/sdk-internal"; import { EncString } from "../../../key-management/crypto/models/enc-string"; @@ -34,21 +33,19 @@ export class Attachment extends Domain { } async decrypt( - orgId: string | undefined, + decryptionKey: SymmetricCryptoKey, context = "No Cipher Context", - encKey?: SymmetricCryptoKey, ): Promise { const view = await this.decryptObj( this, new AttachmentView(this), ["fileName"], - orgId ?? null, - encKey, + decryptionKey, "DomainType: Attachment; " + context, ); if (this.key != null) { - view.key = await this.decryptAttachmentKey(orgId, encKey); + view.key = await this.decryptAttachmentKey(decryptionKey); view.encryptedKey = this.key; // Keep the encrypted key for the view } @@ -56,27 +53,15 @@ export class Attachment extends Domain { } private async decryptAttachmentKey( - orgId: string | undefined, - encKey?: SymmetricCryptoKey, + decryptionKey: SymmetricCryptoKey, ): Promise { try { if (this.key == null) { return undefined; } - if (encKey == null) { - const key = await this.getKeyForDecryption(orgId); - - // If we don't have a key, we can't decrypt - if (key == null) { - return undefined; - } - - encKey = key; - } - const encryptService = Utils.getContainerService().getEncryptService(); - const decValue = await encryptService.unwrapSymmetricKey(this.key, encKey); + const decValue = await encryptService.unwrapSymmetricKey(this.key, decryptionKey); return decValue; } catch (e) { // eslint-disable-next-line no-console @@ -85,11 +70,6 @@ export class Attachment extends Domain { } } - private async getKeyForDecryption(orgId: string | undefined): Promise { - const keyService = Utils.getContainerService().getKeyService(); - return orgId != null ? await keyService.getOrgKey(orgId) : await keyService.getUserKey(); - } - toAttachmentData(): AttachmentData { const a = new AttachmentData(); if (this.size != null) { diff --git a/libs/common/src/vault/models/domain/card.spec.ts b/libs/common/src/vault/models/domain/card.spec.ts index 185c2fa4b8f..1dfda7be359 100644 --- a/libs/common/src/vault/models/domain/card.spec.ts +++ b/libs/common/src/vault/models/domain/card.spec.ts @@ -1,4 +1,9 @@ -import { mockEnc, mockFromJson } from "../../../../spec"; +import { + makeSymmetricCryptoKey, + mockContainerService, + mockEnc, + mockFromJson, +} from "../../../../spec"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { CardData } from "../../../vault/models/data/card.data"; import { Card } from "../../models/domain/card"; @@ -65,7 +70,10 @@ describe("Card", () => { card.expYear = mockEnc("expYear"); card.code = mockEnc("code"); - const view = await card.decrypt(null); + const userKey = makeSymmetricCryptoKey(64); + + mockContainerService(); + const view = await card.decrypt(userKey); expect(view).toEqual({ _brand: "brand", diff --git a/libs/common/src/vault/models/domain/card.ts b/libs/common/src/vault/models/domain/card.ts index b3a087d44fb..2d636e8e265 100644 --- a/libs/common/src/vault/models/domain/card.ts +++ b/libs/common/src/vault/models/domain/card.ts @@ -31,16 +31,11 @@ export class Card extends Domain { this.code = conditionalEncString(obj.code); } - async decrypt( - orgId: string | undefined, - context = "No Cipher Context", - encKey?: SymmetricCryptoKey, - ): Promise { + async decrypt(encKey: SymmetricCryptoKey, context = "No Cipher Context"): Promise { return this.decryptObj( this, new CardView(), ["cardholderName", "brand", "number", "expMonth", "expYear", "code"], - orgId ?? null, encKey, "DomainType: Card; " + context, ); diff --git a/libs/common/src/vault/models/domain/cipher.spec.ts b/libs/common/src/vault/models/domain/cipher.spec.ts index 87301928c57..4fe5e89451c 100644 --- a/libs/common/src/vault/models/domain/cipher.spec.ts +++ b/libs/common/src/vault/models/domain/cipher.spec.ts @@ -2,9 +2,7 @@ import { mock } from "jest-mock-extended"; import { Jsonify } from "type-fest"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { KeyService } from "@bitwarden/key-management"; +import { MockProxy } from "@bitwarden/common/platform/spec/mock-deep"; import { CipherType as SdkCipherType, UriMatchType, @@ -14,11 +12,15 @@ import { EncString as SdkEncString, } from "@bitwarden/sdk-internal"; -import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec/utils"; +import { + makeStaticByteArray, + mockContainerService, + mockEnc, + mockFromJson, +} from "../../../../spec/utils"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; import { EncString } from "../../../key-management/crypto/models/enc-string"; import { UriMatchStrategy } from "../../../models/domain/domain-service"; -import { ContainerService } from "../../../platform/services/container.service"; import { InitializerKey } from "../../../platform/services/cryptography/initializer-key"; import { UserId } from "../../../types/guid"; import { CipherService } from "../../abstractions/cipher.service"; @@ -39,7 +41,16 @@ import { IdentityView } from "../../models/view/identity.view"; import { LoginView } from "../../models/view/login.view"; import { CipherPermissionsApi } from "../api/cipher-permissions.api"; +const mockSymmetricKey = new SymmetricCryptoKey(makeStaticByteArray(64)); + describe("Cipher DTO", () => { + let encryptService: MockProxy; + + beforeEach(() => { + const containerService = mockContainerService(); + encryptService = containerService.encryptService; + }); + it("Convert from empty CipherData", () => { const data = new CipherData(); const cipher = new Cipher(data); @@ -95,13 +106,12 @@ describe("Cipher DTO", () => { login.decrypt.mockResolvedValue(loginView); cipher.login = login; - const keyService = mock(); - const encryptService = mock(); const cipherService = mock(); encryptService.unwrapSymmetricKey.mockRejectedValue(new Error("Failed to unwrap key")); - - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); + cipherService.getKeyForCipherKeyDecryption.mockResolvedValue( + new SymmetricCryptoKey(makeStaticByteArray(64)), + ); const cipherView = await cipher.decrypt( await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), @@ -317,19 +327,11 @@ describe("Cipher DTO", () => { login.decrypt.mockResolvedValue(loginView); cipher.login = login; - const keyService = mock(); - const encryptService = mock(); - const cipherService = mock(); - encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); - - const cipherView = await cipher.decrypt( - await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), - ); + const cipherView = await cipher.decrypt(mockSymmetricKey); expect(cipherView).toMatchObject({ id: "id", @@ -445,19 +447,11 @@ describe("Cipher DTO", () => { cipher.permissions = new CipherPermissionsApi(); cipher.archivedDate = undefined; - const keyService = mock(); - const encryptService = mock(); - const cipherService = mock(); - encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); - - const cipherView = await cipher.decrypt( - await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), - ); + const cipherView = await cipher.decrypt(mockSymmetricKey); expect(cipherView).toMatchObject({ id: "id", @@ -591,19 +585,11 @@ describe("Cipher DTO", () => { card.decrypt.mockResolvedValue(cardView); cipher.card = card; - const keyService = mock(); - const encryptService = mock(); - const cipherService = mock(); - encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); - - const cipherView = await cipher.decrypt( - await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), - ); + const cipherView = await cipher.decrypt(mockSymmetricKey); expect(cipherView).toMatchObject({ id: "id", @@ -761,19 +747,11 @@ describe("Cipher DTO", () => { identity.decrypt.mockResolvedValue(identityView); cipher.identity = identity; - const keyService = mock(); - const encryptService = mock(); - const cipherService = mock(); - encryptService.unwrapSymmetricKey.mockResolvedValue( new SymmetricCryptoKey(makeStaticByteArray(64)), ); - (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); - - const cipherView = await cipher.decrypt( - await cipherService.getKeyForCipherKeyDecryption(cipher, mockUserId), - ); + const cipherView = await cipher.decrypt(mockSymmetricKey); expect(cipherView).toMatchObject({ id: "id", diff --git a/libs/common/src/vault/models/domain/cipher.ts b/libs/common/src/vault/models/domain/cipher.ts index abddb73422b..599b1c765e4 100644 --- a/libs/common/src/vault/models/domain/cipher.ts +++ b/libs/common/src/vault/models/domain/cipher.ts @@ -1,5 +1,6 @@ import { Jsonify } from "type-fest"; +import { assertNonNullish } from "@bitwarden/common/auth/utils"; import { Cipher as SdkCipher } from "@bitwarden/sdk-internal"; import { EncString } from "../../../key-management/crypto/models/enc-string"; @@ -123,19 +124,22 @@ export class Cipher extends Domain implements Decryptable { } } - // We are passing the organizationId into the EncString.decrypt() method here, but because the encKey will always be - // present and so the organizationId will not be used. - // We will refactor the EncString.decrypt() in https://bitwarden.atlassian.net/browse/PM-3762 to remove the dependency on the organizationId. - async decrypt(encKey: SymmetricCryptoKey): Promise { + async decrypt(userKeyOrOrgKey: SymmetricCryptoKey): Promise { + assertNonNullish(userKeyOrOrgKey, "userKeyOrOrgKey", "Cipher decryption"); + const model = new CipherView(this); let bypassValidation = true; + // By default, the user/organization key is used for decryption + let cipherDecryptionKey = userKeyOrOrgKey; + + // If there is a cipher key present, unwrap it and use it for decryption if (this.key != null) { const encryptService = Utils.getContainerService().getEncryptService(); try { - const cipherKey = await encryptService.unwrapSymmetricKey(this.key, encKey); - encKey = cipherKey; + const cipherKey = await encryptService.unwrapSymmetricKey(this.key, userKeyOrOrgKey); + cipherDecryptionKey = cipherKey; bypassValidation = false; } catch { model.name = "[error: cannot decrypt]"; @@ -144,22 +148,15 @@ export class Cipher extends Domain implements Decryptable { } } - await this.decryptObj( - this, - model, - ["name", "notes"], - this.organizationId ?? null, - encKey, - ); + await this.decryptObj(this, model, ["name", "notes"], cipherDecryptionKey); switch (this.type) { case CipherType.Login: if (this.login != null) { model.login = await this.login.decrypt( - this.organizationId, bypassValidation, + userKeyOrOrgKey, `Cipher Id: ${this.id}`, - encKey, ); } break; @@ -170,29 +167,17 @@ export class Cipher extends Domain implements Decryptable { break; case CipherType.Card: if (this.card != null) { - model.card = await this.card.decrypt( - this.organizationId, - `Cipher Id: ${this.id}`, - encKey, - ); + model.card = await this.card.decrypt(userKeyOrOrgKey, `Cipher Id: ${this.id}`); } break; case CipherType.Identity: if (this.identity != null) { - model.identity = await this.identity.decrypt( - this.organizationId, - `Cipher Id: ${this.id}`, - encKey, - ); + model.identity = await this.identity.decrypt(userKeyOrOrgKey, `Cipher Id: ${this.id}`); } break; case CipherType.SshKey: if (this.sshKey != null) { - model.sshKey = await this.sshKey.decrypt( - this.organizationId, - `Cipher Id: ${this.id}`, - encKey, - ); + model.sshKey = await this.sshKey.decrypt(userKeyOrOrgKey, `Cipher Id: ${this.id}`); } break; default: @@ -203,9 +188,8 @@ export class Cipher extends Domain implements Decryptable { const attachments: AttachmentView[] = []; for (const attachment of this.attachments) { const decryptedAttachment = await attachment.decrypt( - this.organizationId, + userKeyOrOrgKey, `Cipher Id: ${this.id}`, - encKey, ); attachments.push(decryptedAttachment); } @@ -215,7 +199,7 @@ export class Cipher extends Domain implements Decryptable { if (this.fields != null && this.fields.length > 0) { const fields: FieldView[] = []; for (const field of this.fields) { - const decryptedField = await field.decrypt(this.organizationId, encKey); + const decryptedField = await field.decrypt(userKeyOrOrgKey); fields.push(decryptedField); } model.fields = fields; @@ -224,7 +208,7 @@ export class Cipher extends Domain implements Decryptable { if (this.passwordHistory != null && this.passwordHistory.length > 0) { const passwordHistory: PasswordHistoryView[] = []; for (const ph of this.passwordHistory) { - const decryptedPh = await ph.decrypt(this.organizationId, encKey); + const decryptedPh = await ph.decrypt(userKeyOrOrgKey); passwordHistory.push(decryptedPh); } model.passwordHistory = passwordHistory; diff --git a/libs/common/src/vault/models/domain/fido2-credential.spec.ts b/libs/common/src/vault/models/domain/fido2-credential.spec.ts index 3f43775433e..05504ea5666 100644 --- a/libs/common/src/vault/models/domain/fido2-credential.spec.ts +++ b/libs/common/src/vault/models/domain/fido2-credential.spec.ts @@ -1,4 +1,4 @@ -import { mockEnc } from "../../../../spec"; +import { makeSymmetricCryptoKey, mockContainerService, mockEnc } from "../../../../spec"; import { EncString } from "../../../key-management/crypto/models/enc-string"; import { EncryptionType } from "../../../platform/enums"; import { Fido2CredentialData } from "../data/fido2-credential.data"; @@ -103,7 +103,10 @@ describe("Fido2Credential", () => { credential.discoverable = mockEnc("true"); credential.creationDate = mockDate; - const credentialView = await credential.decrypt(null); + mockContainerService(); + + const cipherKey = makeSymmetricCryptoKey(64); + const credentialView = await credential.decrypt(cipherKey); expect(credentialView).toEqual({ credentialId: "credentialId", diff --git a/libs/common/src/vault/models/domain/fido2-credential.ts b/libs/common/src/vault/models/domain/fido2-credential.ts index eff95c4d0bd..5123b965c85 100644 --- a/libs/common/src/vault/models/domain/fido2-credential.ts +++ b/libs/common/src/vault/models/domain/fido2-credential.ts @@ -46,10 +46,7 @@ export class Fido2Credential extends Domain { this.creationDate = new Date(obj.creationDate); } - async decrypt( - orgId: string | undefined, - encKey?: SymmetricCryptoKey, - ): Promise { + async decrypt(decryptionKey: SymmetricCryptoKey): Promise { const view = await this.decryptObj( this, new Fido2CredentialView(), @@ -65,8 +62,7 @@ export class Fido2Credential extends Domain { "rpName", "userDisplayName", ], - orgId ?? null, - encKey, + decryptionKey, ); const { counter } = await this.decryptObj< @@ -74,7 +70,7 @@ export class Fido2Credential extends Domain { { counter: string; } - >(this, { counter: "" }, ["counter"], orgId ?? null, encKey); + >(this, { counter: "" }, ["counter"], decryptionKey); // Counter will end up as NaN if this fails view.counter = parseInt(counter); @@ -82,8 +78,7 @@ export class Fido2Credential extends Domain { this, { discoverable: "" }, ["discoverable"], - orgId ?? null, - encKey, + decryptionKey, ); view.discoverable = discoverable === "true"; view.creationDate = this.creationDate; diff --git a/libs/common/src/vault/models/domain/field.spec.ts b/libs/common/src/vault/models/domain/field.spec.ts index 0a4bc8e3c29..bcaccbcf369 100644 --- a/libs/common/src/vault/models/domain/field.spec.ts +++ b/libs/common/src/vault/models/domain/field.spec.ts @@ -6,7 +6,7 @@ import { IdentityLinkedIdType, } from "@bitwarden/sdk-internal"; -import { mockEnc, mockFromJson } from "../../../../spec"; +import { mockContainerService, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { CardLinkedId, IdentityLinkedId, LoginLinkedId } from "../../enums"; import { FieldData } from "../../models/data/field.data"; @@ -22,6 +22,7 @@ describe("Field", () => { value: "encValue", linkedId: null, }; + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/vault/models/domain/field.ts b/libs/common/src/vault/models/domain/field.ts index adec9263515..d61a2dbd82c 100644 --- a/libs/common/src/vault/models/domain/field.ts +++ b/libs/common/src/vault/models/domain/field.ts @@ -33,14 +33,8 @@ export class Field extends Domain { this.value = conditionalEncString(obj.value); } - decrypt(orgId: string | undefined, encKey?: SymmetricCryptoKey): Promise { - return this.decryptObj( - this, - new FieldView(this), - ["name", "value"], - orgId ?? null, - encKey, - ); + decrypt(encKey: SymmetricCryptoKey): Promise { + return this.decryptObj(this, new FieldView(this), ["name", "value"], encKey); } toFieldData(): FieldData { diff --git a/libs/common/src/vault/models/domain/folder.spec.ts b/libs/common/src/vault/models/domain/folder.spec.ts index a837fbb2726..d9e9e265d91 100644 --- a/libs/common/src/vault/models/domain/folder.spec.ts +++ b/libs/common/src/vault/models/domain/folder.spec.ts @@ -1,6 +1,12 @@ import { mock, MockProxy } from "jest-mock-extended"; -import { makeEncString, makeSymmetricCryptoKey, mockEnc, mockFromJson } from "../../../../spec"; +import { + makeEncString, + makeSymmetricCryptoKey, + mockContainerService, + mockEnc, + mockFromJson, +} from "../../../../spec"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { FolderData } from "../../models/data/folder.data"; @@ -15,6 +21,7 @@ describe("Folder", () => { name: "encName", revisionDate: "2022-01-31T12:00:00.000Z", }; + mockContainerService(); }); it("Convert", () => { @@ -33,7 +40,7 @@ describe("Folder", () => { folder.name = mockEnc("encName"); folder.revisionDate = new Date("2022-01-31T12:00:00.000Z"); - const view = await folder.decrypt(); + const view = await folder.decrypt(null); expect(view).toEqual({ id: "id", diff --git a/libs/common/src/vault/models/domain/folder.ts b/libs/common/src/vault/models/domain/folder.ts index 50c67eee01f..c336095f15d 100644 --- a/libs/common/src/vault/models/domain/folder.ts +++ b/libs/common/src/vault/models/domain/folder.ts @@ -39,8 +39,8 @@ export class Folder extends Domain { this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null; } - decrypt(): Promise { - return this.decryptObj(this, new FolderView(this), ["name"], null); + decrypt(key: SymmetricCryptoKey): Promise { + return this.decryptObj(this, new FolderView(this), ["name"], key); } async decryptWithKey( diff --git a/libs/common/src/vault/models/domain/identity.spec.ts b/libs/common/src/vault/models/domain/identity.spec.ts index 411f6d1c9ea..1e3bdc15373 100644 --- a/libs/common/src/vault/models/domain/identity.spec.ts +++ b/libs/common/src/vault/models/domain/identity.spec.ts @@ -1,4 +1,4 @@ -import { mockEnc, mockFromJson } from "../../../../spec"; +import { mockContainerService, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { IdentityData } from "../../models/data/identity.data"; import { Identity } from "../../models/domain/identity"; @@ -27,6 +27,8 @@ describe("Identity", () => { passportNumber: "encpassportNumber", licenseNumber: "enclicenseNumber", }; + + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/vault/models/domain/identity.ts b/libs/common/src/vault/models/domain/identity.ts index e2def3eb386..5424dda1502 100644 --- a/libs/common/src/vault/models/domain/identity.ts +++ b/libs/common/src/vault/models/domain/identity.ts @@ -56,9 +56,8 @@ export class Identity extends Domain { } decrypt( - orgId: string | undefined, + encKey: SymmetricCryptoKey, context: string = "No Cipher Context", - encKey?: SymmetricCryptoKey, ): Promise { return this.decryptObj( this, @@ -83,7 +82,6 @@ export class Identity extends Domain { "passportNumber", "licenseNumber", ], - orgId ?? null, encKey, "DomainType: Identity; " + context, ); diff --git a/libs/common/src/vault/models/domain/login-uri.spec.ts b/libs/common/src/vault/models/domain/login-uri.spec.ts index 2effd1bb9fe..ecdb1bbe00b 100644 --- a/libs/common/src/vault/models/domain/login-uri.spec.ts +++ b/libs/common/src/vault/models/domain/login-uri.spec.ts @@ -1,9 +1,14 @@ -import { MockProxy, mock } from "jest-mock-extended"; +import { MockProxy } from "jest-mock-extended"; import { Jsonify } from "type-fest"; import { UriMatchType } from "@bitwarden/sdk-internal"; -import { mockEnc, mockFromJson } from "../../../../spec"; +import { + makeSymmetricCryptoKey, + mockContainerService, + mockEnc, + mockFromJson, +} from "../../../../spec"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; import { EncString } from "../../../key-management/crypto/models/enc-string"; import { UriMatchStrategy } from "../../../models/domain/domain-service"; @@ -14,6 +19,7 @@ import { LoginUri } from "./login-uri"; describe("LoginUri", () => { let data: LoginUriData; + let encryptService: MockProxy; beforeEach(() => { data = { @@ -21,6 +27,9 @@ describe("LoginUri", () => { uriChecksum: "encUriChecksum", match: UriMatchStrategy.Domain, }; + + const containerService = mockContainerService(); + encryptService = containerService.getEncryptService(); }); it("Convert from empty", () => { @@ -83,22 +92,13 @@ describe("LoginUri", () => { }); describe("validateChecksum", () => { - let encryptService: MockProxy; - - beforeEach(() => { - encryptService = mock(); - global.bitwardenContainerService = { - getEncryptService: () => encryptService, - getKeyService: () => null, - }; - }); - it("returns true if checksums match", async () => { const loginUri = new LoginUri(); loginUri.uriChecksum = mockEnc("checksum"); encryptService.hash.mockResolvedValue("checksum"); - const actual = await loginUri.validateChecksum("uri", undefined, undefined); + const key = makeSymmetricCryptoKey(64); + const actual = await loginUri.validateChecksum("uri", key); expect(actual).toBe(true); expect(encryptService.hash).toHaveBeenCalledWith("uri", "sha256"); @@ -109,7 +109,7 @@ describe("LoginUri", () => { loginUri.uriChecksum = mockEnc("checksum"); encryptService.hash.mockResolvedValue("incorrect checksum"); - const actual = await loginUri.validateChecksum("uri", undefined, undefined); + const actual = await loginUri.validateChecksum("uri", undefined); expect(actual).toBe(false); }); diff --git a/libs/common/src/vault/models/domain/login-uri.ts b/libs/common/src/vault/models/domain/login-uri.ts index 42acca25d6f..e784d10dbd7 100644 --- a/libs/common/src/vault/models/domain/login-uri.ts +++ b/libs/common/src/vault/models/domain/login-uri.ts @@ -31,29 +31,27 @@ export class LoginUri extends Domain { } decrypt( - orgId: string | undefined, + encKey: SymmetricCryptoKey, context: string = "No Cipher Context", - encKey?: SymmetricCryptoKey, ): Promise { return this.decryptObj( this, new LoginUriView(this), ["uri"], - orgId ?? null, encKey, context, ); } - async validateChecksum(clearTextUri: string, orgId?: string, encKey?: SymmetricCryptoKey) { + async validateChecksum(clearTextUri: string, encKey: SymmetricCryptoKey) { if (this.uriChecksum == null) { return false; } - const keyService = Utils.getContainerService().getEncryptService(); - const localChecksum = await keyService.hash(clearTextUri, "sha256"); + const encryptService = Utils.getContainerService().getEncryptService(); + const localChecksum = await encryptService.hash(clearTextUri, "sha256"); - const remoteChecksum = await this.uriChecksum.decrypt(orgId ?? null, encKey); + const remoteChecksum = await encryptService.decryptString(this.uriChecksum, encKey); return remoteChecksum === localChecksum; } diff --git a/libs/common/src/vault/models/domain/login.spec.ts b/libs/common/src/vault/models/domain/login.spec.ts index 6ebcfea057a..fbacd912c60 100644 --- a/libs/common/src/vault/models/domain/login.spec.ts +++ b/libs/common/src/vault/models/domain/login.spec.ts @@ -1,6 +1,6 @@ import { MockProxy, mock } from "jest-mock-extended"; -import { mockEnc, mockFromJson } from "../../../../spec"; +import { mockContainerService, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { UriMatchStrategy } from "../../../models/domain/domain-service"; import { LoginData } from "../../models/data/login.data"; @@ -14,6 +14,10 @@ import { Fido2CredentialView } from "../view/fido2-credential.view"; import { Fido2Credential } from "./fido2-credential"; describe("Login DTO", () => { + beforeEach(() => { + mockContainerService(); + }); + it("Convert from empty LoginData", () => { const data = new LoginData(); const login = new Login(data); @@ -107,7 +111,7 @@ describe("Login DTO", () => { loginUri.validateChecksum.mockResolvedValue(true); login.uris = [loginUri]; - const loginView = await login.decrypt(null, true); + const loginView = await login.decrypt(true, null); expect(loginView).toEqual(expectedView); }); @@ -119,7 +123,7 @@ describe("Login DTO", () => { .mockResolvedValueOnce(true); login.uris = [loginUri, loginUri, loginUri]; - const loginView = await login.decrypt(null, false); + const loginView = await login.decrypt(false, null); expect(loginView).toEqual(expectedView); }); }); diff --git a/libs/common/src/vault/models/domain/login.ts b/libs/common/src/vault/models/domain/login.ts index a9cec13fc7c..830fc48b7d1 100644 --- a/libs/common/src/vault/models/domain/login.ts +++ b/libs/common/src/vault/models/domain/login.ts @@ -44,16 +44,14 @@ export class Login extends Domain { } async decrypt( - orgId: string | undefined, bypassValidation: boolean, + encKey: SymmetricCryptoKey, context: string = "No Cipher Context", - encKey?: SymmetricCryptoKey, ): Promise { const view = await this.decryptObj( this, new LoginView(this), ["username", "password", "totp"], - orgId ?? null, encKey, `DomainType: Login; ${context}`, ); @@ -66,7 +64,7 @@ export class Login extends Domain { continue; } - const uri = await this.uris[i].decrypt(orgId, context, encKey); + const uri = await this.uris[i].decrypt(encKey, context); const uriString = uri.uri; if (uriString == null) { @@ -79,7 +77,7 @@ export class Login extends Domain { // So we bypass the validation if there's no cipher.key or proceed with the validation and // Skip the value if it's been tampered with. const isValidUri = - bypassValidation || (await this.uris[i].validateChecksum(uriString, orgId, encKey)); + bypassValidation || (await this.uris[i].validateChecksum(uriString, encKey)); if (isValidUri) { view.uris.push(uri); @@ -89,7 +87,7 @@ export class Login extends Domain { if (this.fido2Credentials != null) { view.fido2Credentials = await Promise.all( - this.fido2Credentials.map((key) => key.decrypt(orgId, encKey)), + this.fido2Credentials.map((key) => key.decrypt(encKey)), ); } diff --git a/libs/common/src/vault/models/domain/password.spec.ts b/libs/common/src/vault/models/domain/password.spec.ts index 4b2de34beca..fe9918972c4 100644 --- a/libs/common/src/vault/models/domain/password.spec.ts +++ b/libs/common/src/vault/models/domain/password.spec.ts @@ -1,4 +1,4 @@ -import { mockEnc, mockFromJson } from "../../../../spec"; +import { mockContainerService, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; import { PasswordHistoryData } from "../../models/data/password-history.data"; import { Password } from "../../models/domain/password"; @@ -11,6 +11,7 @@ describe("Password", () => { password: "encPassword", lastUsedDate: "2022-01-31T12:00:00.000Z", }; + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/vault/models/domain/password.ts b/libs/common/src/vault/models/domain/password.ts index 84e8919b905..960fd3d5e52 100644 --- a/libs/common/src/vault/models/domain/password.ts +++ b/libs/common/src/vault/models/domain/password.ts @@ -22,12 +22,11 @@ export class Password extends Domain { this.lastUsedDate = new Date(obj.lastUsedDate); } - decrypt(orgId: string | undefined, encKey?: SymmetricCryptoKey): Promise { + decrypt(encKey: SymmetricCryptoKey): Promise { return this.decryptObj( this, new PasswordHistoryView(this), ["password"], - orgId ?? null, encKey, "DomainType: PasswordHistory", ); diff --git a/libs/common/src/vault/models/domain/secure-note.spec.ts b/libs/common/src/vault/models/domain/secure-note.spec.ts index e445e9ea035..c5746d8f8e7 100644 --- a/libs/common/src/vault/models/domain/secure-note.spec.ts +++ b/libs/common/src/vault/models/domain/secure-note.spec.ts @@ -1,3 +1,4 @@ +import { mockContainerService } from "../../../../spec"; import { SecureNoteType } from "../../enums"; import { SecureNoteData } from "../data/secure-note.data"; @@ -10,6 +11,8 @@ describe("SecureNote", () => { data = { type: SecureNoteType.Generic, }; + + mockContainerService(); }); it("Convert from empty", () => { diff --git a/libs/common/src/vault/models/domain/ssh-key.spec.ts b/libs/common/src/vault/models/domain/ssh-key.spec.ts index 10149ebc82d..c4ecc1e54f6 100644 --- a/libs/common/src/vault/models/domain/ssh-key.spec.ts +++ b/libs/common/src/vault/models/domain/ssh-key.spec.ts @@ -1,7 +1,7 @@ import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString as SdkEncString, SshKey as SdkSshKey } from "@bitwarden/sdk-internal"; -import { mockEnc } from "../../../../spec"; +import { mockContainerService, mockEnc } from "../../../../spec"; import { SshKeyApi } from "../api/ssh-key.api"; import { SshKeyData } from "../data/ssh-key.data"; @@ -18,6 +18,8 @@ describe("Sshkey", () => { KeyFingerprint: "keyFingerprint", }), ); + + mockContainerService(); }); it("Convert", () => { diff --git a/libs/common/src/vault/models/domain/ssh-key.ts b/libs/common/src/vault/models/domain/ssh-key.ts index a7028321a44..dc9a23403a8 100644 --- a/libs/common/src/vault/models/domain/ssh-key.ts +++ b/libs/common/src/vault/models/domain/ssh-key.ts @@ -24,16 +24,11 @@ export class SshKey extends Domain { this.keyFingerprint = new EncString(obj.keyFingerprint); } - decrypt( - orgId: string | undefined, - context = "No Cipher Context", - encKey?: SymmetricCryptoKey, - ): Promise { + decrypt(encKey: SymmetricCryptoKey, context = "No Cipher Context"): Promise { return this.decryptObj( this, new SshKeyView(), ["privateKey", "publicKey", "keyFingerprint"], - orgId ?? null, encKey, "DomainType: SshKey; " + context, ); diff --git a/libs/common/src/vault/services/cipher.service.spec.ts b/libs/common/src/vault/services/cipher.service.spec.ts index fe2926144b8..50823807fcf 100644 --- a/libs/common/src/vault/services/cipher.service.spec.ts +++ b/libs/common/src/vault/services/cipher.service.spec.ts @@ -55,7 +55,7 @@ const ENCRYPTED_BYTES = mock(); const cipherData: CipherData = { id: "id", - organizationId: "orgId", + organizationId: "4ff8c0b2-1d3e-4f8c-9b2d-1d3e4f8c0b2" as OrganizationId, folderId: "folderId", edit: true, viewPassword: true, @@ -119,6 +119,8 @@ describe("Cipher Service", () => { beforeEach(() => { encryptService.encryptFileData.mockReturnValue(Promise.resolve(ENCRYPTED_BYTES)); encryptService.encryptString.mockReturnValue(Promise.resolve(new EncString(ENCRYPTED_TEXT))); + keyService.orgKeys$.mockReturnValue(of({ [orgId]: makeSymmetricCryptoKey(32) as OrgKey })); + keyService.userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64) as UserKey)); // Mock i18nService collator i18nService.collator = { @@ -181,9 +183,6 @@ describe("Cipher Service", () => { const testCipher = new Cipher(cipherData); const expectedRevisionDate = "2022-01-31T12:00:00.000Z"; - keyService.getOrgKey.mockReturnValue( - Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey), - ); keyService.makeDataEncKey.mockReturnValue( Promise.resolve([ new SymmetricCryptoKey(new Uint8Array(32)), diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index a3bd229e80c..7eebe960a7f 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -1564,10 +1564,15 @@ export class CipherService implements CipherServiceAbstraction { } async getKeyForCipherKeyDecryption(cipher: Cipher, userId: UserId): Promise { - return ( - (await this.keyService.getOrgKey(cipher.organizationId)) || - ((await this.keyService.getUserKey(userId)) as UserKey) - ); + if (cipher.organizationId == null) { + return await firstValueFrom(this.keyService.userKey$(userId)); + } else { + return await firstValueFrom( + this.keyService + .orgKeys$(userId) + .pipe(map((orgKeys) => orgKeys[cipher.organizationId as OrganizationId] as OrgKey)), + ); + } } async setAddEditCipherInfo(value: AddEditCipherInfo, userId: UserId) { diff --git a/libs/components/src/icon-button/icon-button.component.html b/libs/components/src/icon-button/icon-button.component.html index b5826ce9928..447d04e7d41 100644 --- a/libs/components/src/icon-button/icon-button.component.html +++ b/libs/components/src/icon-button/icon-button.component.html @@ -1,6 +1,6 @@ - + [this.icon(), "!tw-m-0"]); protected readonly disabledAttr = computed(() => { const disabled = this.disabled() != null && this.disabled() !== false; diff --git a/libs/components/src/icon-button/icon-button.stories.ts b/libs/components/src/icon-button/icon-button.stories.ts index c93beb167bd..83e8e051b86 100644 --- a/libs/components/src/icon-button/icon-button.stories.ts +++ b/libs/components/src/icon-button/icon-button.stories.ts @@ -5,7 +5,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { formatArgsForCodeSnippet } from "../../../../.storybook/format-args-for-code-snippet"; import { I18nMockService } from "../utils"; -import { BitIconButtonComponent } from "./icon-button.component"; +import { BitIconButtonComponent, IconButtonTypes } from "./icon-button.component"; export default { title: "Component Library/Icon Button", @@ -30,7 +30,7 @@ export default { }, argTypes: { buttonType: { - options: ["primary", "secondary", "danger", "unstyled", "contrast", "main", "muted", "light"], + options: IconButtonTypes, }, }, parameters: { diff --git a/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts b/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts index bf74bcd69fa..1f5be7f18ab 100644 --- a/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts +++ b/libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts @@ -6,7 +6,6 @@ import { filter, firstValueFrom } from "rxjs"; // eslint-disable-next-line no-restricted-imports import { Collection, CollectionView } from "@bitwarden/admin-console/common"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; -import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { @@ -46,6 +45,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { } async parse(data: string): Promise { + const account = await firstValueFrom(this.accountService.activeAccount$); this.result = new ImportResult(); const results: BitwardenJsonExport = JSON.parse(data); if (results == null || results.items == null) { @@ -54,9 +54,9 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { } if (results.encrypted) { - await this.parseEncrypted(results as any); + await this.parseEncrypted(results as any, account.id); } else { - await this.parseDecrypted(results as any); + await this.parseDecrypted(results as any, account.id); } return this.result; @@ -64,9 +64,8 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { private async parseEncrypted( results: BitwardenEncryptedIndividualJsonExport | BitwardenEncryptedOrgJsonExport, + userId: UserId, ) { - const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - if (results.encKeyValidation_DO_NOT_EDIT != null) { const orgKeys = await firstValueFrom(this.keyService.orgKeys$(userId)); let keyForDecryption: SymmetricCryptoKey = orgKeys?.[this.organizationId]; @@ -84,8 +83,8 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { } const groupingsMap = this.organization - ? await this.parseCollections(userId, results as BitwardenEncryptedOrgJsonExport) - : await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport); + ? await this.parseCollections(results as BitwardenEncryptedOrgJsonExport, userId) + : await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport, userId); for (const c of results.items) { const cipher = CipherWithIdExport.toDomain(c); @@ -125,12 +124,11 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { private async parseDecrypted( results: BitwardenUnEncryptedIndividualJsonExport | BitwardenUnEncryptedOrgJsonExport, + userId: UserId, ) { - const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - const groupingsMap = this.organization - ? await this.parseCollections(userId, results as BitwardenUnEncryptedOrgJsonExport) - : await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport); + ? await this.parseCollections(results as BitwardenUnEncryptedOrgJsonExport, userId) + : await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport, userId); results.items.forEach((c) => { const cipher = CipherWithIdExport.toView(c); @@ -169,11 +167,14 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { private async parseFolders( data: BitwardenUnEncryptedIndividualJsonExport | BitwardenEncryptedIndividualJsonExport, + userId: UserId, ): Promise> | null { if (data.folders == null) { return null; } + const userKey = await firstValueFrom(this.keyService.userKey$(userId)); + const groupingsMap = new Map(); for (const f of data.folders) { @@ -181,7 +182,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { if (data.encrypted) { const folder = FolderWithIdExport.toDomain(f); if (folder != null) { - folderView = await folder.decrypt(); + folderView = await folder.decrypt(userKey); } } else { folderView = FolderWithIdExport.toView(f); @@ -196,8 +197,8 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer { } private async parseCollections( - userId: UserId, data: BitwardenUnEncryptedOrgJsonExport | BitwardenEncryptedOrgJsonExport, + userId: UserId, ): Promise> | null { if (data.collections == null) { return null; diff --git a/package-lock.json b/package-lock.json index b03c0c7b20c..505c12b320c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,7 +82,7 @@ "@angular/compiler-cli": "20.3.15", "@babel/core": "7.28.5", "@babel/preset-env": "7.28.5", - "@compodoc/compodoc": "1.1.26", + "@compodoc/compodoc": "1.1.32", "@electron/notarize": "3.0.1", "@electron/rebuild": "4.0.1", "@eslint/compat": "2.0.0", @@ -125,7 +125,7 @@ "axe-playwright": "2.2.2", "babel-loader": "9.2.1", "base64-loader": "1.0.0", - "browserslist": "4.28.0", + "browserslist": "4.28.1", "chromatic": "13.3.1", "concurrently": "9.2.0", "copy-webpack-plugin": "13.0.1", @@ -1595,16 +1595,6 @@ "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/core/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, "node_modules/@angular-devkit/schematics": { "version": "20.3.12", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.3.12.tgz", @@ -2703,6 +2693,16 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@arr/every": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@arr/every/-/every-1.0.1.tgz", + "integrity": "sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@asamuzakjp/css-color": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", @@ -4830,34 +4830,36 @@ "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@compodoc/compodoc": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.26.tgz", - "integrity": "sha512-CJkqTtdotxMA4SDyUx8J6Mrm3MMmcgFtfEViUnG9Of2CXhYiXIqNeD881+pxn0opmMC+VCTL0/SCD03tDYhWYA==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.32.tgz", + "integrity": "sha512-kaYk5+o4k7GB585iphwV5NE49BKKk8d+gJLNBE8eu2fIRdhnHOWblasRbOBRULfwJ+qxfmgrIqi32K34wCag6A==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular-devkit/schematics": "18.2.8", - "@babel/core": "7.25.8", - "@babel/plugin-transform-private-methods": "7.25.7", - "@babel/preset-env": "7.25.8", + "@angular-devkit/schematics": "20.3.4", + "@babel/core": "7.28.4", + "@babel/plugin-transform-private-methods": "7.27.1", + "@babel/preset-env": "7.28.3", "@compodoc/live-server": "^1.2.3", "@compodoc/ngd-transformer": "^2.1.3", - "bootstrap.native": "^5.0.13", - "cheerio": "1.0.0-rc.12", - "chokidar": "^4.0.1", + "@polka/send-type": "^0.5.2", + "body-parser": "^2.2.0", + "bootstrap.native": "^5.1.6", + "cheerio": "1.1.2", + "chokidar": "^4.0.3", "colors": "1.4.0", - "commander": "^12.1.0", + "commander": "^14.0.1", "cosmiconfig": "^9.0.0", "decache": "^4.6.2", "es6-shim": "^0.35.8", "fancy-log": "^2.0.0", - "fast-glob": "^3.3.2", - "fs-extra": "^11.2.0", - "glob": "^11.0.0", + "fast-glob": "^3.3.3", + "fs-extra": "^11.3.2", + "glob": "^11.0.3", "handlebars": "^4.7.8", - "html-entities": "^2.5.2", - "i18next": "^23.16.0", + "html-entities": "^2.6.0", + "i18next": "25.5.3", "json5": "^2.2.3", "lodash": "^4.17.21", "loglevel": "^1.9.2", @@ -4868,62 +4870,45 @@ "neotraverse": "^0.6.18", "opencollective-postinstall": "^2.0.3", "os-name": "4.0.1", - "picocolors": "^1.1.0", - "prismjs": "^1.29.0", - "semver": "^7.6.3", - "svg-pan-zoom": "^3.6.1", - "tablesort": "^5.3.0", - "ts-morph": "^24.0.0", - "uuid": "^10.0.0", - "vis": "^4.21.0-EOL" + "picocolors": "^1.1.1", + "polka": "^0.5.2", + "prismjs": "^1.30.0", + "semver": "^7.7.2", + "sirv": "^3.0.2", + "svg-pan-zoom": "^3.6.2", + "tablesort": "^5.6.0", + "ts-morph": "^27.0.0", + "uuid": "11.1.0", + "vis-network": "^10.0.2" }, "bin": { "compodoc": "bin/index-cli.js" }, "engines": { - "node": ">= 16.0.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics": { - "version": "18.2.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.8.tgz", - "integrity": "sha512-i/h2Oji5FhJMC7wDSnIl5XUe/qym+C1ZwScaATJwDyRLCUIynZkj5rLgdG/uK6l+H0PgvxigkF+akWpokkwW6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "18.2.8", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.11", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "18.2.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.8.tgz", - "integrity": "sha512-4o2T6wsmXGE/v53+F8L7kGoN2+qzt03C9rtjLVQpOljzpJVttQ8bhvfWxyYLWwcl04RWqRa+82fpIZtBkOlZJw==", + "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/core": { + "version": "20.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.4.tgz", + "integrity": "sha512-r83jn9yVdPh618oGgoKPggMsQGOkQqJbxEutd4CE9mnotPCE2uRTIyaFMh8sohNUeoQNRmj9rbr2pWGVlgERpg==", "dev": true, "license": "MIT", "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" + "picomatch": "4.0.3", + "rxjs": "7.8.2", + "source-map": "0.7.6" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "peerDependencies": { - "chokidar": "^3.5.2" + "chokidar": "^4.0.0" }, "peerDependenciesMeta": { "chokidar": { @@ -4931,50 +4916,42 @@ } } }, - "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics": { + "version": "20.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.3.4.tgz", + "integrity": "sha512-JYlcmVBKNT9+cQ6T2tmu+yVQ2bJk8tG0mXvPHWXrl/M4c6NObhSSThK50tJHy0Xo3gl8WgogOxUeJNnBq67cIQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "@angular-devkit/core": "20.3.4", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "8.2.0", + "rxjs": "7.8.2" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, "node_modules/@compodoc/compodoc/node_modules/@babel/core": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", - "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helpers": "^7.25.7", - "@babel/parser": "^7.25.8", - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.8", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -4999,97 +4976,82 @@ "semver": "bin/semver.js" } }, - "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", - "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@compodoc/compodoc/node_modules/@babel/preset-env": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.8.tgz", - "integrity": "sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", + "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.8", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/compat-data": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.25.7", - "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.8", - "@babel/plugin-transform-async-to-generator": "^7.25.7", - "@babel/plugin-transform-block-scoped-functions": "^7.25.7", - "@babel/plugin-transform-block-scoping": "^7.25.7", - "@babel/plugin-transform-class-properties": "^7.25.7", - "@babel/plugin-transform-class-static-block": "^7.25.8", - "@babel/plugin-transform-classes": "^7.25.7", - "@babel/plugin-transform-computed-properties": "^7.25.7", - "@babel/plugin-transform-destructuring": "^7.25.7", - "@babel/plugin-transform-dotall-regex": "^7.25.7", - "@babel/plugin-transform-duplicate-keys": "^7.25.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-dynamic-import": "^7.25.8", - "@babel/plugin-transform-exponentiation-operator": "^7.25.7", - "@babel/plugin-transform-export-namespace-from": "^7.25.8", - "@babel/plugin-transform-for-of": "^7.25.7", - "@babel/plugin-transform-function-name": "^7.25.7", - "@babel/plugin-transform-json-strings": "^7.25.8", - "@babel/plugin-transform-literals": "^7.25.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.8", - "@babel/plugin-transform-member-expression-literals": "^7.25.7", - "@babel/plugin-transform-modules-amd": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-modules-systemjs": "^7.25.7", - "@babel/plugin-transform-modules-umd": "^7.25.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-new-target": "^7.25.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.8", - "@babel/plugin-transform-numeric-separator": "^7.25.8", - "@babel/plugin-transform-object-rest-spread": "^7.25.8", - "@babel/plugin-transform-object-super": "^7.25.7", - "@babel/plugin-transform-optional-catch-binding": "^7.25.8", - "@babel/plugin-transform-optional-chaining": "^7.25.8", - "@babel/plugin-transform-parameters": "^7.25.7", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/plugin-transform-private-property-in-object": "^7.25.8", - "@babel/plugin-transform-property-literals": "^7.25.7", - "@babel/plugin-transform-regenerator": "^7.25.7", - "@babel/plugin-transform-reserved-words": "^7.25.7", - "@babel/plugin-transform-shorthand-properties": "^7.25.7", - "@babel/plugin-transform-spread": "^7.25.7", - "@babel/plugin-transform-sticky-regex": "^7.25.7", - "@babel/plugin-transform-template-literals": "^7.25.7", - "@babel/plugin-transform-typeof-symbol": "^7.25.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.7", - "@babel/plugin-transform-unicode-property-regex": "^7.25.7", - "@babel/plugin-transform-unicode-regex": "^7.25.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.3", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.3", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", "semver": "^6.3.1" }, "engines": { @@ -5109,28 +5071,69 @@ "semver": "bin/semver.js" } }, - "node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@compodoc/compodoc/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/@compodoc/compodoc/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@compodoc/compodoc/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@compodoc/compodoc/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" } }, "node_modules/@compodoc/compodoc/node_modules/convert-source-map": { @@ -5140,61 +5143,183 @@ "dev": true, "license": "MIT" }, - "node_modules/@compodoc/compodoc/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@compodoc/compodoc/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC", - "optional": true, - "peer": true, + "license": "MIT" + }, + "node_modules/@compodoc/compodoc/node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">= 6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@compodoc/compodoc/node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "node_modules/@compodoc/compodoc/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/@compodoc/compodoc/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@compodoc/compodoc/node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/@compodoc/compodoc/node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/@compodoc/compodoc/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/compodoc/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@compodoc/live-server": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@compodoc/live-server/-/live-server-1.2.3.tgz", @@ -5570,6 +5695,20 @@ "node": ">=14.17.0" } }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@electron/asar": { "version": "3.2.18", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", @@ -11693,6 +11832,20 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@polka/send-type": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@polka/send-type/-/send-type-0.5.2.tgz", + "integrity": "sha512-jGXalKihnhGQmMQ+xxfxrRfI2cWs38TIZuwgYpnbQDD4r9TkOiU3ocjAS+6CqqMNQNAu9Ul2iHU5YFRDODak2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@polka/url": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz", + "integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.52.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.3.tgz", @@ -13334,28 +13487,28 @@ } }, "node_modules/@ts-morph/common": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.25.0.tgz", - "integrity": "sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz", + "integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==", "dev": true, "license": "MIT", "dependencies": { - "minimatch": "^9.0.4", + "minimatch": "^10.0.1", "path-browserify": "^1.0.1", - "tinyglobby": "^0.2.9" + "tinyglobby": "^0.2.14" } }, "node_modules/@ts-morph/common/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -13696,6 +13849,14 @@ "@types/node": "*" } }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@types/har-format": { "version": "1.2.16", "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", @@ -16893,9 +17054,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.30", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.30.tgz", - "integrity": "sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.3.tgz", + "integrity": "sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -17198,9 +17359,9 @@ "optional": true }, "node_modules/bootstrap.native": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/bootstrap.native/-/bootstrap.native-5.1.5.tgz", - "integrity": "sha512-sQdFng2Szpseyo1TlpG5pV+se4nbGeQWFXBemsPSnrVzd82ps9F6hti+lHFwcGgS80oIc54dY5ycOYJwUpQn3A==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/bootstrap.native/-/bootstrap.native-5.1.6.tgz", + "integrity": "sha512-bLveDBWhNLoFLsPctVo6yxSRQ1ysmKHBa+1FFMTQuruzTb3y7/InGSoe5lZdOiqZ4L0UOzpdbXMsI+bA5DoRew==", "dev": true, "license": "MIT", "dependencies": { @@ -17278,9 +17439,9 @@ "license": "MIT" }, "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "funding": [ { "type": "opencollective", @@ -17297,11 +17458,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -17858,9 +18019,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001756", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", - "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", "funding": [ { "type": "opencollective", @@ -17984,22 +18145,26 @@ } }, "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz", + "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==", "dev": true, "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.12.0", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=20.18.1" }, "funding": { "url": "https://github.com/cheeriojs/cheerio?sponsor=1" @@ -18023,26 +18188,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cheerio/node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -18528,6 +18673,20 @@ "node": ">=0.10.0" } }, + "node_modules/component-emitter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-2.0.0.tgz", + "integrity": "sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -20607,9 +20766,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.259", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", - "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", + "version": "1.5.266", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", + "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", "license": "ISC" }, "node_modules/electron-updater": { @@ -20731,15 +20890,6 @@ "node": ">= 4.0.0" } }, - "node_modules/emitter-component": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.2.tgz", - "integrity": "sha512-QdXO3nXOzZB4pAjM0n6ZE+R9/+kPpECA/XSELIcc54NeYVnBqIk+4DFiBgK+8QbV3mdvTG6nedl7dTYgO+5wDw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -20786,6 +20936,20 @@ "iconv-lite": "^0.6.2" } }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -22875,9 +23039,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "dependencies": { @@ -23320,16 +23484,6 @@ "dev": true, "license": "MIT" }, - "node_modules/hammerjs": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", - "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -23997,9 +24151,9 @@ } }, "node_modules/i18next": { - "version": "23.16.8", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", - "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "version": "25.5.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.5.3.tgz", + "integrity": "sha512-joFqorDeQ6YpIXni944upwnuHBf5IoPMuqAchGVeQLdWC2JOjxgM9V8UGLhNIIH/Q8QleRxIi0BSRQehSrDLcg==", "dev": true, "funding": [ { @@ -24017,7 +24171,15 @@ ], "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2" + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/iconv-corefoundation": { @@ -27381,7 +27543,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.2.0.tgz", "integrity": "sha512-i/XBRTiLqRConPKioy2oq45vbv04e8x59b0mnsIRQM+7Ec/8BC7UcL5pnC4FMeGb8KwG7q4wOMw7CtNZf5tiIg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/keygrip": { "version": "1.1.0", @@ -28856,6 +29019,19 @@ "node": ">=10" } }, + "node_modules/matchit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/matchit/-/matchit-1.1.0.tgz", + "integrity": "sha512-+nGYoOlfHmxe5BW5tE0EMJppXEwdSf8uBA1GTZC7Q77kbT35+VKLYJMzVNWCHSsga1ps1tPYFtFyvxvKzWVmMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@arr/every": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -30118,16 +30294,6 @@ "dev": true, "license": "MIT" }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -33079,6 +33245,19 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parse5-sax-parser": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", @@ -33542,6 +33721,17 @@ "node": ">=10.4.0" } }, + "node_modules/polka": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/polka/-/polka-0.5.2.tgz", + "integrity": "sha512-FVg3vDmCqP80tOrs+OeNlgXYmFppTXdjD5E7I4ET1NjvtNmQrb1/mJibybKkb/d4NA7YWAr1ojxuhpL3FHqdlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^0.5.0", + "trouter": "^2.0.1" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -34594,16 +34784,6 @@ "node": ">= 6" } }, - "node_modules/propagating-hammerjs": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/propagating-hammerjs/-/propagating-hammerjs-1.5.0.tgz", - "integrity": "sha512-3PUXWmomwutoZfydC+lJwK1bKCh6sK6jZGB31RUX6+4EXzsbkDZrK4/sVR7gBrvJaEIwpTVyxQUAd29FKkmVdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hammerjs": "^2.0.8" - } - }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -36918,6 +37098,28 @@ "node": ">=10" } }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/sirv/node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -37025,12 +37227,12 @@ } }, "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/source-map-js": { @@ -38696,6 +38898,16 @@ "node": ">=0.6" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -38768,6 +38980,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trouter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/trouter/-/trouter-2.0.1.tgz", + "integrity": "sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "matchit": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -38910,13 +39135,13 @@ } }, "node_modules/ts-morph": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-24.0.0.tgz", - "integrity": "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz", + "integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==", "dev": true, "license": "MIT", "dependencies": { - "@ts-morph/common": "~0.25.0", + "@ts-morph/common": "~0.28.1", "code-block-writer": "^13.0.3" } }, @@ -39790,6 +40015,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -40029,9 +40264,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", "funding": [ { "type": "opencollective", @@ -40155,9 +40390,9 @@ } }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -40165,7 +40400,7 @@ ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { @@ -40284,19 +40519,58 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vis": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/vis/-/vis-4.21.0.tgz", - "integrity": "sha512-jonDXTGm2mFU/X6Kg9pvkZEQtXh2J6+NlDJD1tDP7TDCFy+qNeKlsTcXKQtv4nAtUIiKo6sphCt4kbRlEKw75A==", - "deprecated": "Please consider using https://github.com/visjs", + "node_modules/vis-data": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/vis-data/-/vis-data-8.0.3.tgz", + "integrity": "sha512-jhnb6rJNqkKR1Qmlay0VuDXY9ZlvAnYN1udsrP4U+krgZEq7C0yNSKdZqmnCe13mdnf9AdVcdDGFOzy2mpPoqw==", "dev": true, "license": "(Apache-2.0 OR MIT)", - "dependencies": { - "emitter-component": "^1.1.1", - "hammerjs": "^2.0.8", - "keycharm": "^0.2.0", - "moment": "^2.18.1", - "propagating-hammerjs": "^1.4.6" + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/visjs" + }, + "peerDependencies": { + "uuid": "^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^13.0.0", + "vis-util": ">=6.0.0" + } + }, + "node_modules/vis-network": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/vis-network/-/vis-network-10.0.2.tgz", + "integrity": "sha512-qPl8GLYBeHEFqiTqp4VBbYQIJ2EA8KLr7TstA2E8nJxfEHaKCU81hQLz7hhq11NUpHbMaRzBjW5uZpVKJ45/wA==", + "dev": true, + "license": "(Apache-2.0 OR MIT)", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/visjs" + }, + "peerDependencies": { + "@egjs/hammerjs": "^2.0.0", + "component-emitter": "^1.3.0 || ^2.0.0", + "keycharm": "^0.2.0 || ^0.3.0 || ^0.4.0", + "uuid": "^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^13.0.0", + "vis-data": ">=8.0.0", + "vis-util": ">=6.0.0" + } + }, + "node_modules/vis-util": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vis-util/-/vis-util-6.0.0.tgz", + "integrity": "sha512-qtpts3HRma0zPe4bO7t9A2uejkRNj8Z2Tb6do6lN85iPNWExFkUiVhdAq5uLGIUqBFduyYeqWJKv/jMkxX0R5g==", + "dev": true, + "license": "(Apache-2.0 OR MIT)", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/visjs" + }, + "peerDependencies": { + "@egjs/hammerjs": "^2.0.0", + "component-emitter": "^1.3.0 || ^2.0.0" } }, "node_modules/vite": { diff --git a/package.json b/package.json index fd56093210f..94019fafea8 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@angular/compiler-cli": "20.3.15", "@babel/core": "7.28.5", "@babel/preset-env": "7.28.5", - "@compodoc/compodoc": "1.1.26", + "@compodoc/compodoc": "1.1.32", "@electron/notarize": "3.0.1", "@electron/rebuild": "4.0.1", "@eslint/compat": "2.0.0", @@ -87,7 +87,7 @@ "axe-playwright": "2.2.2", "babel-loader": "9.2.1", "base64-loader": "1.0.0", - "browserslist": "4.28.0", + "browserslist": "4.28.1", "chromatic": "13.3.1", "concurrently": "9.2.0", "copy-webpack-plugin": "13.0.1",