import { cloneObjectExcept as _cloneObjectExcept, jsonMerge as _jsonMerge, KvObj, QuizConfig, } from "./types.ts"; import { kvStore } from "../modules/KvCacheStore.ts"; /** * Interface to define the structure of a Quiz document. * Using an interface provides strong typing for our data. */ export interface Quiz { id: string; ownerId: string; questions: unknown[]; [key: string]: unknown; } /** * A client for interacting with quiz data using KvCacheStore. * Uses the shared KvCacheStore for connection management and operations. */ export class QuizDataClient { // No longer needs Cosmos DB client - using KvCacheStore instead /** * Creates an instance of the QuizDataClient. * No longer requires connection string since using KvCacheStore. */ constructor() { // KvCacheStore is initialized globally, no connection needed } /** * Retrieves all quizzes from KvCacheStore. * @returns {Promise} A promise that resolves to an array of all quiz documents. */ async getAllQuizzes(): Promise { const quizzes: Quiz[] = []; for await ( const entry of kvStore.list({ prefix: ["quiz_configs"] }) ) { quizzes.push(entry.value); } return quizzes; } /** * Retrieves all quizzes for a specific owner from KvCacheStore. * @param {string} ownerId The ID of the owner. * @returns {Promise} A promise that resolves to an array of quiz documents for the specified owner. */ async getAllQuizzesForOwner(ownerId: string): Promise { const quizzes: Quiz[] = []; for await ( const entry of kvStore.list({ prefix: ["quiz_configs", ownerId] }) ) { quizzes.push(entry.value); } return quizzes; } /** * Retrieves a single, specific quiz by its ID and owner ID from KvCacheStore. * @param {string} ownerId The ID of the owner. * @param {string} quizId The ID of the quiz document. * @returns {Promise} A promise that resolves to the quiz document, or undefined if not found. */ async getQuiz(ownerId: string, quizId: string): Promise { const key = ["quiz_configs", ownerId, quizId]; const result = await kvStore.get(key); return result || undefined; } /** * Creates a new quiz or updates an existing one in KvCacheStore. * @param {Quiz} quiz The quiz document to create or update. * @returns {Promise} A promise that resolves to the state of the quiz document after the upsert operation. */ async upsertQuiz(quiz: Quiz): Promise { const key = ["quiz_configs", quiz.ownerId, quiz.id]; await kvStore.set(key, quiz); return quiz; } /** * Deletes a specific quiz document from KvCacheStore. * @param {string} ownerId The ID of the owner. * @param {string} quizId The ID of the quiz document to delete. * @returns {Promise} A promise that resolves when the delete operation is complete. */ async deleteQuiz(ownerId: string, quizId: string): Promise { const key = ["quiz_configs", ownerId, quizId]; await kvStore.delete(key); } } export async function initKvQuizAny( owner_id: string, quiz_id: string, quiz: QuizConfig, ): Promise> { const key = ["quiz_configs", owner_id, quiz_id]; await kvStore.set(key, quiz); const objQuizConfig: KvObj = { ok: true, key: key, versionstamp: Date.now().toString(), value: quiz, }; return objQuizConfig; } export async function upsertKvQuizAny( kvObjQuizConfig: KvObj, ): Promise> { if ( kvObjQuizConfig.key && kvObjQuizConfig.key[1] && kvObjQuizConfig.key[2] && kvObjQuizConfig.value ) { await kvStore.set(kvObjQuizConfig.key, kvObjQuizConfig.value); const objQuizConfig: KvObj = { ok: true, key: kvObjQuizConfig.key, versionstamp: Date.now().toString(), value: kvObjQuizConfig.value, }; return objQuizConfig; } else { kvObjQuizConfig.versionstamp += " upsertKvQuizAny: Input parameter bad."; } kvObjQuizConfig.ok = false; console.log("failed", kvObjQuizConfig.value?.quiz_name); return kvObjQuizConfig; } export async function setKvQuizAny( kvObjQuizConfig: KvObj, ): Promise> { await kvStore.set(kvObjQuizConfig.key, kvObjQuizConfig.value); const objQuizConfig: KvObj = { ok: true, key: kvObjQuizConfig.key, versionstamp: Date.now().toString(), value: kvObjQuizConfig.value, }; return objQuizConfig; } export async function getKvQuiz( owner_id: string, quiz_id: string, ): Promise> { const key = ["quiz_configs", owner_id, quiz_id]; const value = await kvStore.get(key); const kvObjQuizConfig: KvObj = { ok: true, key: key, versionstamp: Date.now().toString(), value: value, }; return kvObjQuizConfig; } export async function getAllKvQuizConfigs( owner_id?: string, ): Promise[]> { const quizs: KvObj[] = []; const prefix = owner_id ? ["quiz_configs", owner_id] : ["quiz_configs"]; for await (const entry of kvStore.list({ prefix })) { const res: KvObj = { key: [...entry.key] as string[], ok: true, value: entry.value, versionstamp: Date.now().toString(), }; if (!owner_id || res.key[1] === owner_id) { quizs.push(res); } } return quizs; } export async function trasKvQuizAny( kvObjQuizConfig: KvObj, ): Promise> { if ( kvObjQuizConfig.key && kvObjQuizConfig.key[1] && kvObjQuizConfig.key[2] && kvObjQuizConfig.value ) { // For trash functionality, we'll delete the quiz from KvCacheStore await kvStore.delete(kvObjQuizConfig.key); const objQuizConfig: KvObj = { ok: true, key: kvObjQuizConfig.key, versionstamp: Date.now().toString(), value: kvObjQuizConfig.value, }; return objQuizConfig; } else { kvObjQuizConfig.versionstamp += " trasKvQuizAny: Input parameter bad."; } kvObjQuizConfig.ok = false; console.log("failed", kvObjQuizConfig.value?.quiz_name); return kvObjQuizConfig; } export async function deleteQuizAny(quiz_id: string) { // Delete all quizzes with the given quiz_id across all owners const prefix = ["quiz_configs"]; for await (const entry of kvStore.list({ prefix })) { if (entry.key[2] === quiz_id) { await kvStore.delete(entry.key); } } console.log("Delete quiz", quiz_id); } export const quizDataClient = new QuizDataClient();