diff options
author | Miodec <[email protected]> | 2024-02-07 23:13:10 +0100 |
---|---|---|
committer | Miodec <[email protected]> | 2024-02-07 23:13:10 +0100 |
commit | 4f5f28a92d67ab074a7d1d5e2dab23bd6f76c460 (patch) | |
tree | fa2e98efceb66d5b2922ea6ea078b587e9eac929 | |
parent | efb972a659ef796adfdec1fd5eec18beb6d38876 (diff) | |
download | monkeytype-4f5f28a92d67ab074a7d1d5e2dab23bd6f76c460.tar.gz monkeytype-4f5f28a92d67ab074a7d1d5e2dab23bd6f76c460.zip |
refactor(types): ape keys types
move to shared types (#4774)
add types to ape client (#4786)
-rw-r--r-- | backend/src/api/controllers/ape-key.ts | 4 | ||||
-rw-r--r-- | backend/src/dal/ape-keys.ts | 52 | ||||
-rw-r--r-- | backend/src/types/types.d.ts | 9 | ||||
-rw-r--r-- | frontend/src/ts/ape/endpoints/ape-keys.ts | 11 | ||||
-rw-r--r-- | frontend/src/ts/ape/types/ape-keys.d.ts | 9 | ||||
-rw-r--r-- | frontend/src/ts/popups/ape-keys-popup.ts | 8 | ||||
-rw-r--r-- | frontend/src/ts/popups/simple-popups.ts | 3 | ||||
-rw-r--r-- | frontend/src/ts/types/types.d.ts | 12 | ||||
-rw-r--r-- | shared-types/types.d.ts | 9 |
9 files changed, 62 insertions, 55 deletions
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<MonkeyTypes.ApeKey> { +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<MonkeyTypes.ApeKeyDB> +> => db.collection<MonkeyTypes.ApeKeyDB>("ape-keys"); function getApeKeyFilter( uid: string, keyId: string -): Filter<MonkeyTypes.ApeKey> { +): Filter<MonkeyTypes.ApeKeyDB> { return { _id: new ObjectId(keyId), uid, }; } -export async function getApeKeys(uid: string): Promise<MonkeyTypes.ApeKey[]> { - return await db - .collection<MonkeyTypes.ApeKey>(COLLECTION_NAME) - .find({ uid }) - .toArray(); +export async function getApeKeys(uid: string): Promise<MonkeyTypes.ApeKeyDB[]> { + return await getApeKeysCollection().find({ uid }).toArray(); } export async function getApeKey( keyId: string -): Promise<MonkeyTypes.ApeKey | null> { - return await db - .collection<MonkeyTypes.ApeKey>(COLLECTION_NAME) - .findOne({ _id: new ObjectId(keyId) }); +): Promise<MonkeyTypes.ApeKeyDB | null> { + return await getApeKeysCollection().findOne({ _id: new ObjectId(keyId) }); } export async function countApeKeysForUser(uid: string): Promise<number> { @@ -35,24 +38,23 @@ export async function countApeKeysForUser(uid: string): Promise<number> { return _.size(apeKeys); } -export async function addApeKey(apeKey: MonkeyTypes.ApeKey): Promise<string> { - const insertionResult = await db - .collection<MonkeyTypes.ApeKey>(COLLECTION_NAME) - .insertOne(apeKey); +export async function addApeKey(apeKey: MonkeyTypes.ApeKeyDB): Promise<string> { + const insertionResult = await getApeKeysCollection().insertOne(apeKey); return insertionResult.insertedId.toHexString(); } async function updateApeKey( uid: string, keyId: string, - updates: MatchKeysAndValues<MonkeyTypes.ApeKey> + updates: MatchKeysAndValues<MonkeyTypes.ApeKeyDB> ): Promise<void> { - const updateResult = await db - .collection<MonkeyTypes.ApeKey>(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<void> { - const deletionResult = await db - .collection<MonkeyTypes.ApeKey>(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<void> { } export async function deleteAllApeKeys(uid: string): Promise<void> { - await db.collection<MonkeyTypes.ApeKey>(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<ApeKeysApe.GetApeKeys> { return await this.httpClient.get(BASE_PATH); } - async generate(name: string, enabled: boolean): Ape.EndpointResponse { + async generate( + name: string, + enabled: boolean + ): Ape.EndpointResponse<ApeKeysApe.GenerateApeKey> { 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<null> { const payload = { ...updates }; return await this.httpClient.patch(`${BASE_PATH}/${apeKeyId}`, { payload }); } - async delete(apeKeyId: string): Ape.EndpointResponse { + async delete(apeKeyId: string): Ape.EndpointResponse<null> { 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<string, SharedTypes.ApeKey>; + + 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<void> { 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(` <tr keyId="${apeKeyId}"> <td> 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; + } } |