mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-11-07 11:30:24 +08:00
refactor(types): ape keys types
move to shared types (#4774) add types to ape client (#4786)
This commit is contained in:
parent
efb972a659
commit
4f5f28a92d
9 changed files with 62 additions and 55 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
|||
9
backend/src/types/types.d.ts
vendored
9
backend/src/types/types.d.ts
vendored
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9
frontend/src/ts/ape/types/ape-keys.d.ts
vendored
Normal file
9
frontend/src/ts/ape/types/ape-keys.d.ts
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
declare namespace ApeKeysApe {
|
||||
type GetApeKeys = Record<string, SharedTypes.ApeKey>;
|
||||
|
||||
type GenerateApeKey = {
|
||||
apeKey: string;
|
||||
apeKeyId: string;
|
||||
apeKeyDetails: SharedTypes.ApeKey;
|
||||
};
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
12
frontend/src/ts/types/types.d.ts
vendored
12
frontend/src/ts/types/types.d.ts
vendored
|
|
@ -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;
|
||||
|
|
|
|||
9
shared-types/types.d.ts
vendored
9
shared-types/types.d.ts
vendored
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue