import * as db from "../init/db"; import { type Filter, type MatchKeysAndValues, type WithId, ObjectId, Collection, } from "mongodb"; import MonkeyError from "../utils/error"; import { ApeKey } from "@monkeytype/schemas/ape-keys"; export type DBApeKey = ApeKey & { _id: ObjectId; uid: string; hash: string; useCount: number; }; export const getApeKeysCollection = (): Collection> => db.collection("ape-keys"); function getApeKeyFilter(uid: string, keyId: string): Filter { return { _id: new ObjectId(keyId), uid, }; } export async function getApeKeys(uid: string): Promise { return await getApeKeysCollection().find({ uid }).toArray(); } export async function getApeKey(keyId: string): Promise { return await getApeKeysCollection().findOne({ _id: new ObjectId(keyId) }); } export async function countApeKeysForUser(uid: string): Promise { return getApeKeysCollection().countDocuments({ uid }); } export async function addApeKey(apeKey: DBApeKey): Promise { const insertionResult = await getApeKeysCollection().insertOne(apeKey); return insertionResult.insertedId.toHexString(); } async function updateApeKey( uid: string, keyId: string, updates: MatchKeysAndValues, ): Promise { const updateResult = await getApeKeysCollection().updateOne( getApeKeyFilter(uid, keyId), { $inc: { useCount: "lastUsedOn" in updates ? 1 : 0 }, $set: Object.fromEntries( Object.entries(updates).filter( ([_, value]) => value !== null && value !== undefined, ), ), }, ); if (updateResult.modifiedCount === 0) { throw new MonkeyError(404, "ApeKey not found"); } } export async function editApeKey( uid: string, keyId: string, name?: string, enabled?: boolean, ): Promise { //check if there is a change if (name === undefined && enabled === undefined) return; const apeKeyUpdates = { name, enabled, modifiedOn: Date.now(), }; await updateApeKey(uid, keyId, apeKeyUpdates); } export async function updateLastUsedOn( uid: string, keyId: string, ): Promise { const apeKeyUpdates = { lastUsedOn: Date.now(), }; await updateApeKey(uid, keyId, apeKeyUpdates); } export async function deleteApeKey(uid: string, keyId: string): Promise { const deletionResult = await getApeKeysCollection().deleteOne( getApeKeyFilter(uid, keyId), ); if (deletionResult.deletedCount === 0) { throw new MonkeyError(404, "ApeKey not found"); } } export async function deleteAllApeKeys(uid: string): Promise { await getApeKeysCollection().deleteMany({ uid }); }