From 4f5f28a92d67ab074a7d1d5e2dab23bd6f76c460 Mon Sep 17 00:00:00 2001 From: Miodec Date: Wed, 7 Feb 2024 23:13:10 +0100 Subject: [PATCH] refactor(types): ape keys types move to shared types (#4774) add types to ape client (#4786) --- backend/src/api/controllers/ape-key.ts | 4 +- backend/src/dal/ape-keys.ts | 52 ++++++++++++----------- backend/src/types/types.d.ts | 9 +--- frontend/src/ts/ape/endpoints/ape-keys.ts | 11 +++-- frontend/src/ts/ape/types/ape-keys.d.ts | 9 ++++ frontend/src/ts/popups/ape-keys-popup.ts | 8 ++-- frontend/src/ts/popups/simple-popups.ts | 3 +- frontend/src/ts/types/types.d.ts | 12 ------ shared-types/types.d.ts | 9 ++++ 9 files changed, 62 insertions(+), 55 deletions(-) create mode 100644 frontend/src/ts/ape/types/ape-keys.d.ts diff --git a/backend/src/api/controllers/ape-key.ts b/backend/src/api/controllers/ape-key.ts index 42298f331..85e21871c 100644 --- a/backend/src/api/controllers/ape-key.ts +++ b/backend/src/api/controllers/ape-key.ts @@ -7,7 +7,7 @@ import { MonkeyResponse } from "../../utils/monkey-response"; import { base64UrlEncode } from "../../utils/misc"; import { ObjectId } from "mongodb"; -function cleanApeKey(apeKey: MonkeyTypes.ApeKey): Partial { +function cleanApeKey(apeKey: MonkeyTypes.ApeKeyDB): SharedTypes.ApeKey { return _.omit(apeKey, "hash", "_id", "uid", "useCount"); } @@ -39,7 +39,7 @@ export async function generateApeKey( const apiKey = randomBytes(apeKeyBytes).toString("base64url"); const saltyHash = await hash(apiKey, apeKeySaltRounds); - const apeKey: MonkeyTypes.ApeKey = { + const apeKey: MonkeyTypes.ApeKeyDB = { _id: new ObjectId(), name, enabled, diff --git a/backend/src/dal/ape-keys.ts b/backend/src/dal/ape-keys.ts index df518771a..46a08aaed 100644 --- a/backend/src/dal/ape-keys.ts +++ b/backend/src/dal/ape-keys.ts @@ -1,33 +1,36 @@ import _ from "lodash"; import * as db from "../init/db"; -import { Filter, ObjectId, MatchKeysAndValues } from "mongodb"; +import { + Filter, + ObjectId, + MatchKeysAndValues, + Collection, + WithId, +} from "mongodb"; import MonkeyError from "../utils/error"; -const COLLECTION_NAME = "ape-keys"; +export const getApeKeysCollection = (): Collection< + WithId +> => db.collection("ape-keys"); function getApeKeyFilter( uid: string, keyId: string -): Filter { +): Filter { return { _id: new ObjectId(keyId), uid, }; } -export async function getApeKeys(uid: string): Promise { - return await db - .collection(COLLECTION_NAME) - .find({ uid }) - .toArray(); +export async function getApeKeys(uid: string): Promise { + return await getApeKeysCollection().find({ uid }).toArray(); } export async function getApeKey( keyId: string -): Promise { - return await db - .collection(COLLECTION_NAME) - .findOne({ _id: new ObjectId(keyId) }); +): Promise { + return await getApeKeysCollection().findOne({ _id: new ObjectId(keyId) }); } export async function countApeKeysForUser(uid: string): Promise { @@ -35,24 +38,23 @@ export async function countApeKeysForUser(uid: string): Promise { return _.size(apeKeys); } -export async function addApeKey(apeKey: MonkeyTypes.ApeKey): Promise { - const insertionResult = await db - .collection(COLLECTION_NAME) - .insertOne(apeKey); +export async function addApeKey(apeKey: MonkeyTypes.ApeKeyDB): Promise { + const insertionResult = await getApeKeysCollection().insertOne(apeKey); return insertionResult.insertedId.toHexString(); } async function updateApeKey( uid: string, keyId: string, - updates: MatchKeysAndValues + updates: MatchKeysAndValues ): Promise { - const updateResult = await db - .collection(COLLECTION_NAME) - .updateOne(getApeKeyFilter(uid, keyId), { + const updateResult = await getApeKeysCollection().updateOne( + getApeKeyFilter(uid, keyId), + { $inc: { useCount: _.has(updates, "lastUsedOn") ? 1 : 0 }, $set: _.pickBy(updates, (value) => !_.isNil(value)), - }); + } + ); if (updateResult.modifiedCount === 0) { throw new MonkeyError(404, "ApeKey not found"); @@ -86,9 +88,9 @@ export async function updateLastUsedOn( } export async function deleteApeKey(uid: string, keyId: string): Promise { - const deletionResult = await db - .collection(COLLECTION_NAME) - .deleteOne(getApeKeyFilter(uid, keyId)); + const deletionResult = await getApeKeysCollection().deleteOne( + getApeKeyFilter(uid, keyId) + ); if (deletionResult.deletedCount === 0) { throw new MonkeyError(404, "ApeKey not found"); @@ -96,5 +98,5 @@ export async function deleteApeKey(uid: string, keyId: string): Promise { } export async function deleteAllApeKeys(uid: string): Promise { - await db.collection(COLLECTION_NAME).deleteMany({ uid }); + await getApeKeysCollection().deleteMany({ uid }); } diff --git a/backend/src/types/types.d.ts b/backend/src/types/types.d.ts index 82ba98c42..c5429436f 100644 --- a/backend/src/types/types.d.ts +++ b/backend/src/types/types.d.ts @@ -163,17 +163,12 @@ declare namespace MonkeyTypes { colors: string[]; } - interface ApeKey { + type ApeKeyDB = SharedTypes.ApeKey & { _id: ObjectId; uid: string; - name: string; hash: string; - createdOn: number; - modifiedOn: number; - lastUsedOn: number; useCount: number; - enabled: boolean; - } + }; interface NewQuote { _id: ObjectId; diff --git a/frontend/src/ts/ape/endpoints/ape-keys.ts b/frontend/src/ts/ape/endpoints/ape-keys.ts index 767ab2db3..2d32601ab 100644 --- a/frontend/src/ts/ape/endpoints/ape-keys.ts +++ b/frontend/src/ts/ape/endpoints/ape-keys.ts @@ -5,11 +5,14 @@ export default class ApeKeys { this.httpClient = httpClient; } - async get(): Ape.EndpointResponse { + async get(): Ape.EndpointResponse { return await this.httpClient.get(BASE_PATH); } - async generate(name: string, enabled: boolean): Ape.EndpointResponse { + async generate( + name: string, + enabled: boolean + ): Ape.EndpointResponse { const payload = { name, enabled }; return await this.httpClient.post(BASE_PATH, { payload }); } @@ -17,12 +20,12 @@ export default class ApeKeys { async update( apeKeyId: string, updates: { name?: string; enabled?: boolean } - ): Ape.EndpointResponse { + ): Ape.EndpointResponse { const payload = { ...updates }; return await this.httpClient.patch(`${BASE_PATH}/${apeKeyId}`, { payload }); } - async delete(apeKeyId: string): Ape.EndpointResponse { + async delete(apeKeyId: string): Ape.EndpointResponse { return await this.httpClient.delete(`${BASE_PATH}/${apeKeyId}`); } } diff --git a/frontend/src/ts/ape/types/ape-keys.d.ts b/frontend/src/ts/ape/types/ape-keys.d.ts new file mode 100644 index 000000000..1016f9f01 --- /dev/null +++ b/frontend/src/ts/ape/types/ape-keys.d.ts @@ -0,0 +1,9 @@ +declare namespace ApeKeysApe { + type GetApeKeys = Record; + + type GenerateApeKey = { + apeKey: string; + apeKeyId: string; + apeKeyDetails: SharedTypes.ApeKey; + }; +} diff --git a/frontend/src/ts/popups/ape-keys-popup.ts b/frontend/src/ts/popups/ape-keys-popup.ts index a690f7ce3..f80a01dd8 100644 --- a/frontend/src/ts/popups/ape-keys-popup.ts +++ b/frontend/src/ts/popups/ape-keys-popup.ts @@ -6,7 +6,7 @@ import * as ConnectionState from "../states/connection"; import * as Skeleton from "./skeleton"; import { isPopupVisible } from "../utils/misc"; -let apeKeys: MonkeyTypes.ApeKeys = {}; +let apeKeys: ApeKeysApe.GetApeKeys | null = {}; const wrapperId = "apeKeysPopupWrapper"; @@ -20,12 +20,12 @@ async function getData(): Promise { return undefined; } - apeKeys = response.data as MonkeyTypes.ApeKeys; + apeKeys = response.data; } function refreshList(): void { const data = apeKeys; - if (data === undefined) return; + if (data === undefined || data === null) return; const table = $("#apeKeysPopupWrapper table tbody"); table.empty(); const apeKeyIds = Object.keys(data); @@ -36,7 +36,7 @@ function refreshList(): void { return; } apeKeyIds.forEach((apeKeyId) => { - const key = data[apeKeyId] as MonkeyTypes.ApeKey; + const key = data[apeKeyId] as SharedTypes.ApeKey; table.append(` diff --git a/frontend/src/ts/popups/simple-popups.ts b/frontend/src/ts/popups/simple-popups.ts index 3ad6d6b71..bcaa57920 100644 --- a/frontend/src/ts/popups/simple-popups.ts +++ b/frontend/src/ts/popups/simple-popups.ts @@ -1316,7 +1316,8 @@ list["generateApeKey"] = new SimplePopup( }; } - const data = response.data; + //if response is 200 data is guaranteed to not be null + const data = response.data as ApeKeysApe.GenerateApeKey; return { status: 1, diff --git a/frontend/src/ts/types/types.d.ts b/frontend/src/ts/types/types.d.ts index f80330903..10f4a61ff 100644 --- a/frontend/src/ts/types/types.d.ts +++ b/frontend/src/ts/types/types.d.ts @@ -318,18 +318,6 @@ declare namespace MonkeyTypes { completedTests: number; } - interface ApeKey { - name: string; - enabled: boolean; - createdOn: number; - modifiedOn: number; - lastUsedOn: number; - } - - interface ApeKeys { - [key: string]: ApeKey; - } - interface Config { theme: string; themeLight: string; diff --git a/shared-types/types.d.ts b/shared-types/types.d.ts index 39a8adb4f..c62312d38 100644 --- a/shared-types/types.d.ts +++ b/shared-types/types.d.ts @@ -330,10 +330,19 @@ declare namespace SharedTypes { interface SpeedHistogram { [key: string]: number; } + interface PublicTypingStats { type: string; timeTyping: number; testsCompleted: number; testsStarted: number; } + + interface ApeKey { + name: string; + enabled: boolean; + createdOn: number; + modifiedOn: number; + lastUsedOn: number; + } }