From 94ebb2532780f01e4910147e2e3c1752722449ae Mon Sep 17 00:00:00 2001 From: jaasen-livefront Date: Mon, 27 Oct 2025 17:17:06 -0700 Subject: [PATCH] enforce strict types on folders --- .../common/src/models/export/folder.export.ts | 10 ++++---- .../src/vault/models/data/folder.data.ts | 19 +++++++++------ .../src/vault/models/domain/folder.spec.ts | 19 ++++++--------- libs/common/src/vault/models/domain/folder.ts | 23 ++++++++++--------- .../src/vault/models/view/folder.view.ts | 16 +++++++------ 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/libs/common/src/models/export/folder.export.ts b/libs/common/src/models/export/folder.export.ts index 96f0f1058b8..127a5b8baba 100644 --- a/libs/common/src/models/export/folder.export.ts +++ b/libs/common/src/models/export/folder.export.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { EncString } from "../../key-management/crypto/models/enc-string"; import { Folder as FolderDomain } from "../../vault/models/domain/folder"; import { FolderView } from "../../vault/models/view/folder.view"; @@ -7,6 +5,8 @@ import { FolderView } from "../../vault/models/view/folder.view"; import { safeGetString } from "./utils"; export class FolderExport { + name: string = ""; + static template(): FolderExport { const req = new FolderExport(); req.name = "Folder name"; @@ -19,14 +19,12 @@ export class FolderExport { } static toDomain(req: FolderExport, domain = new FolderDomain()) { - domain.name = req.name != null ? new EncString(req.name) : null; + domain.name = new EncString(req.name); return domain; } - name: string; - // Use build method instead of ctor so that we can control order of JSON stringify for pretty print build(o: FolderView | FolderDomain) { - this.name = safeGetString(o.name); + this.name = safeGetString(o.name) ?? ""; } } diff --git a/libs/common/src/vault/models/data/folder.data.ts b/libs/common/src/vault/models/data/folder.data.ts index c2eb585a6f4..f6ad114949f 100644 --- a/libs/common/src/vault/models/data/folder.data.ts +++ b/libs/common/src/vault/models/data/folder.data.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Jsonify } from "type-fest"; import { FolderResponse } from "../response/folder.response"; @@ -10,12 +8,19 @@ export class FolderData { revisionDate: string; constructor(response: Partial) { - this.name = response?.name; - this.id = response?.id; - this.revisionDate = response?.revisionDate; + this.name = response.name ?? ""; + this.id = response.id ?? ""; + this.revisionDate = response.revisionDate ?? ""; } - static fromJSON(obj: Jsonify) { - return Object.assign(new FolderData({}), obj); + static fromJSON(obj: Jsonify) { + if (obj == null) { + return null; + } + return new FolderData({ + id: obj.id, + name: obj.name, + revisionDate: obj.revisionDate, + }); } } diff --git a/libs/common/src/vault/models/domain/folder.spec.ts b/libs/common/src/vault/models/domain/folder.spec.ts index a837fbb2726..3b08c5490f1 100644 --- a/libs/common/src/vault/models/domain/folder.spec.ts +++ b/libs/common/src/vault/models/domain/folder.spec.ts @@ -2,7 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended"; import { makeEncString, makeSymmetricCryptoKey, mockEnc, mockFromJson } from "../../../../spec"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; -import { EncryptedString, EncString } from "../../../key-management/crypto/models/enc-string"; +import { EncString } from "../../../key-management/crypto/models/enc-string"; import { FolderData } from "../../models/data/folder.data"; import { Folder } from "../../models/domain/folder"; @@ -50,17 +50,14 @@ describe("Folder", () => { const revisionDate = new Date("2022-08-04T01:06:40.441Z"); const actual = Folder.fromJSON({ revisionDate: revisionDate.toISOString(), - name: "name" as EncryptedString, + name: "name", id: "id", }); - const expected = { - revisionDate: revisionDate, - name: "name_fromJSON", - id: "id", - }; - - expect(actual).toMatchObject(expected); + expect(actual?.id).toBe("id"); + expect(actual?.revisionDate).toEqual(revisionDate); + expect(actual?.name).toBeInstanceOf(EncString); + expect((actual?.name as EncString).encryptedString).toBe("name"); }); }); @@ -82,9 +79,7 @@ describe("Folder", () => { const view = await folder.decryptWithKey(key, encryptService); - expect(view).toEqual({ - name: "encName", - }); + expect(view.name).toBe("encName"); }); it("assigns the folder id and revision date", async () => { diff --git a/libs/common/src/vault/models/domain/folder.ts b/libs/common/src/vault/models/domain/folder.ts index 50c67eee01f..2a6355eb33f 100644 --- a/libs/common/src/vault/models/domain/folder.ts +++ b/libs/common/src/vault/models/domain/folder.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Jsonify } from "type-fest"; import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service"; @@ -10,19 +8,20 @@ import { FolderData } from "../data/folder.data"; import { FolderView } from "../view/folder.view"; export class Test extends Domain { - id: string; - name: EncString; - revisionDate: Date; + id: string = ""; + name: EncString = new EncString(""); + revisionDate: Date = new Date(); } export class Folder extends Domain { - id: string; - name: EncString; + id: string = ""; + name: EncString = new EncString(""); revisionDate: Date; constructor(obj?: FolderData) { super(); if (obj == null) { + this.revisionDate = new Date(); return; } @@ -35,8 +34,8 @@ export class Folder extends Domain { }, ["id"], ); - - this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null; + this.name = new EncString(obj.name); + this.revisionDate = new Date(obj.revisionDate); } decrypt(): Promise { @@ -62,7 +61,9 @@ export class Folder extends Domain { } static fromJSON(obj: Jsonify) { - const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate); - return Object.assign(new Folder(), obj, { name: EncString.fromJSON(obj.name), revisionDate }); + if (obj == null) { + return null; + } + return new Folder({ name: obj.name, revisionDate: obj.revisionDate, id: obj.id }); } } diff --git a/libs/common/src/vault/models/view/folder.view.ts b/libs/common/src/vault/models/view/folder.view.ts index bc908e98eb8..d0126a728ea 100644 --- a/libs/common/src/vault/models/view/folder.view.ts +++ b/libs/common/src/vault/models/view/folder.view.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Jsonify } from "type-fest"; import { View } from "../../../models/view/view"; @@ -8,12 +6,13 @@ import { Folder } from "../domain/folder"; import { ITreeNodeObject } from "../domain/tree-node"; export class FolderView implements View, ITreeNodeObject { - id: string = null; - name: string = null; - revisionDate: Date = null; + id: string = ""; + name: string = ""; + revisionDate: Date; constructor(f?: Folder | DecryptedObject) { if (!f) { + this.revisionDate = new Date(); return; } @@ -22,7 +21,10 @@ export class FolderView implements View, ITreeNodeObject { } static fromJSON(obj: Jsonify) { - const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate); - return Object.assign(new FolderView(), obj, { revisionDate }); + const folderView = new FolderView(); + folderView.id = obj.id; + folderView.name = obj.name; + folderView.revisionDate = new Date(obj.revisionDate); + return folderView; } }