@orjok/commons 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -0
- package/dist/amplify.cjs +129 -0
- package/dist/amplify.cjs.map +1 -0
- package/dist/amplify.d.cts +40 -0
- package/dist/amplify.d.ts +40 -0
- package/dist/amplify.js +129 -0
- package/dist/amplify.js.map +1 -0
- package/dist/client-BaOC79Nc.d.cts +775 -0
- package/dist/client-Bm9aiyTx.d.ts +775 -0
- package/dist/hooks.cjs +16 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.cts +8 -0
- package/dist/hooks.d.ts +8 -0
- package/dist/hooks.js +16 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.cjs +1723 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +1723 -0
- package/dist/index.js.map +1 -0
- package/dist/storage-DLqdJgQt.d.cts +72 -0
- package/dist/storage-DLqdJgQt.d.ts +72 -0
- package/dist/testing.cjs +97 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +52 -0
- package/dist/testing.d.ts +52 -0
- package/dist/testing.js +97 -0
- package/dist/testing.js.map +1 -0
- package/package.json +104 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/user.service.ts","../src/services/question.service.ts","../src/services/pack.service.ts","../src/services/contest.service.ts","../src/services/course.service.ts","../src/services/curriculum.service.ts","../src/services/media.service.ts","../src/services/progress.service.ts","../src/services/ai.service.ts","../src/services/news.service.ts","../src/client.ts","../src/logic/elo.ts","../src/logic/exam.ts","../src/logic/import-export.ts","../src/logic/media-url.ts","../src/logic/practice.ts","../src/utils/shuffle.ts","../src/utils/bangla-numbers.ts","../src/utils/format-curriculum.ts","../src/utils/relative-time.ts","../src/utils/latex.ts"],"sourcesContent":["import type { NetworkProvider } from \"../providers/network\";\nimport type { UpdateUserAvatarInput } from \"../types/inputs\";\nimport type {\n User,\n PaginatedList,\n QuestionObject,\n Pack,\n Course,\n CourseEnrolled,\n} from \"../types/models\";\n\nexport class UserService {\n constructor(private network: NetworkProvider) {}\n\n async get(id: string): Promise<User | null> {\n const result = await this.network.query<{ getUser: User | null }>(\n `query GetUser($id: String!) {\n getUser(id: $id) {\n id fullName avatarUrl avatarConfig tier subscriptionExpiresAt\n aiEvaluationRemaining questionCount packCount contestCount\n EngineeringRating MedicalRating VarsityRating BCSRating\n sscOverallRating sscPhysicsRating sscChemistryRating sscMathRating sscBiologyRating\n hscOverallRating hscPhysicsRating hscChemistryRating hscMathRating hscBiologyRating\n bcsOverallRating\n }\n }`,\n { id }\n );\n return result.data.getUser;\n }\n\n async updateAvatar(input: UpdateUserAvatarInput): Promise<User | null> {\n const result = await this.network.mutate<{ updateUser: User | null }>(\n `mutation UpdateUser($input: UpdateUserInput!) {\n updateUser(input: $input) {\n id fullName avatarUrl avatarConfig\n }\n }`,\n { input: { id: input.userId, avatarUrl: input.avatarUrl, avatarConfig: input.avatarConfig } }\n );\n return result.data.updateUser;\n }\n\n async getQuestions(\n userId: string,\n nextToken?: string\n ): Promise<PaginatedList<QuestionObject>> {\n const result = await this.network.query<{\n listQuestionObjectByOwnerAndCreatedAt: PaginatedList<QuestionObject>;\n }>(\n `query ListUserQuestions($owner: ID!, $nextToken: String, $sortDirection: ModelSortDirection) {\n listQuestionObjectByOwnerAndCreatedAt(owner: $owner, sortDirection: $sortDirection, nextToken: $nextToken) {\n items {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId createdAt\n options { items { id content } }\n tags { items { id tagId } }\n }\n nextToken\n }\n }`,\n { owner: userId, nextToken, sortDirection: \"DESC\" }\n );\n return result.data.listQuestionObjectByOwnerAndCreatedAt;\n }\n\n async getPacks(\n userId: string,\n nextToken?: string\n ): Promise<PaginatedList<Pack>> {\n const result = await this.network.query<{\n listPackByOwnerAndCreatedAt: PaginatedList<Pack>;\n }>(\n `query ListUserPacks($owner: ID!, $nextToken: String, $sortDirection: ModelSortDirection) {\n listPackByOwnerAndCreatedAt(owner: $owner, sortDirection: $sortDirection, nextToken: $nextToken) {\n items {\n id name language level difficulty questionCount automaticNumbering\n owner subjectId chapterId topicId verificationStatus createdAt\n tags { items { id tagId } }\n }\n nextToken\n }\n }`,\n { owner: userId, nextToken, sortDirection: \"DESC\" }\n );\n return result.data.listPackByOwnerAndCreatedAt;\n }\n\n async getCourses(userId: string): Promise<Course[]> {\n const result = await this.network.query<{\n listCourseByOwnerAndCreatedAt: PaginatedList<Course>;\n }>(\n `query ListUserCourses($owner: ID!, $sortDirection: ModelSortDirection) {\n listCourseByOwnerAndCreatedAt(owner: $owner, sortDirection: $sortDirection) {\n items {\n id name description imageUrl videoCount fileCount price totalEnrolled owner createdAt\n }\n }\n }`,\n { owner: userId, sortDirection: \"DESC\" }\n );\n return result.data.listCourseByOwnerAndCreatedAt.items;\n }\n\n async getEnrolledCourses(userId: string): Promise<CourseEnrolled[]> {\n const result = await this.network.query<{\n listCourseEnrolledByUserIdAndCreatedAt: PaginatedList<CourseEnrolled>;\n }>(\n `query ListEnrolledCourses($userId: ID!, $sortDirection: ModelSortDirection) {\n listCourseEnrolledByUserIdAndCreatedAt(userId: $userId, sortDirection: $sortDirection) {\n items {\n id courseId userId score rank createdAt\n course { id name description imageUrl price totalEnrolled }\n }\n }\n }`,\n { userId, sortDirection: \"DESC\" }\n );\n return result.data.listCourseEnrolledByUserIdAndCreatedAt.items;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type {\n CreateQuestionInput,\n VoteInput,\n AddQuestionTagInput,\n ListByCurriculumInput,\n ListByRandomHashInput,\n} from \"../types/inputs\";\nimport type {\n CreateQuestionResponse,\n StatusIdResponse,\n StatusResponse,\n} from \"../types/responses\";\nimport type {\n QuestionObject,\n PaginatedList,\n Option,\n Verification,\n} from \"../types/models\";\n\nexport class QuestionService {\n constructor(private network: NetworkProvider) {}\n\n async create(input: CreateQuestionInput): Promise<CreateQuestionResponse> {\n const result = await this.network.mutate<{ createQuestion: CreateQuestionResponse }>(\n `mutation CreateQuestion($question: String!, $answer: String!, $options: String!, $language: String!, $level: String!, $difficulty: String!, $type: String, $explanation: String, $tags: String, $imagePayload: String, $optionsImagesPayload: String, $packId: ID, $order: Int, $contestId: ID, $subjectId: ID, $chapterId: ID, $topicId: ID, $extra: String, $markingInstructions: String) {\n createQuestion(question: $question, answer: $answer, options: $options, language: $language, level: $level, difficulty: $difficulty, type: $type, explanation: $explanation, tags: $tags, imagePayload: $imagePayload, optionsImagesPayload: $optionsImagesPayload, packId: $packId, order: $order, contestId: $contestId, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId, extra: $extra, markingInstructions: $markingInstructions) {\n status questionId\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.createQuestion;\n }\n\n async get(id: string): Promise<QuestionObject | null> {\n const result = await this.network.query<{ getQuestionObject: QuestionObject | null }>(\n `query GetQuestion($id: String!) {\n getQuestionObject(id: $id) {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId subjectId chapterId topicId order createdAt\n options { items { id content } }\n tags { items { id tagId } }\n }\n }`,\n { id }\n );\n return result.data.getQuestionObject;\n }\n\n async getFull(id: string): Promise<QuestionObject | null> {\n const result = await this.network.query<{ getQuestionObject: QuestionObject | null }>(\n `query GetFullQuestion($id: String!) {\n getQuestionObject(id: $id) {\n id question answer explanation extra imageUrl language level difficulty type\n markingInstructions voteCount verificationStatus owner packId\n subjectId chapterId topicId order createdAt\n options { items { id content } }\n tags { items { id tagId } }\n user { id fullName avatarUrl }\n }\n }`,\n { id }\n );\n return result.data.getQuestionObject;\n }\n\n async getAnswer(id: string): Promise<Option | null> {\n const result = await this.network.query<{ getQuestionObject: { answer: string } | null }>(\n `query GetAnswer($id: String!) {\n getQuestionObject(id: $id) { answer }\n }`,\n { id }\n );\n if (!result.data.getQuestionObject) return null;\n return { id, content: result.data.getQuestionObject.answer } as Option;\n }\n\n async getQuestionId(packId: string, order: number): Promise<string | null> {\n const result = await this.network.query<{\n listQuestionObjectByPackIdAndOrder: PaginatedList<{ id: string }>;\n }>(\n `query GetQuestionId($packId: ID!, $order: ModelIntKeyConditionInput) {\n listQuestionObjectByPackIdAndOrder(packId: $packId, order: $order, limit: 1) {\n items { id }\n }\n }`,\n { packId, order: { eq: order } }\n );\n return result.data.listQuestionObjectByPackIdAndOrder.items[0]?.id ?? null;\n }\n\n async update(\n id: string,\n fields: Record<string, unknown>\n ): Promise<QuestionObject | null> {\n const result = await this.network.mutate<{ updateQuestionObject: QuestionObject | null }>(\n `mutation UpdateQuestion($input: UpdateQuestionObjectInput!) {\n updateQuestionObject(input: $input) {\n id question answer explanation extra imageUrl language level difficulty type\n markingInstructions voteCount owner packId subjectId chapterId topicId order createdAt\n options { items { id content } }\n }\n }`,\n { input: { id, ...fields } }\n );\n return result.data.updateQuestionObject;\n }\n\n async delete(id: string): Promise<QuestionObject | null> {\n const result = await this.network.mutate<{ deleteQuestionObject: QuestionObject | null }>(\n `mutation DeleteQuestion($input: DeleteQuestionObjectInput!) {\n deleteQuestionObject(input: $input) { id }\n }`,\n { input: { id } }\n );\n return result.data.deleteQuestionObject;\n }\n\n async vote(input: VoteInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ vote: StatusIdResponse }>(\n `mutation Vote($questionId: ID!, $type: String!, $modelType: String!) {\n vote(questionId: $questionId, type: $type, modelType: $modelType) {\n status id\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.vote;\n }\n\n async upVote(questionId: string): Promise<StatusIdResponse> {\n return this.vote({ questionId, type: \"upvote\", modelType: \"question\" });\n }\n\n async downVote(questionId: string): Promise<StatusIdResponse> {\n return this.vote({ questionId, type: \"downvote\", modelType: \"question\" });\n }\n\n async verify(id: string, userId: string): Promise<Verification | null> {\n const result = await this.network.mutate<{ createVerification: Verification | null }>(\n `mutation VerifyQuestion($input: CreateVerificationInput!) {\n createVerification(input: $input) { id verifiedObjectId type userId }\n }`,\n { input: { verifiedObjectId: id, type: \"question\", userId } }\n );\n return result.data.createVerification;\n }\n\n async report(id: string, reason: string): Promise<{ id: string }> {\n const result = await this.network.mutate<{ createQuestionReport: { id: string } }>(\n `mutation ReportQuestion($input: CreateQuestionReportInput!) {\n createQuestionReport(input: $input) { id }\n }`,\n { input: { questionId: id, reason } }\n );\n return result.data.createQuestionReport;\n }\n\n async addTags(input: AddQuestionTagInput): Promise<StatusResponse> {\n const result = await this.network.mutate<{ addQuestionTag: StatusResponse }>(\n `mutation AddQuestionTag($tags: String!, $packId: ID, $questionId: ID) {\n addQuestionTag(tags: $tags, packId: $packId, questionId: $questionId) {\n status\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.addQuestionTag;\n }\n\n async listBySubject(input: ListByCurriculumInput): Promise<PaginatedList<QuestionObject>> {\n const variables: Record<string, unknown> = {\n subjectId: input.id,\n sortDirection: input.sortDirection ?? \"DESC\",\n limit: input.limit ?? 20,\n nextToken: input.nextToken,\n };\n const result = await this.network.query<{\n listQuestionObjectBySubjectIdAndCreatedAt: PaginatedList<QuestionObject>;\n }>(\n `query ListQuestionsBySubject($subjectId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listQuestionObjectBySubjectIdAndCreatedAt(subjectId: $subjectId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId createdAt\n options { items { id content } }\n }\n nextToken\n }\n }`,\n variables\n );\n return result.data.listQuestionObjectBySubjectIdAndCreatedAt;\n }\n\n async listByChapter(input: ListByCurriculumInput): Promise<PaginatedList<QuestionObject>> {\n const variables: Record<string, unknown> = {\n chapterId: input.id,\n sortDirection: input.sortDirection ?? \"DESC\",\n limit: input.limit ?? 20,\n nextToken: input.nextToken,\n };\n const result = await this.network.query<{\n listQuestionObjectByChapterIdAndCreatedAt: PaginatedList<QuestionObject>;\n }>(\n `query ListQuestionsByChapter($chapterId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listQuestionObjectByChapterIdAndCreatedAt(chapterId: $chapterId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId createdAt\n options { items { id content } }\n }\n nextToken\n }\n }`,\n variables\n );\n return result.data.listQuestionObjectByChapterIdAndCreatedAt;\n }\n\n async listByTopic(input: ListByCurriculumInput): Promise<PaginatedList<QuestionObject>> {\n const variables: Record<string, unknown> = {\n topicId: input.id,\n sortDirection: input.sortDirection ?? \"DESC\",\n limit: input.limit ?? 20,\n nextToken: input.nextToken,\n };\n const result = await this.network.query<{\n listQuestionObjectByTopicIdAndCreatedAt: PaginatedList<QuestionObject>;\n }>(\n `query ListQuestionsByTopic($topicId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listQuestionObjectByTopicIdAndCreatedAt(topicId: $topicId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId createdAt\n options { items { id content } }\n }\n nextToken\n }\n }`,\n variables\n );\n return result.data.listQuestionObjectByTopicIdAndCreatedAt;\n }\n\n async listByRandomHash(input: ListByRandomHashInput): Promise<PaginatedList<QuestionObject>> {\n const compositeKey = [input.language, input.difficulty].filter(Boolean).join(\"_\");\n const variables: Record<string, unknown> = {\n subjectId: input.id,\n sortDirection: input.sortDirection ?? \"ASC\",\n limit: input.limit ?? 1,\n language_difficulty_randomHash: input.randomHashFilter\n ? { beginsWith: compositeKey, ...input.randomHashFilter }\n : { beginsWith: compositeKey },\n };\n const result = await this.network.query<{\n listQuestionObjectBySubjectIdAndLanguage_difficulty_randomHash: PaginatedList<QuestionObject>;\n }>(\n `query ListByRandomHash($subjectId: String!, $language_difficulty_randomHash: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int) {\n listQuestionObjectBySubjectIdAndLanguage_difficulty_randomHash(subjectId: $subjectId, language_difficulty_randomHash: $language_difficulty_randomHash, sortDirection: $sortDirection, limit: $limit) {\n items {\n id question imageUrl language level difficulty type voteCount\n verificationStatus owner packId subjectId chapterId topicId createdAt\n options { items { id content } }\n }\n nextToken\n }\n }`,\n variables\n );\n return result.data.listQuestionObjectBySubjectIdAndLanguage_difficulty_randomHash;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { CreatePackInput, ListByCurriculumInput } from \"../types/inputs\";\nimport type { StatusIdResponse } from \"../types/responses\";\nimport type {\n Pack,\n PaginatedList,\n PackExamResults,\n PackGroup,\n Verification,\n} from \"../types/models\";\n\nexport class PackService {\n constructor(private network: NetworkProvider) {}\n\n async create(input: CreatePackInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ createPackObject: StatusIdResponse }>(\n `mutation CreatePack($name: String!, $level: String!, $language: String!, $difficulty: String!, $automaticNumbering: Boolean, $subjectId: ID, $chapterId: ID, $topicId: ID) {\n createPackObject(name: $name, level: $level, language: $language, difficulty: $difficulty, automaticNumbering: $automaticNumbering, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId) {\n status id\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.createPackObject;\n }\n\n async get(id: string): Promise<Pack | null> {\n const result = await this.network.query<{ getPack: Pack | null }>(\n `query GetPack($id: ID!) {\n getPack(id: $id) {\n id name language level difficulty questionCount automaticNumbering\n owner subjectId chapterId topicId packGroupId verificationStatus createdAt\n tags { items { id tagId } }\n user { id fullName avatarUrl }\n }\n }`,\n { id }\n );\n return result.data.getPack;\n }\n\n async getFull(id: string): Promise<Pack | null> {\n const result = await this.network.query<{ getPack: Pack | null }>(\n `query GetFullPack($id: ID!) {\n getPack(id: $id) {\n id name language level difficulty questionCount automaticNumbering\n owner subjectId chapterId topicId packGroupId verificationStatus createdAt\n tags { items { id tagId } }\n user { id fullName avatarUrl }\n questions(sortDirection: ASC, limit: 200) {\n items {\n id question answer explanation extra imageUrl language level difficulty type\n markingInstructions voteCount owner order createdAt\n options { items { id content } }\n tags { items { id tagId } }\n }\n }\n }\n }`,\n { id }\n );\n return result.data.getPack;\n }\n\n async update(id: string, fields: Record<string, unknown>): Promise<Pack | null> {\n const result = await this.network.mutate<{ updatePack: Pack | null }>(\n `mutation UpdatePack($input: UpdatePackInput!) {\n updatePack(input: $input) {\n id name language level difficulty questionCount automaticNumbering\n owner subjectId chapterId topicId verificationStatus createdAt\n }\n }`,\n { input: { id, ...fields } }\n );\n return result.data.updatePack;\n }\n\n async delete(id: string): Promise<Pack | null> {\n const result = await this.network.mutate<{ deletePack: Pack | null }>(\n `mutation DeletePack($input: DeletePackInput!) {\n deletePack(input: $input) { id }\n }`,\n { input: { id } }\n );\n return result.data.deletePack;\n }\n\n async verify(id: string, userId: string): Promise<Verification | null> {\n const result = await this.network.mutate<{ createVerification: Verification | null }>(\n `mutation VerifyPack($input: CreateVerificationInput!) {\n createVerification(input: $input) { id verifiedObjectId type userId }\n }`,\n { input: { verifiedObjectId: id, type: \"pack\", userId } }\n );\n return result.data.createVerification;\n }\n\n async report(id: string, reason: string): Promise<{ id: string }> {\n const result = await this.network.mutate<{ createPackReport: { id: string } }>(\n `mutation ReportPack($input: CreatePackReportInput!) {\n createPackReport(input: $input) { id }\n }`,\n { input: { packId: id, reason } }\n );\n return result.data.createPackReport;\n }\n\n async submitExam(packId: string, selectedOptions: (string | null)[]): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ submitPackExam: StatusIdResponse }>(\n `mutation SubmitPackExam($packId: ID!, $selectedOptions: String!) {\n submitPackExam(packId: $packId, selectedOptions: $selectedOptions) {\n status id\n }\n }`,\n { packId, selectedOptions: JSON.stringify(selectedOptions) }\n );\n return result.data.submitPackExam;\n }\n\n async getExams(userId: string, nextToken?: string): Promise<PaginatedList<PackExamResults>> {\n const result = await this.network.query<{\n listPackExamResultsByOwnerAndCreatedAt: PaginatedList<PackExamResults>;\n }>(\n `query ListPackExams($owner: ID!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listPackExamResultsByOwnerAndCreatedAt(owner: $owner, sortDirection: $sortDirection, nextToken: $nextToken) {\n items {\n id packId selectedOptions aiEvaluations owner createdAt\n pack { id name language level difficulty questionCount }\n }\n nextToken\n }\n }`,\n { owner: userId, sortDirection: \"DESC\", nextToken }\n );\n return result.data.listPackExamResultsByOwnerAndCreatedAt;\n }\n\n async getExamResult(resultId: string): Promise<PackExamResults | null> {\n const result = await this.network.query<{ getPackExamResults: PackExamResults | null }>(\n `query GetPackExamResult($id: ID!) {\n getPackExamResults(id: $id) {\n id packId selectedOptions aiEvaluations owner createdAt\n pack { id name language level difficulty questionCount }\n }\n }`,\n { id: resultId }\n );\n return result.data.getPackExamResults;\n }\n\n async listBySubject(input: ListByCurriculumInput): Promise<PaginatedList<Pack>> {\n const result = await this.network.query<{\n listPackBySubjectIdAndCreatedAt: PaginatedList<Pack>;\n }>(\n `query ListPacksBySubject($subjectId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listPackBySubjectIdAndCreatedAt(subjectId: $subjectId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id name language level difficulty questionCount owner createdAt verificationStatus\n tags { items { id tagId } }\n }\n nextToken\n }\n }`,\n { subjectId: input.id, sortDirection: \"DESC\", limit: input.limit ?? 20, nextToken: input.nextToken }\n );\n return result.data.listPackBySubjectIdAndCreatedAt;\n }\n\n async listByChapter(input: ListByCurriculumInput): Promise<PaginatedList<Pack>> {\n const result = await this.network.query<{\n listPackByChapterIdAndCreatedAt: PaginatedList<Pack>;\n }>(\n `query ListPacksByChapter($chapterId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listPackByChapterIdAndCreatedAt(chapterId: $chapterId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id name language level difficulty questionCount owner createdAt verificationStatus\n tags { items { id tagId } }\n }\n nextToken\n }\n }`,\n { chapterId: input.id, sortDirection: \"DESC\", limit: input.limit ?? 20, nextToken: input.nextToken }\n );\n return result.data.listPackByChapterIdAndCreatedAt;\n }\n\n async listByTopic(input: ListByCurriculumInput): Promise<PaginatedList<Pack>> {\n const result = await this.network.query<{\n listPackByTopicIdAndCreatedAt: PaginatedList<Pack>;\n }>(\n `query ListPacksByTopic($topicId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {\n listPackByTopicIdAndCreatedAt(topicId: $topicId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {\n items {\n id name language level difficulty questionCount owner createdAt verificationStatus\n tags { items { id tagId } }\n }\n nextToken\n }\n }`,\n { topicId: input.id, sortDirection: \"DESC\", limit: input.limit ?? 20, nextToken: input.nextToken }\n );\n return result.data.listPackByTopicIdAndCreatedAt;\n }\n\n async listGroups(type: string, level?: string): Promise<PackGroup[]> {\n const queryField = level ? \"listPackGroupByTypeLevelAndOrder\" : \"listPackGroupByTypeAndOrder\";\n const variables: Record<string, unknown> = level\n ? { typeLevel: `${type}_${level}`, sortDirection: \"ASC\" }\n : { type, sortDirection: \"ASC\" };\n\n const result = await this.network.query<Record<string, PaginatedList<PackGroup>>>(\n level\n ? `query ListPackGroups($typeLevel: String!, $sortDirection: ModelSortDirection) {\n listPackGroupByTypeLevelAndOrder(typeLevel: $typeLevel, sortDirection: $sortDirection) {\n items { id name description imageUrl type level typeLevel packCount order }\n }\n }`\n : `query ListPackGroups($type: String!, $sortDirection: ModelSortDirection) {\n listPackGroupByTypeAndOrder(type: $type, sortDirection: $sortDirection) {\n items { id name description imageUrl type level typeLevel packCount order }\n }\n }`,\n variables\n );\n return (result.data[queryField] as PaginatedList<PackGroup>).items;\n }\n\n async getGroup(id: string): Promise<PackGroup | null> {\n const result = await this.network.query<{ getPackGroup: PackGroup | null }>(\n `query GetPackGroup($id: ID!) {\n getPackGroup(id: $id) {\n id name description imageUrl type level typeLevel packCount order\n packs { items { id name language level difficulty questionCount owner createdAt verificationStatus } }\n }\n }`,\n { id }\n );\n return result.data.getPackGroup;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { CreateContestInput } from \"../types/inputs\";\nimport type {\n StatusIdResponse,\n StatusResponse,\n CheckParticipationResponse,\n ContestQuestionsResponse,\n ContestAnswersResponse,\n LeaderboardResponse,\n} from \"../types/responses\";\nimport type { Contest, PaginatedList, ContestParticipant } from \"../types/models\";\n\nexport class ContestService {\n constructor(private network: NetworkProvider) {}\n\n async create(input: CreateContestInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ makeContest: StatusIdResponse }>(\n `mutation MakeContest($name: String!, $description: String!, $level: String!, $language: String!, $startTime: AWSDateTime!, $endTime: AWSDateTime!, $subject: String!, $isRated: Boolean!, $questions: String!, $maximumParticipants: Int!, $solutionVideoUrl: String, $imageUrl: String) {\n makeContest(name: $name, description: $description, level: $level, language: $language, startTime: $startTime, endTime: $endTime, subject: $subject, isRated: $isRated, questions: $questions, maximumParticipants: $maximumParticipants, solutionVideoUrl: $solutionVideoUrl, imageUrl: $imageUrl) {\n status id\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.makeContest;\n }\n\n async get(id: string): Promise<Contest | null> {\n const result = await this.network.query<{ getContest: Contest | null }>(\n `query GetContest($id: ID!) {\n getContest(id: $id) {\n id name description startTime endTime level language owner isRated subject\n totalQuestions resultsPublished totalParticipants maximumParticipants\n rankings globalPk solutionVideoUrl imageUrl\n }\n }`,\n { id }\n );\n return result.data.getContest;\n }\n\n async getName(id: string): Promise<string | null> {\n const result = await this.network.query<{ getContest: { name: string } | null }>(\n `query GetContestName($id: ID!) { getContest(id: $id) { name } }`,\n { id }\n );\n return result.data.getContest?.name ?? null;\n }\n\n async list(nextToken?: string, level?: string): Promise<PaginatedList<Contest>> {\n const variables: Record<string, unknown> = level\n ? { level, sortDirection: \"DESC\", nextToken }\n : { globalPk: \"ALL\", sortDirection: \"DESC\", nextToken };\n\n const result = await this.network.query<Record<string, PaginatedList<Contest>>>(\n level\n ? `query ListContests($level: String!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listContestByLevelAndStartTime(level: $level, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id name description startTime endTime level language owner isRated subject totalQuestions resultsPublished totalParticipants maximumParticipants solutionVideoUrl imageUrl }\n nextToken\n }\n }`\n : `query ListContests($globalPk: String!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listContestByGlobalPkAndStartTime(globalPk: $globalPk, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id name description startTime endTime level language owner isRated subject totalQuestions resultsPublished totalParticipants maximumParticipants solutionVideoUrl imageUrl }\n nextToken\n }\n }`,\n variables\n );\n const key = level ? \"listContestByLevelAndStartTime\" : \"listContestByGlobalPkAndStartTime\";\n return result.data[key] as PaginatedList<Contest>;\n }\n\n async participate(contestId: string): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ participateContest: StatusIdResponse }>(\n `mutation ParticipateContest($contestId: ID!) {\n participateContest(contestId: $contestId) { status id }\n }`,\n { contestId }\n );\n return result.data.participateContest;\n }\n\n async checkParticipation(contestId: string): Promise<CheckParticipationResponse> {\n const result = await this.network.query<{ checkUserParticipation: CheckParticipationResponse }>(\n `query CheckParticipation($contestId: ID!) {\n checkUserParticipation(contestId: $contestId) {\n status participated selectedOptions score rank beforeRating afterRating\n }\n }`,\n { contestId }\n );\n return result.data.checkUserParticipation;\n }\n\n async selectOption(contestId: string, optionId: string, order: number): Promise<StatusResponse> {\n const result = await this.network.mutate<{ selectContestOption: StatusResponse }>(\n `mutation SelectContestOption($contestId: ID!, $optionId: String!, $order: Int!) {\n selectContestOption(contestId: $contestId, optionId: $optionId, order: $order) { status }\n }`,\n { contestId, optionId, order }\n );\n return result.data.selectContestOption;\n }\n\n async getQuestions(contestId: string): Promise<ContestQuestionsResponse> {\n const result = await this.network.query<{ getContestQuestions: ContestQuestionsResponse }>(\n `query GetContestQuestions($contestId: ID!) {\n getContestQuestions(contestId: $contestId) { status questions }\n }`,\n { contestId }\n );\n return result.data.getContestQuestions;\n }\n\n async getAnswers(contestId: string): Promise<ContestAnswersResponse> {\n const result = await this.network.query<{ getContestAnswers: ContestAnswersResponse }>(\n `query GetContestAnswers($contestId: ID!) {\n getContestAnswers(contestId: $contestId) { status answers }\n }`,\n { contestId }\n );\n return result.data.getContestAnswers;\n }\n\n async publish(contestId: string): Promise<StatusResponse> {\n const result = await this.network.mutate<{ publishContestResults: StatusResponse }>(\n `mutation PublishResults($contestId: ID!) {\n publishContestResults(contestId: $contestId) { status }\n }`,\n { contestId }\n );\n return result.data.publishContestResults;\n }\n\n async getLeaderboard(contestId: string, nextToken?: string | null): Promise<LeaderboardResponse> {\n const result = await this.network.query<{\n listContestParticipantByContestIdAndRank: PaginatedList<ContestParticipant>;\n }>(\n `query GetLeaderboard($contestId: ID!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listContestParticipantByContestIdAndRank(contestId: $contestId, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id contestId userId rank score afterRating beforeRating createdAt user { id fullName avatarUrl } }\n nextToken\n }\n }`,\n { contestId, sortDirection: \"ASC\", nextToken }\n );\n const data = result.data.listContestParticipantByContestIdAndRank;\n return {\n status: \"success\",\n leaderboard: JSON.stringify(data.items),\n nextToken: data.nextToken,\n };\n }\n\n async getUserResults(userId: string, nextToken?: string | null): Promise<PaginatedList<ContestParticipant>> {\n const result = await this.network.query<{\n listContestParticipantByUserIdAndCreatedAt: PaginatedList<ContestParticipant>;\n }>(\n `query GetUserResults($userId: ID!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listContestParticipantByUserIdAndCreatedAt(userId: $userId, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id contestId userId rank score afterRating beforeRating selectedOptions createdAt contest { id name subject level startTime } }\n nextToken\n }\n }`,\n { userId, sortDirection: \"DESC\", nextToken }\n );\n return result.data.listContestParticipantByUserIdAndCreatedAt;\n }\n\n async updateSolutionVideo(contestId: string, url: string | null): Promise<StatusResponse> {\n const result = await this.network.mutate<{ updateContest: Contest | null }>(\n `mutation UpdateSolutionVideo($input: UpdateContestInput!) {\n updateContest(input: $input) { id solutionVideoUrl }\n }`,\n { input: { id: contestId, solutionVideoUrl: url } }\n );\n return { status: result.data.updateContest ? \"success\" : \"error\" };\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type {\n CreateCourseInput,\n CreateCourseItemInput,\n CreateCourseLiveExamInput,\n DeleteCourseItemInput,\n EnrollStudentInput,\n SendEnrollmentRequestInput,\n GetSignedURLInput,\n GetSignedFileURLInput,\n CreateCourseVideoInput,\n UploadVideoToBunnyInput,\n} from \"../types/inputs\";\nimport type {\n CreateCourseResponse,\n StatusIdResponse,\n StatusResponse,\n SignedURLResponse,\n CreateCourseVideoResponse,\n CourseLiveExamQuestionsResponse,\n LeaderboardResponse,\n} from \"../types/responses\";\nimport type {\n Course,\n CourseItem,\n CourseEnrolled,\n CourseLiveExam,\n PaginatedList,\n} from \"../types/models\";\n\nexport class CourseService {\n constructor(private network: NetworkProvider) {}\n\n async create(input: CreateCourseInput): Promise<CreateCourseResponse> {\n const result = await this.network.mutate<{ makeCourse: CreateCourseResponse }>(\n `mutation MakeCourse($name: String!, $description: String!, $price: Int!, $imageUrl: String) {\n makeCourse(name: $name, description: $description, price: $price, imageUrl: $imageUrl) { status courseId }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.makeCourse;\n }\n\n async get(id: string): Promise<Course | null> {\n const result = await this.network.query<{ getCourse: Course | null }>(\n `query GetCourse($id: ID!) {\n getCourse(id: $id) { id name description imageUrl videoCount fileCount price totalEnrolled owner createdAt }\n }`,\n { id }\n );\n return result.data.getCourse;\n }\n\n async getItems(courseId: string): Promise<CourseItem[]> {\n const result = await this.network.query<{\n listCourseItemsByCourseIdAndOrder: PaginatedList<CourseItem>;\n }>(\n `query ListCourseItems($courseId: ID!, $sortDirection: ModelSortDirection) {\n listCourseItemsByCourseIdAndOrder(courseId: $courseId, sortDirection: $sortDirection) {\n items { id type name courseId parentId order owner }\n }\n }`,\n { courseId, sortDirection: \"ASC\" }\n );\n return result.data.listCourseItemsByCourseIdAndOrder.items;\n }\n\n async createItem(input: CreateCourseItemInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ createCourseItem: StatusIdResponse }>(\n `mutation CreateCourseItem($courseId: ID!, $name: String!, $order: Int!, $type: CourseItemsType, $parentId: ID, $id: ID) {\n createCourseItem(courseId: $courseId, name: $name, order: $order, type: $type, parentId: $parentId, id: $id) { status id }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.createCourseItem;\n }\n\n async updateItem(id: string, name: string, order: number): Promise<CourseItem | null> {\n const result = await this.network.mutate<{ updateCourseItems: CourseItem | null }>(\n `mutation UpdateCourseItem($input: UpdateCourseItemsInput!) {\n updateCourseItems(input: $input) { id type name courseId parentId order owner }\n }`,\n { input: { id, name, order } }\n );\n return result.data.updateCourseItems;\n }\n\n async deleteItem(input: DeleteCourseItemInput): Promise<StatusResponse> {\n const result = await this.network.mutate<{ deleteCourseItem: StatusResponse }>(\n `mutation DeleteCourseItem($id: ID!, $fileType: String!, $courseId: ID!, $parentId: ID) {\n deleteCourseItem(id: $id, fileType: $fileType, courseId: $courseId, parentId: $parentId) { status }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.deleteCourseItem;\n }\n\n async enroll(input: EnrollStudentInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ enrollStudent: StatusIdResponse }>(\n `mutation EnrollStudent($courseId: ID!, $userId: ID!) {\n enrollStudent(courseId: $courseId, userId: $userId) { status id }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.enrollStudent;\n }\n\n async getEnrolledStudent(courseId: string, userId: string): Promise<CourseEnrolled | null> {\n const result = await this.network.query<{\n listCourseEnrolledByCourseIdAndCreatedAt: PaginatedList<CourseEnrolled>;\n }>(\n `query GetEnrolledStudent($courseId: ID!, $filter: ModelCourseEnrolledFilterInput) {\n listCourseEnrolledByCourseIdAndCreatedAt(courseId: $courseId, filter: $filter) {\n items { id courseId userId owner score rank createdAt }\n }\n }`,\n { courseId, filter: { userId: { eq: userId } } }\n );\n return result.data.listCourseEnrolledByCourseIdAndCreatedAt.items[0] ?? null;\n }\n\n async getEnrolledStudents(courseId: string, nextToken?: string | null): Promise<PaginatedList<CourseEnrolled>> {\n const result = await this.network.query<{\n listCourseEnrolledByCourseIdAndCreatedAt: PaginatedList<CourseEnrolled>;\n }>(\n `query ListEnrolledStudents($courseId: ID!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listCourseEnrolledByCourseIdAndCreatedAt(courseId: $courseId, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id courseId userId owner score rank createdAt user { id fullName avatarUrl } }\n nextToken\n }\n }`,\n { courseId, sortDirection: \"DESC\", nextToken }\n );\n return result.data.listCourseEnrolledByCourseIdAndCreatedAt;\n }\n\n async sendEnrollmentRequest(input: SendEnrollmentRequestInput): Promise<{ id: string }> {\n const result = await this.network.mutate<{ createCourseEnrollmentRequest: { id: string } }>(\n `mutation SendEnrollmentRequest($input: CreateCourseEnrollmentRequestInput!) {\n createCourseEnrollmentRequest(input: $input) { id }\n }`,\n { input: { courseId: input.courseId, name: input.name, phone: input.phone, transactionID: input.transactionId, coupon: input.couponId } }\n );\n return result.data.createCourseEnrollmentRequest;\n }\n\n async getSignedURL(input: GetSignedURLInput): Promise<SignedURLResponse> {\n const result = await this.network.query<{ getR2SignedURL: SignedURLResponse }>(\n `query GetR2SignedURL($courseId: ID!, $fileName: String!, $fileType: String!, $parentId: ID) {\n getR2SignedURL(courseId: $courseId, fileName: $fileName, fileType: $fileType, parentId: $parentId) { status signedURL }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.getR2SignedURL;\n }\n\n async getSignedFileURL(input: GetSignedFileURLInput): Promise<SignedURLResponse> {\n const result = await this.network.query<{ getR2SignedFileURL: SignedURLResponse }>(\n `query GetR2SignedFileURL($courseId: ID!, $itemId: ID!, $key: ID!) {\n getR2SignedFileURL(courseId: $courseId, itemId: $itemId, key: $key) { status signedURL }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.getR2SignedFileURL;\n }\n\n async createVideo(input: CreateCourseVideoInput): Promise<CreateCourseVideoResponse> {\n const result = await this.network.query<{ createCourseVideo: CreateCourseVideoResponse }>(\n `query CreateCourseVideo($courseId: ID!, $fileName: String!, $fileType: String!) {\n createCourseVideo(courseId: $courseId, fileName: $fileName, fileType: $fileType) { status videoId }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.createCourseVideo;\n }\n\n async uploadVideoToBunny(input: UploadVideoToBunnyInput): Promise<StatusResponse> {\n const result = await this.network.mutate<{ uploadR2VideoToBunny: StatusResponse }>(\n `mutation UploadR2VideoToBunny($key: String!, $videoId: String!, $fileType: String!) {\n uploadR2VideoToBunny(key: $key, videoId: $videoId, fileType: $fileType) { status }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.uploadR2VideoToBunny;\n }\n\n async getLiveExams(courseId: string, nextToken?: string | null): Promise<PaginatedList<CourseLiveExam>> {\n const result = await this.network.query<{\n listCourseLiveExamByCourseIdAndStartTime: PaginatedList<CourseLiveExam>;\n }>(\n `query ListLiveExams($courseId: ID!, $sortDirection: ModelSortDirection, $nextToken: String) {\n listCourseLiveExamByCourseIdAndStartTime(courseId: $courseId, sortDirection: $sortDirection, nextToken: $nextToken) {\n items { id courseId name startTime endTime owner totalParticipants resultsPublished }\n nextToken\n }\n }`,\n { courseId, sortDirection: \"DESC\", nextToken }\n );\n return result.data.listCourseLiveExamByCourseIdAndStartTime;\n }\n\n async createLiveExam(input: CreateCourseLiveExamInput): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ makeCourseLiveExam: StatusIdResponse }>(\n `mutation MakeCourseLiveExam($courseId: ID!, $name: String!, $questions: String!, $startTime: AWSDateTime!, $endTime: AWSDateTime!) {\n makeCourseLiveExam(courseId: $courseId, name: $name, questions: $questions, startTime: $startTime, endTime: $endTime) { status id }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.makeCourseLiveExam;\n }\n\n async getLiveExamQuestions(examId: string): Promise<CourseLiveExamQuestionsResponse> {\n const result = await this.network.query<{ getCourseLiveExamQuestions: CourseLiveExamQuestionsResponse }>(\n `query GetLiveExamQuestions($examId: ID!) {\n getCourseLiveExamQuestions(examId: $examId) { status name startTime endTime questions selectedOptions }\n }`,\n { examId }\n );\n return result.data.getCourseLiveExamQuestions;\n }\n\n async participateLiveExam(examId: string): Promise<StatusResponse> {\n const result = await this.network.mutate<{ participateCourseLiveExam: StatusResponse }>(\n `mutation ParticipateLiveExam($examId: ID!) {\n participateCourseLiveExam(examId: $examId) { status }\n }`,\n { examId }\n );\n return result.data.participateCourseLiveExam;\n }\n\n async selectLiveExamOption(examId: string, optionId: string, order: number): Promise<StatusResponse> {\n const result = await this.network.mutate<{ selectCourseLiveExamOption: StatusResponse }>(\n `mutation SelectLiveExamOption($examId: ID!, $optionId: ID!, $order: Int!) {\n selectCourseLiveExamOption(examId: $examId, optionId: $optionId, order: $order) { status }\n }`,\n { examId, optionId, order }\n );\n return result.data.selectCourseLiveExamOption;\n }\n\n async getLiveExamLeaderboard(examId: string, nextToken?: string | null): Promise<LeaderboardResponse> {\n const result = await this.network.query<{ getCourseLiveExamLeaderboard: LeaderboardResponse }>(\n `query GetLiveExamLeaderboard($examId: ID!, $nextToken: String) {\n getCourseLiveExamLeaderboard(examId: $examId, nextToken: $nextToken) { status leaderboard nextToken totalParticipants }\n }`,\n { examId, nextToken }\n );\n return result.data.getCourseLiveExamLeaderboard;\n }\n\n async publishLiveExamResults(examId: string): Promise<StatusResponse> {\n const result = await this.network.mutate<{ publishCourseLiveExamResults: StatusResponse }>(\n `mutation PublishLiveExamResults($examId: ID!) {\n publishCourseLiveExamResults(examId: $examId) { status }\n }`,\n { examId }\n );\n return result.data.publishCourseLiveExamResults;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { StatusIdResponse } from \"../types/responses\";\nimport type { Subject, Chapter, Topic } from \"../types/models\";\n\nexport class CurriculumService {\n constructor(private network: NetworkProvider) { }\n\n async createSubject(name: string, level: string): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ makeSubject: StatusIdResponse }>(\n `mutation MakeSubject($name: String!, $level: String!) {\n makeSubject(name: $name, level: $level) { status id }\n }`,\n { name, level }\n );\n return result.data.makeSubject;\n }\n\n async createChapter(name: string, subjectId: string, order: number): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ makeChapter: StatusIdResponse }>(\n `mutation MakeChapter($name: String!, $subjectId: ID!, $order: Int!) {\n makeChapter(name: $name, subjectId: $subjectId, order: $order) { status id }\n }`,\n { name, subjectId, order }\n );\n return result.data.makeChapter;\n }\n\n async createTopic(name: string, chapterId: string): Promise<StatusIdResponse> {\n const result = await this.network.mutate<{ makeTopic: StatusIdResponse }>(\n `mutation MakeTopic($name: String!, $chapterId: ID!) {\n makeTopic(name: $name, chapterId: $chapterId) { status id }\n }`,\n { name, chapterId }\n );\n return result.data.makeTopic;\n }\n\n async getSubjects(level: string): Promise<Subject[]> {\n const result = await this.network.query<{\n listSubjectByLevel: { items: Subject[] };\n }>(\n `query ListSubjects($level: String!) {\n listSubjectByLevel(level: $level) {\n items { id name level questionCount }\n }\n }`,\n { level }\n );\n return result.data.listSubjectByLevel.items;\n }\n\n async getChapters(subjectId: string): Promise<Chapter[]> {\n const result = await this.network.query<{\n listChapterBySubjectIdAndOrder: { items: Chapter[] };\n }>(\n `query ListChapters($subjectId: ID!, $sortDirection: ModelSortDirection) {\n listChapterBySubjectIdAndOrder(subjectId: $subjectId, sortDirection: $sortDirection) {\n items { id name order subjectId questionCount }\n }\n }`,\n { subjectId, sortDirection: \"ASC\" }\n );\n return result.data.listChapterBySubjectIdAndOrder.items;\n }\n\n async getTopics(chapterId: string): Promise<Topic[]> {\n const result = await this.network.query<{\n listTopicByChapterId: { items: Topic[] };\n }>(\n `query ListTopics($chapterId: ID!) {\n listTopicByChapterId(chapterId: $chapterId) {\n items { id name chapterId questionCount }\n }\n }`,\n { chapterId }\n );\n return result.data.listTopicByChapterId.items;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { StorageProvider } from \"../providers/storage\";\nimport type {\n GetSignedURLInput,\n GetSignedFileURLInput,\n CreateCourseVideoInput,\n UploadVideoToBunnyInput,\n} from \"../types/inputs\";\nimport type {\n UploadImageResponse,\n StatusResponse,\n SignedURLResponse,\n CreateCourseVideoResponse,\n} from \"../types/responses\";\n\nexport class MediaService {\n constructor(\n private network: NetworkProvider,\n private storage?: StorageProvider\n ) {}\n\n async uploadImage(questionId: string, image: string): Promise<UploadImageResponse> {\n const result = await this.network.mutate<{ uploadImage: UploadImageResponse }>(\n `mutation UploadImage($questionId: ID!, $image: String!) {\n uploadImage(questionId: $questionId, image: $image) { status imageUrl }\n }`,\n { questionId, image }\n );\n return result.data.uploadImage;\n }\n\n async deleteImage(imageUrl: string): Promise<StatusResponse> {\n const result = await this.network.mutate<{ deleteImage: StatusResponse }>(\n `mutation DeleteImage($imageUrl: ID!) {\n deleteImage(imageUrl: $imageUrl) { status }\n }`,\n { imageUrl }\n );\n return result.data.deleteImage;\n }\n\n async getSignedURL(input: GetSignedURLInput): Promise<SignedURLResponse> {\n const result = await this.network.query<{ getR2SignedURL: SignedURLResponse }>(\n `query GetR2SignedURL($courseId: ID!, $fileName: String!, $fileType: String!, $parentId: ID) {\n getR2SignedURL(courseId: $courseId, fileName: $fileName, fileType: $fileType, parentId: $parentId) { status signedURL }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.getR2SignedURL;\n }\n\n async getSignedFileURL(input: GetSignedFileURLInput): Promise<SignedURLResponse> {\n const result = await this.network.query<{ getR2SignedFileURL: SignedURLResponse }>(\n `query GetR2SignedFileURL($courseId: ID!, $itemId: ID!, $key: ID!) {\n getR2SignedFileURL(courseId: $courseId, itemId: $itemId, key: $key) { status signedURL }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.getR2SignedFileURL;\n }\n\n async getFileUrl(path: string): Promise<{ url: string }> {\n if (!this.storage) throw new Error(\"StorageProvider not configured\");\n return this.storage.getFileUrl(path);\n }\n\n async uploadFile(\n path: string,\n data: Blob | ArrayBuffer | string,\n options?: { contentType?: string; onProgress?: (progress: { loaded: number; total: number }) => void }\n ): Promise<{ path: string }> {\n if (!this.storage) throw new Error(\"StorageProvider not configured\");\n return this.storage.uploadFile(path, data, options);\n }\n\n async createVideo(input: CreateCourseVideoInput): Promise<CreateCourseVideoResponse> {\n const result = await this.network.query<{ createCourseVideo: CreateCourseVideoResponse }>(\n `query CreateCourseVideo($courseId: ID!, $fileName: String!, $fileType: String!) {\n createCourseVideo(courseId: $courseId, fileName: $fileName, fileType: $fileType) { status videoId }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.createCourseVideo;\n }\n\n async uploadVideoToBunny(input: UploadVideoToBunnyInput): Promise<StatusResponse> {\n const result = await this.network.mutate<{ uploadR2VideoToBunny: StatusResponse }>(\n `mutation UploadR2VideoToBunny($key: String!, $videoId: String!, $fileType: String!) {\n uploadR2VideoToBunny(key: $key, videoId: $videoId, fileType: $fileType) { status }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.uploadR2VideoToBunny;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { TrackPracticeProgressInput } from \"../types/inputs\";\nimport type { StatusResponse } from \"../types/responses\";\nimport type {\n UserSubjectProgress,\n UserChapterProgress,\n UserTopicProgress,\n UserTopicMetric,\n QuestionTracking,\n PaginatedList,\n} from \"../types/models\";\n\nexport class ProgressService {\n constructor(private network: NetworkProvider) {}\n\n async track(input: TrackPracticeProgressInput): Promise<StatusResponse> {\n const result = await this.network.mutate<{ trackPracticeProgress: StatusResponse }>(\n `mutation TrackProgress($questionId: ID!, $isCorrect: Boolean!, $subjectId: ID, $chapterId: ID, $topicId: ID) {\n trackPracticeProgress(questionId: $questionId, isCorrect: $isCorrect, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId) { status }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.trackPracticeProgress;\n }\n\n async getSubjectProgress(userId: string): Promise<UserSubjectProgress[]> {\n const result = await this.network.query<{\n listUserSubjectProgressByUserIdAndSubjectId: PaginatedList<UserSubjectProgress>;\n }>(\n `query ListSubjectProgress($userId: String!) {\n listUserSubjectProgressByUserIdAndSubjectId(userId: $userId) {\n items { id userId subjectId practicedCount mistakeCount correctedCount accuracyScore }\n }\n }`,\n { userId }\n );\n return result.data.listUserSubjectProgressByUserIdAndSubjectId.items;\n }\n\n async getChapterProgress(userId: string): Promise<UserChapterProgress[]> {\n const result = await this.network.query<{\n listUserChapterProgressByUserIdAndChapterId: PaginatedList<UserChapterProgress>;\n }>(\n `query ListChapterProgress($userId: String!) {\n listUserChapterProgressByUserIdAndChapterId(userId: $userId) {\n items { id userId chapterId practicedCount mistakeCount correctedCount accuracyScore }\n }\n }`,\n { userId }\n );\n return result.data.listUserChapterProgressByUserIdAndChapterId.items;\n }\n\n async getTopicProgress(userId: string): Promise<UserTopicProgress[]> {\n const result = await this.network.query<{\n listUserTopicProgressByUserIdAndTopicId: PaginatedList<UserTopicProgress>;\n }>(\n `query ListTopicProgress($userId: String!) {\n listUserTopicProgressByUserIdAndTopicId(userId: $userId) {\n items { id userId topicId practicedCount mistakeCount correctedCount accuracyScore }\n }\n }`,\n { userId }\n );\n return result.data.listUserTopicProgressByUserIdAndTopicId.items;\n }\n\n async getTopicMetrics(userId: string): Promise<UserTopicMetric[]> {\n const result = await this.network.query<{\n listUserTopicMetrics: PaginatedList<UserTopicMetric>;\n }>(\n `query ListTopicMetrics($filter: ModelUserTopicMetricFilterInput) {\n listUserTopicMetrics(filter: $filter) {\n items { id userId topicId totalAttempted totalCorrect accuracy }\n }\n }`,\n { filter: { userId: { eq: userId } } }\n );\n return result.data.listUserTopicMetrics.items;\n }\n\n async getMistakenQuestions(userId: string): Promise<QuestionTracking[]> {\n const result = await this.network.query<{\n listQuestionTrackingByUserIdAndSubjectId: PaginatedList<QuestionTracking>;\n }>(\n `query ListMistakes($userId: String!, $filter: ModelQuestionTrackingFilterInput) {\n listQuestionTrackingByUserIdAndSubjectId(userId: $userId, filter: $filter) {\n items { id userId questionId subjectId chapterId topicId status attempts }\n }\n }`,\n { userId, filter: { status: { eq: \"MISTAKE\" } } }\n );\n return result.data.listQuestionTrackingByUserIdAndSubjectId.items;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { EvaluateWrittenAnswerInput } from \"../types/inputs\";\nimport type { EvaluateWrittenAnswerResponse } from \"../types/responses\";\n\nexport class AIService {\n constructor(private network: NetworkProvider) {}\n\n async evaluateWrittenAnswer(input: EvaluateWrittenAnswerInput): Promise<EvaluateWrittenAnswerResponse> {\n const result = await this.network.query<{ evaluateWrittenAnswer: EvaluateWrittenAnswerResponse }>(\n `query EvaluateWrittenAnswer($question: String!, $userAnswer: String!, $correctAnswer: String!, $markingInstructions: String, $topicId: String, $topicName: String, $questionImageUrl: String) {\n evaluateWrittenAnswer(question: $question, userAnswer: $userAnswer, correctAnswer: $correctAnswer, markingInstructions: $markingInstructions, topicId: $topicId, topicName: $topicName, questionImageUrl: $questionImageUrl) {\n score maxScore feedback isCorrect markingExplanation improvementFeedback subquestions markLocation\n }\n }`,\n input as unknown as Record<string, unknown>\n );\n return result.data.evaluateWrittenAnswer;\n }\n}\n","import type { NetworkProvider } from \"../providers/network\";\nimport type { NewsArticle, PaginatedList } from \"../types/models\";\n\nexport class NewsService {\n constructor(private network: NetworkProvider) {}\n\n async create(\n title: string,\n content: string,\n image?: string,\n category?: string,\n excerpt?: string\n ): Promise<NewsArticle | null> {\n const result = await this.network.mutate<{ createNewsArticle: NewsArticle | null }>(\n `mutation CreateNews($input: CreateNewsArticleInput!) {\n createNewsArticle(input: $input) { id title content image category excerpt createdAt updatedAt }\n }`,\n { input: { title, content, image, category, excerpt } }\n );\n return result.data.createNewsArticle;\n }\n\n async list(nextToken?: string): Promise<PaginatedList<NewsArticle>> {\n const result = await this.network.query<{\n listNewsArticles: PaginatedList<NewsArticle>;\n }>(\n `query ListNews($nextToken: String) {\n listNewsArticles(nextToken: $nextToken) {\n items { id title content image category excerpt createdAt updatedAt }\n nextToken\n }\n }`,\n { nextToken }\n );\n return result.data.listNewsArticles;\n }\n\n async get(id: string): Promise<NewsArticle | null> {\n const result = await this.network.query<{ getNewsArticle: NewsArticle | null }>(\n `query GetNews($id: ID!) {\n getNewsArticle(id: $id) { id title content image category excerpt createdAt updatedAt }\n }`,\n { id }\n );\n return result.data.getNewsArticle;\n }\n}\n","import type { AuthProvider } from \"./providers/auth\";\nimport type { NetworkProvider } from \"./providers/network\";\nimport type { StorageProvider } from \"./providers/storage\";\nimport { UserService } from \"./services/user.service\";\nimport { QuestionService } from \"./services/question.service\";\nimport { PackService } from \"./services/pack.service\";\nimport { ContestService } from \"./services/contest.service\";\nimport { CourseService } from \"./services/course.service\";\nimport { CurriculumService } from \"./services/curriculum.service\";\nimport { MediaService } from \"./services/media.service\";\nimport { ProgressService } from \"./services/progress.service\";\nimport { AIService } from \"./services/ai.service\";\nimport { NewsService } from \"./services/news.service\";\n\nexport interface OrjokClientConfig {\n authProvider: AuthProvider;\n networkProvider: NetworkProvider;\n storageProvider?: StorageProvider;\n}\n\nexport class OrjokClient {\n readonly auth: AuthProvider;\n readonly users: UserService;\n readonly questions: QuestionService;\n readonly packs: PackService;\n readonly contests: ContestService;\n readonly courses: CourseService;\n readonly curriculum: CurriculumService;\n readonly media: MediaService;\n readonly progress: ProgressService;\n readonly ai: AIService;\n readonly news: NewsService;\n\n constructor(config: OrjokClientConfig) {\n this.auth = config.authProvider;\n this.users = new UserService(config.networkProvider);\n this.questions = new QuestionService(config.networkProvider);\n this.packs = new PackService(config.networkProvider);\n this.contests = new ContestService(config.networkProvider);\n this.courses = new CourseService(config.networkProvider);\n this.curriculum = new CurriculumService(config.networkProvider);\n this.media = new MediaService(config.networkProvider, config.storageProvider);\n this.progress = new ProgressService(config.networkProvider);\n this.ai = new AIService(config.networkProvider);\n this.news = new NewsService(config.networkProvider);\n }\n}\n\nexport function createOrjokClient(config: OrjokClientConfig): OrjokClient {\n return new OrjokClient(config);\n}\n","export interface EloTier {\n name: string;\n minRating: number;\n maxRating: number;\n color: string;\n}\n\nconst TIERS: EloTier[] = [\n { name: \"Iron\", minRating: 0, maxRating: 799, color: \"#6B7280\" },\n { name: \"Bronze\", minRating: 800, maxRating: 999, color: \"#CD7F32\" },\n { name: \"Silver\", minRating: 1000, maxRating: 1199, color: \"#C0C0C0\" },\n { name: \"Gold\", minRating: 1200, maxRating: 1399, color: \"#FFD700\" },\n { name: \"Platinum\", minRating: 1400, maxRating: 1599, color: \"#00CED1\" },\n { name: \"Diamond\", minRating: 1600, maxRating: 1799, color: \"#B9F2FF\" },\n { name: \"Master\", minRating: 1800, maxRating: 1999, color: \"#9B59B6\" },\n { name: \"Grandmaster\", minRating: 2000, maxRating: 2399, color: \"#E74C3C\" },\n { name: \"Challenger\", minRating: 2400, maxRating: Infinity, color: \"#F1C40F\" },\n];\n\nexport function getEloTier(rating: number): EloTier {\n return TIERS.find((t) => rating >= t.minRating && rating <= t.maxRating) ?? TIERS[0]!;\n}\n\nexport function getEloProgress(rating: number): number {\n const tier = getEloTier(rating);\n if (tier.maxRating === Infinity) return 100;\n const range = tier.maxRating - tier.minRating;\n return Math.round(((rating - tier.minRating) / range) * 100);\n}\n\nexport function getAllTiers(): EloTier[] {\n return [...TIERS];\n}\n\nexport type RatingField =\n | \"sscOverallRating\"\n | \"sscPhysicsRating\"\n | \"sscChemistryRating\"\n | \"sscMathRating\"\n | \"sscBiologyRating\"\n | \"hscOverallRating\"\n | \"hscPhysicsRating\"\n | \"hscChemistryRating\"\n | \"hscMathRating\"\n | \"hscBiologyRating\"\n | \"bcsOverallRating\"\n | \"EngineeringRating\"\n | \"MedicalRating\"\n | \"VarsityRating\"\n | \"BCSRating\";\n\nexport function getRatingForSubject(\n user: Record<string, number | null | undefined>,\n subject: string\n): number {\n const key = subject as RatingField;\n return (user[key] as number | null | undefined) ?? 1000;\n}\n\nexport function computeRatingDelta(beforeRating: number | null | undefined, afterRating: number | null | undefined): number {\n if (beforeRating == null || afterRating == null) return 0;\n return afterRating - beforeRating;\n}\n","import type { QuestionObject } from \"../types/models\";\nimport type { Difficulty, QuestionType } from \"../types/enums\";\n\nexport type ExamMode = \"MCQ\" | \"WRITTEN\" | \"BOTH\";\n\nexport interface ExamConfig {\n mode: ExamMode;\n timePerQuestion: number;\n}\n\nexport function filterQuestionsByMode(\n questions: QuestionObject[],\n mode: ExamMode\n): QuestionObject[] {\n if (mode === \"BOTH\") return questions;\n return questions.filter((q) => q.type === mode || (!q.type && mode === \"MCQ\"));\n}\n\nexport function calculateExamTime(questionCount: number, secondsPerQuestion: number = 60): number {\n return questionCount * secondsPerQuestion;\n}\n\nexport function formatExamTime(totalSeconds: number): string {\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) {\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n }\n return `${minutes}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nexport function scoreExam(\n selectedOptions: (string | null)[],\n correctAnswers: string[]\n): { correct: number; incorrect: number; unanswered: number; total: number } {\n let correct = 0;\n let incorrect = 0;\n let unanswered = 0;\n\n for (let i = 0; i < correctAnswers.length; i++) {\n const selected = selectedOptions[i];\n if (!selected) {\n unanswered++;\n } else if (selected === correctAnswers[i]) {\n correct++;\n } else {\n incorrect++;\n }\n }\n\n return { correct, incorrect, unanswered, total: correctAnswers.length };\n}\n\nexport function isImageAnswer(answer: string | null | undefined): boolean {\n if (!answer) return false;\n return answer.startsWith(\"image::\") || answer.startsWith(\"images::\");\n}\n\nexport function parseImageKeys(answer: string): string[] {\n if (answer.startsWith(\"images::\")) {\n return answer.slice(\"images::\".length).split(\",\").filter(Boolean);\n }\n if (answer.startsWith(\"image::\")) {\n const key = answer.slice(\"image::\".length);\n return key ? [key] : [];\n }\n return [];\n}\n\nexport function buildImageAnswer(keys: string[]): string {\n if (keys.length === 0) return \"\";\n if (keys.length === 1) return `image::${keys[0]}`;\n return `images::${keys.join(\",\")}`;\n}\n\nexport function normalizeDifficulty(raw: string): Difficulty | undefined {\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n const capitalized = trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase();\n if (capitalized === \"Easy\" || capitalized === \"Medium\" || capitalized === \"Hard\") {\n return capitalized as Difficulty;\n }\n return undefined;\n}\n\nexport function detectQuestionType(\n option2: string,\n option3: string,\n option4: string\n): QuestionType {\n if (!option2.trim() && !option3.trim() && !option4.trim()) {\n return \"WRITTEN\";\n }\n return \"MCQ\";\n}\n","import type { Difficulty } from \"../types/enums\";\n\nexport interface ParsedQuestion {\n id?: string;\n imageUrl?: string;\n question: string;\n answer: string;\n option2: string;\n option3: string;\n option4: string;\n explanation: string;\n tags: string[];\n extra?: string;\n difficulty?: Difficulty;\n subjectId?: string;\n chapterId?: string;\n topicId?: string;\n type: \"MCQ\" | \"WRITTEN\";\n markingInstructions?: string;\n answerImageUrl?: string;\n option2ImageUrl?: string;\n option3ImageUrl?: string;\n option4ImageUrl?: string;\n}\n\nexport interface ParseResult {\n questions: ParsedQuestion[];\n errors: string[];\n}\n\nconst MAX_QUESTIONS = 200;\n\nfunction parseFields(parts: string[]): Omit<ParsedQuestion, \"question\" | \"answer\" | \"option2\" | \"option3\" | \"option4\" | \"explanation\" | \"tags\" | \"type\"> {\n let extra = \"\";\n let difficulty: Difficulty | undefined;\n let subjectId = \"\";\n let chapterId = \"\";\n let topicId = \"\";\n let markingInstructions = \"\";\n let id = \"\";\n let imageUrl = \"\";\n let answerImageUrl = \"\";\n let option2ImageUrl = \"\";\n let option3ImageUrl = \"\";\n let option4ImageUrl = \"\";\n\n if (parts.length >= 13) {\n extra = parts[7]?.trim() ?? \"\";\n const rawDiff = parts[8]?.trim() ?? \"\";\n if (rawDiff) {\n const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();\n if (cap === \"Easy\" || cap === \"Medium\" || cap === \"Hard\") difficulty = cap as Difficulty;\n }\n subjectId = parts[9]?.trim() ?? \"\";\n chapterId = parts[10]?.trim() ?? \"\";\n topicId = parts[11]?.trim() ?? \"\";\n markingInstructions = parts[12]?.trim() ?? \"\";\n if (parts.length > 13) id = parts[13]?.trim() ?? \"\";\n if (parts.length > 14) imageUrl = parts[14]?.trim() ?? \"\";\n if (parts.length > 15) answerImageUrl = parts[15]?.trim() ?? \"\";\n if (parts.length > 16) option2ImageUrl = parts[16]?.trim() ?? \"\";\n if (parts.length > 17) option3ImageUrl = parts[17]?.trim() ?? \"\";\n if (parts.length > 18) option4ImageUrl = parts[18]?.trim() ?? \"\";\n } else if (parts.length === 8) {\n extra = parts[7]?.trim() ?? \"\";\n } else if (parts.length === 9) {\n extra = parts[7]?.trim() ?? \"\";\n const rawDiff = parts[8]?.trim() ?? \"\";\n if (rawDiff) {\n const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();\n if (cap === \"Easy\" || cap === \"Medium\" || cap === \"Hard\") difficulty = cap as Difficulty;\n }\n } else if (parts.length === 10) {\n subjectId = parts[7]?.trim() ?? \"\";\n chapterId = parts[8]?.trim() ?? \"\";\n topicId = parts[9]?.trim() ?? \"\";\n } else if (parts.length === 11) {\n extra = parts[7]?.trim() ?? \"\";\n subjectId = parts[8]?.trim() ?? \"\";\n chapterId = parts[9]?.trim() ?? \"\";\n topicId = parts[10]?.trim() ?? \"\";\n } else if (parts.length === 12) {\n extra = parts[7]?.trim() ?? \"\";\n const rawDiff = parts[8]?.trim() ?? \"\";\n if (rawDiff) {\n const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();\n if (cap === \"Easy\" || cap === \"Medium\" || cap === \"Hard\") difficulty = cap as Difficulty;\n }\n subjectId = parts[9]?.trim() ?? \"\";\n chapterId = parts[10]?.trim() ?? \"\";\n topicId = parts[11]?.trim() ?? \"\";\n }\n\n return {\n id: id || undefined,\n imageUrl: imageUrl || undefined,\n extra: extra || undefined,\n difficulty,\n subjectId: subjectId || undefined,\n chapterId: chapterId || undefined,\n topicId: topicId || undefined,\n markingInstructions: markingInstructions || undefined,\n answerImageUrl: answerImageUrl || undefined,\n option2ImageUrl: option2ImageUrl || undefined,\n option3ImageUrl: option3ImageUrl || undefined,\n option4ImageUrl: option4ImageUrl || undefined,\n };\n}\n\nfunction buildQuestion(parts: string[]): ParsedQuestion {\n const tags =\n parts.length >= 7 && parts[6]\n ? parts[6].split(\",\").map((t) => t.trim()).filter(Boolean)\n : [];\n\n const opt2 = parts[2]?.trim() ?? \"\";\n const opt3 = parts[3]?.trim() ?? \"\";\n const opt4 = parts[4]?.trim() ?? \"\";\n const isWritten = parts.length < 6 || (!opt2 && !opt3 && !opt4);\n\n const extra = parseFields(parts);\n\n return {\n question: parts[0]?.trim() ?? \"\",\n answer: parts[1]?.trim() ?? \"\",\n option2: opt2,\n option3: opt3,\n option4: opt4,\n explanation: parts[5]?.trim() ?? \"\",\n tags,\n type: isWritten ? \"WRITTEN\" : \"MCQ\",\n ...extra,\n };\n}\n\nexport function parseTextQuestions(text: string, keyword: string, minParts: number = 2): ParseResult {\n const lines = text.split(\"\\n\");\n const questions: ParsedQuestion[] = [];\n const errors: string[] = [];\n\n if (lines.length > MAX_QUESTIONS) {\n errors.push(`Can't have more than ${MAX_QUESTIONS} questions/lines`);\n return { questions, errors };\n }\n\n for (let idx = 0; idx < lines.length; idx++) {\n const line = lines[idx]!;\n const parts = line.split(keyword);\n if (parts.length === 1 && (parts[0] === \"\\r\" || parts[0] === \"\\n\" || parts[0] === \"\")) {\n continue;\n }\n if (parts.length < minParts || parts.length > 19) {\n errors.push(`Line ${idx + 1} doesn't have between ${minParts} and 19 parts`);\n continue;\n }\n questions.push(buildQuestion(parts));\n }\n\n return { questions, errors };\n}\n\nexport function parseCsvQuestions(rows: string[][]): ParseResult {\n const questions: ParsedQuestion[] = [];\n const errors: string[] = [];\n\n // Skip header row\n const dataRows = rows.slice(1);\n if (dataRows.length > MAX_QUESTIONS) {\n errors.push(`Can't have more than ${MAX_QUESTIONS} questions/lines`);\n return { questions, errors };\n }\n\n for (let idx = 0; idx < dataRows.length; idx++) {\n const line = dataRows[idx]!;\n if (line.length < 2 || line.length > 19) {\n errors.push(`Line ${idx + 2} doesn't have between 2 and 19 parts`);\n continue;\n }\n questions.push(buildQuestion(line));\n }\n\n return { questions, errors };\n}\n\nexport function formatQuestionsToText(\n questions: ParsedQuestion[],\n keyword: string,\n packSubjectId?: string,\n packChapterId?: string,\n packTopicId?: string\n): string {\n const lines = questions.map((q) => {\n const activeSubject = q.subjectId || packSubjectId;\n const activeChapter = q.chapterId || packChapterId;\n const activeTopic = q.topicId || packTopicId;\n\n const subjectSlug = activeSubject ? activeSubject.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n const chapterSlug = activeChapter ? activeChapter.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n const topicSlug = activeTopic ? activeTopic.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n\n const fields = [\n q.question,\n q.answer,\n q.type === \"WRITTEN\" ? \"\" : q.option2,\n q.type === \"WRITTEN\" ? \"\" : q.option3,\n q.type === \"WRITTEN\" ? \"\" : q.option4,\n q.explanation,\n q.tags.join(\", \"),\n q.extra ?? \"\",\n q.difficulty ?? \"\",\n subjectSlug,\n chapterSlug,\n topicSlug,\n q.markingInstructions ?? \"\",\n q.id ?? \"\",\n q.imageUrl ?? \"\",\n q.answerImageUrl ?? \"\",\n q.option2ImageUrl ?? \"\",\n q.option3ImageUrl ?? \"\",\n q.option4ImageUrl ?? \"\",\n ];\n return fields.map((f) => (f || \"\").trim()).join(keyword);\n });\n\n return lines.join(\"\\n\");\n}\n\nexport function formatQuestionsToCsv(\n questions: ParsedQuestion[],\n packSubjectId?: string,\n packChapterId?: string,\n packTopicId?: string\n): string {\n const escapeCSV = (value: string | undefined) =>\n `\"${(value || \"\").replace(/\"/g, '\"\"')}\"`;\n\n const header =\n \"Question,Answer,Option2,Option3,Option4,Explanation,Tags,Extra,Difficulty,Subject,Chapter,Topic,MarkingInstructions,Id,ImageUrl,AnswerImageUrl,Option2ImageUrl,Option3ImageUrl,Option4ImageUrl\";\n\n const rows = questions.map((q) => {\n const activeSubject = q.subjectId || packSubjectId;\n const activeChapter = q.chapterId || packChapterId;\n const activeTopic = q.topicId || packTopicId;\n\n const subjectSlug = activeSubject ? activeSubject.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n const chapterSlug = activeChapter ? activeChapter.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n const topicSlug = activeTopic ? activeTopic.split(\"::\")[0]?.trim() ?? \"\" : \"\";\n\n return [\n escapeCSV(q.question),\n escapeCSV(q.answer),\n escapeCSV(q.type === \"WRITTEN\" ? \"\" : q.option2),\n escapeCSV(q.type === \"WRITTEN\" ? \"\" : q.option3),\n escapeCSV(q.type === \"WRITTEN\" ? \"\" : q.option4),\n escapeCSV(q.explanation),\n escapeCSV(q.tags.join(\", \")),\n escapeCSV(q.extra),\n escapeCSV(q.difficulty),\n escapeCSV(subjectSlug),\n escapeCSV(chapterSlug),\n escapeCSV(topicSlug),\n escapeCSV(q.markingInstructions),\n escapeCSV(q.id),\n escapeCSV(q.imageUrl),\n escapeCSV(q.answerImageUrl),\n escapeCSV(q.option2ImageUrl),\n escapeCSV(q.option3ImageUrl),\n escapeCSV(q.option4ImageUrl),\n ].join(\",\");\n });\n\n return `${header}\\n${rows.join(\"\\n\")}`;\n}\n","import type { StorageProvider } from \"../providers/storage\";\n\nexport function isStorageKey(value: string): boolean {\n return !value.startsWith(\"http://\") && !value.startsWith(\"https://\");\n}\n\ninterface CacheEntry {\n url: string;\n expiresAt: number;\n}\n\nexport class MediaUrlCache {\n private cache = new Map<string, CacheEntry>();\n private readonly ttlMs: number;\n\n constructor(ttlMs: number = 50 * 60 * 1000) {\n this.ttlMs = ttlMs;\n }\n\n get(key: string): string | undefined {\n const entry = this.cache.get(key);\n if (!entry) return undefined;\n if (Date.now() >= entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n return entry.url;\n }\n\n set(key: string, url: string): void {\n this.cache.set(key, { url, expiresAt: Date.now() + this.ttlMs });\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n\nlet warnedNoStorage = false;\n\nexport async function resolveMediaUrl(\n value: string | null | undefined,\n storage: StorageProvider | undefined,\n cache?: MediaUrlCache,\n): Promise<string | null> {\n if (!value || value.length === 0) return null;\n if (!isStorageKey(value)) return value;\n\n if (cache) {\n const cached = cache.get(value);\n if (cached) return cached;\n }\n\n if (!storage) {\n if (!warnedNoStorage) {\n warnedNoStorage = true;\n console.warn(\"@orjok/commons: resolveMediaUrl called without a StorageProvider — returning raw key\");\n }\n return value;\n }\n\n const { url } = await storage.getFileUrl(value);\n cache?.set(value, url);\n return url;\n}\n\nexport async function resolveMediaUrls<T extends Record<string, unknown>>(\n obj: T,\n fields: (keyof T)[],\n storage: StorageProvider | undefined,\n cache?: MediaUrlCache,\n): Promise<T> {\n const copy = { ...obj };\n await Promise.all(\n fields.map(async (field) => {\n const val = copy[field];\n if (typeof val === \"string\") {\n (copy as Record<string, unknown>)[field as string] = await resolveMediaUrl(val, storage, cache);\n }\n }),\n );\n return copy;\n}\n\n// Reset the one-time warning flag (for testing only)\nexport function _resetMediaUrlWarning(): void {\n warnedNoStorage = false;\n}\n","import type { UserSubjectProgress, UserChapterProgress, UserTopicProgress } from \"../types/models\";\n\nexport interface PracticeMetrics {\n totalPracticed: number;\n totalMistakes: number;\n totalCorrected: number;\n accuracy: number;\n}\n\nexport function aggregateSubjectMetrics(progress: UserSubjectProgress[]): PracticeMetrics {\n let totalPracticed = 0;\n let totalMistakes = 0;\n let totalCorrected = 0;\n\n for (const p of progress) {\n totalPracticed += p.practicedCount ?? 0;\n totalMistakes += p.mistakeCount ?? 0;\n totalCorrected += p.correctedCount ?? 0;\n }\n\n const accuracy = totalPracticed > 0\n ? Math.round(((totalPracticed - totalMistakes) / totalPracticed) * 100)\n : 0;\n\n return { totalPracticed, totalMistakes, totalCorrected, accuracy };\n}\n\nexport function aggregateChapterMetrics(progress: UserChapterProgress[]): PracticeMetrics {\n let totalPracticed = 0;\n let totalMistakes = 0;\n let totalCorrected = 0;\n\n for (const p of progress) {\n totalPracticed += p.practicedCount ?? 0;\n totalMistakes += p.mistakeCount ?? 0;\n totalCorrected += p.correctedCount ?? 0;\n }\n\n const accuracy = totalPracticed > 0\n ? Math.round(((totalPracticed - totalMistakes) / totalPracticed) * 100)\n : 0;\n\n return { totalPracticed, totalMistakes, totalCorrected, accuracy };\n}\n\nexport function aggregateTopicMetrics(progress: UserTopicProgress[]): PracticeMetrics {\n let totalPracticed = 0;\n let totalMistakes = 0;\n let totalCorrected = 0;\n\n for (const p of progress) {\n totalPracticed += p.practicedCount ?? 0;\n totalMistakes += p.mistakeCount ?? 0;\n totalCorrected += p.correctedCount ?? 0;\n }\n\n const accuracy = totalPracticed > 0\n ? Math.round(((totalPracticed - totalMistakes) / totalPracticed) * 100)\n : 0;\n\n return { totalPracticed, totalMistakes, totalCorrected, accuracy };\n}\n\nexport function calculateAccuracy(practiced: number, mistakes: number): number {\n if (practiced <= 0) return 0;\n return Math.round(((practiced - mistakes) / practiced) * 100);\n}\n","export function shuffle<T>(array: T[]): T[] {\n const result = [...array];\n let currentIndex = result.length;\n while (currentIndex !== 0) {\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n [result[currentIndex], result[randomIndex]] = [result[randomIndex]!, result[currentIndex]!];\n }\n return result;\n}\n\nexport function shuffleInPlace<T>(array: T[]): void {\n let currentIndex = array.length;\n while (currentIndex !== 0) {\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n [array[currentIndex], array[randomIndex]] = [array[randomIndex]!, array[currentIndex]!];\n }\n}\n","const BANGLA_DIGITS = [\"০\", \"১\", \"২\", \"৩\", \"৪\", \"৫\", \"৬\", \"৭\", \"৮\", \"৯\"] as const;\n\nexport function engToBanglaNumber(num: number | string): string {\n return String(num)\n .split(\"\")\n .map((digit) => {\n const n = parseInt(digit, 10);\n return !isNaN(n) ? BANGLA_DIGITS[n]! : digit;\n })\n .join(\"\");\n}\n","export function formatCurriculumName(idString: string, dbName?: string | null): string {\n if (dbName) return dbName;\n if (!idString) return \"\";\n const namePart = idString.split(\"::\")[0] ?? \"\";\n const clean = namePart.replace(/[-_]/g, \" \");\n return clean\n .split(/\\s+/)\n .map((word) => {\n if (!word) return \"\";\n return word.charAt(0).toUpperCase() + word.slice(1);\n })\n .join(\" \");\n}\n","export function getRelativeTime(startTime: string | Date, endTime?: string | Date): string {\n const now = new Date();\n const start = new Date(startTime);\n const end = endTime ? new Date(endTime) : null;\n\n if (end && now >= start && now <= end) {\n return \"\";\n }\n\n const diffInSeconds = Math.floor((start.getTime() - now.getTime()) / 1000);\n const absDiff = Math.abs(diffInSeconds);\n\n const minute = 60;\n const hour = minute * 60;\n const day = hour * 24;\n const week = day * 7;\n const month = day * 30;\n const year = day * 365;\n\n if (diffInSeconds < 0) {\n if (absDiff < minute) return \"just now\";\n if (absDiff < hour) return `${Math.floor(absDiff / minute)} minutes ago`;\n if (absDiff < day) return `${Math.floor(absDiff / hour)} hours ago`;\n if (absDiff < week) return `${Math.floor(absDiff / day)} days ago`;\n if (absDiff < month) return `${Math.floor(absDiff / week)} weeks ago`;\n if (absDiff < year) return `${Math.floor(absDiff / month)} months ago`;\n return `${Math.floor(absDiff / year)} years ago`;\n } else {\n if (absDiff < minute) return \"in a moment\";\n if (absDiff < hour) return `in ${Math.floor(absDiff / minute)} minutes`;\n if (absDiff < day) return `in ${Math.floor(absDiff / hour)} hours`;\n if (absDiff < week) return `in ${Math.floor(absDiff / day)} days`;\n if (absDiff < month) return `in ${Math.floor(absDiff / week)} weeks`;\n if (absDiff < year) return `in ${Math.floor(absDiff / month)} months`;\n return `in ${Math.floor(absDiff / year)} years`;\n }\n}\n","export function processLatexText(str: string): string {\n if (!str) return str;\n\n const regex = /(\\$\\$(.*?)\\$\\$)|(\\$(.*?)\\$)/gs;\n\n let lastIndex = 0;\n let result = \"\";\n let match;\n\n while ((match = regex.exec(str)) !== null) {\n const textBefore = str.substring(lastIndex, match.index);\n result += textBefore.replace(/\\\\n/g, \"\\n\");\n\n const isDisplay = match[1] !== undefined;\n const mathContent = isDisplay ? match[2]! : match[4]!;\n const delimiter = isDisplay ? \"$$\" : \"$\";\n\n const processedMath = mathContent.replace(\n /(\\\\text\\s*\\{[^{}]*\\})|([\\u0980-\\u09FF]+(?:\\s+[\\u0980-\\u09FF]+)*)/g,\n (_: string, p1: string | undefined, p2: string | undefined) => {\n if (p1) return p1;\n return `\\\\text{${p2}}`;\n }\n );\n\n result += delimiter + processedMath + delimiter;\n lastIndex = regex.lastIndex;\n }\n\n const remainingText = str.substring(lastIndex);\n result += remainingText.replace(/\\\\n/g, \"\\n\");\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
interface UserAttributes {
|
|
2
|
+
email?: string;
|
|
3
|
+
email_verified?: string;
|
|
4
|
+
sub?: string;
|
|
5
|
+
"custom:fullName"?: string;
|
|
6
|
+
[key: string]: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
interface AuthSession {
|
|
9
|
+
tokens?: {
|
|
10
|
+
accessToken?: {
|
|
11
|
+
toString(): string;
|
|
12
|
+
};
|
|
13
|
+
idToken?: {
|
|
14
|
+
toString(): string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
credentials?: {
|
|
18
|
+
accessKeyId: string;
|
|
19
|
+
secretAccessKey: string;
|
|
20
|
+
sessionToken?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface AuthProvider {
|
|
24
|
+
signIn(username: string, password: string): Promise<{
|
|
25
|
+
isSignedIn: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
signUp(username: string, password: string, attributes: Record<string, string>): Promise<{
|
|
28
|
+
isSignUpComplete: boolean;
|
|
29
|
+
userId?: string;
|
|
30
|
+
}>;
|
|
31
|
+
signOut(): Promise<void>;
|
|
32
|
+
signInWithRedirect(provider: string): Promise<void>;
|
|
33
|
+
fetchUserAttributes(): Promise<UserAttributes>;
|
|
34
|
+
updateUserAttributes(attributes: Record<string, string>): Promise<void>;
|
|
35
|
+
fetchAuthSession(): Promise<AuthSession>;
|
|
36
|
+
confirmSignUp(username: string, code: string): Promise<{
|
|
37
|
+
isSignUpComplete: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
resendSignUpCode(username: string): Promise<void>;
|
|
40
|
+
resetPassword(username: string): Promise<void>;
|
|
41
|
+
confirmResetPassword(username: string, code: string, newPassword: string): Promise<void>;
|
|
42
|
+
getCurrentUserId(): Promise<string | null>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface GraphQLResult<T = Record<string, unknown>> {
|
|
46
|
+
data: T;
|
|
47
|
+
errors?: Array<{
|
|
48
|
+
message: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
interface NetworkProvider {
|
|
52
|
+
query<T>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
53
|
+
mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface UploadOptions {
|
|
57
|
+
contentType?: string;
|
|
58
|
+
onProgress?: (progress: {
|
|
59
|
+
loaded: number;
|
|
60
|
+
total: number;
|
|
61
|
+
}) => void;
|
|
62
|
+
}
|
|
63
|
+
interface StorageProvider {
|
|
64
|
+
getFileUrl(path: string): Promise<{
|
|
65
|
+
url: string;
|
|
66
|
+
}>;
|
|
67
|
+
uploadFile(path: string, data: Blob | ArrayBuffer | string, options?: UploadOptions): Promise<{
|
|
68
|
+
path: string;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type { AuthProvider as A, GraphQLResult as G, NetworkProvider as N, StorageProvider as S, UserAttributes as U, AuthSession as a, UploadOptions as b };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
interface UserAttributes {
|
|
2
|
+
email?: string;
|
|
3
|
+
email_verified?: string;
|
|
4
|
+
sub?: string;
|
|
5
|
+
"custom:fullName"?: string;
|
|
6
|
+
[key: string]: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
interface AuthSession {
|
|
9
|
+
tokens?: {
|
|
10
|
+
accessToken?: {
|
|
11
|
+
toString(): string;
|
|
12
|
+
};
|
|
13
|
+
idToken?: {
|
|
14
|
+
toString(): string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
credentials?: {
|
|
18
|
+
accessKeyId: string;
|
|
19
|
+
secretAccessKey: string;
|
|
20
|
+
sessionToken?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface AuthProvider {
|
|
24
|
+
signIn(username: string, password: string): Promise<{
|
|
25
|
+
isSignedIn: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
signUp(username: string, password: string, attributes: Record<string, string>): Promise<{
|
|
28
|
+
isSignUpComplete: boolean;
|
|
29
|
+
userId?: string;
|
|
30
|
+
}>;
|
|
31
|
+
signOut(): Promise<void>;
|
|
32
|
+
signInWithRedirect(provider: string): Promise<void>;
|
|
33
|
+
fetchUserAttributes(): Promise<UserAttributes>;
|
|
34
|
+
updateUserAttributes(attributes: Record<string, string>): Promise<void>;
|
|
35
|
+
fetchAuthSession(): Promise<AuthSession>;
|
|
36
|
+
confirmSignUp(username: string, code: string): Promise<{
|
|
37
|
+
isSignUpComplete: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
resendSignUpCode(username: string): Promise<void>;
|
|
40
|
+
resetPassword(username: string): Promise<void>;
|
|
41
|
+
confirmResetPassword(username: string, code: string, newPassword: string): Promise<void>;
|
|
42
|
+
getCurrentUserId(): Promise<string | null>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface GraphQLResult<T = Record<string, unknown>> {
|
|
46
|
+
data: T;
|
|
47
|
+
errors?: Array<{
|
|
48
|
+
message: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
interface NetworkProvider {
|
|
52
|
+
query<T>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
53
|
+
mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface UploadOptions {
|
|
57
|
+
contentType?: string;
|
|
58
|
+
onProgress?: (progress: {
|
|
59
|
+
loaded: number;
|
|
60
|
+
total: number;
|
|
61
|
+
}) => void;
|
|
62
|
+
}
|
|
63
|
+
interface StorageProvider {
|
|
64
|
+
getFileUrl(path: string): Promise<{
|
|
65
|
+
url: string;
|
|
66
|
+
}>;
|
|
67
|
+
uploadFile(path: string, data: Blob | ArrayBuffer | string, options?: UploadOptions): Promise<{
|
|
68
|
+
path: string;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type { AuthProvider as A, GraphQLResult as G, NetworkProvider as N, StorageProvider as S, UserAttributes as U, AuthSession as a, UploadOptions as b };
|
package/dist/testing.cjs
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/testing/mock-providers.ts
|
|
2
|
+
var MockAuthProvider = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.currentUserId = "test-user-id";
|
|
5
|
+
}
|
|
6
|
+
setCurrentUserId(userId) {
|
|
7
|
+
this.currentUserId = userId;
|
|
8
|
+
}
|
|
9
|
+
async signIn(_username, _password) {
|
|
10
|
+
return { isSignedIn: true };
|
|
11
|
+
}
|
|
12
|
+
async signUp(_username, _password, _attributes) {
|
|
13
|
+
return { isSignUpComplete: true, userId: _nullishCoalesce(this.currentUserId, () => ( void 0)) };
|
|
14
|
+
}
|
|
15
|
+
async signOut() {
|
|
16
|
+
}
|
|
17
|
+
async signInWithRedirect(_provider) {
|
|
18
|
+
}
|
|
19
|
+
async fetchUserAttributes() {
|
|
20
|
+
return { email: "test@test.com", sub: _nullishCoalesce(this.currentUserId, () => ( void 0)) };
|
|
21
|
+
}
|
|
22
|
+
async updateUserAttributes(_attributes) {
|
|
23
|
+
}
|
|
24
|
+
async fetchAuthSession() {
|
|
25
|
+
return {
|
|
26
|
+
tokens: {
|
|
27
|
+
accessToken: { toString: () => "mock-access-token" },
|
|
28
|
+
idToken: { toString: () => "mock-id-token" }
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async confirmSignUp(_username, _code) {
|
|
33
|
+
return { isSignUpComplete: true };
|
|
34
|
+
}
|
|
35
|
+
async resendSignUpCode(_username) {
|
|
36
|
+
}
|
|
37
|
+
async resetPassword(_username) {
|
|
38
|
+
}
|
|
39
|
+
async confirmResetPassword(_username, _code, _newPassword) {
|
|
40
|
+
}
|
|
41
|
+
async getCurrentUserId() {
|
|
42
|
+
return this.currentUserId;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var MockNetworkProvider = class {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.responses = /* @__PURE__ */ new Map();
|
|
48
|
+
this.calls = [];
|
|
49
|
+
}
|
|
50
|
+
setResponse(operationKey, data) {
|
|
51
|
+
this.responses.set(operationKey, data);
|
|
52
|
+
}
|
|
53
|
+
reset() {
|
|
54
|
+
this.responses.clear();
|
|
55
|
+
this.calls.length = 0;
|
|
56
|
+
}
|
|
57
|
+
async query(query, variables) {
|
|
58
|
+
this.calls.push({ type: "query", query, variables });
|
|
59
|
+
return this.findResponse(query);
|
|
60
|
+
}
|
|
61
|
+
async mutate(mutation, variables) {
|
|
62
|
+
this.calls.push({ type: "mutation", query: mutation, variables });
|
|
63
|
+
return this.findResponse(mutation);
|
|
64
|
+
}
|
|
65
|
+
findResponse(queryString) {
|
|
66
|
+
for (const [key, value] of this.responses.entries()) {
|
|
67
|
+
if (queryString.includes(key)) {
|
|
68
|
+
return { data: value };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
throw new Error(
|
|
72
|
+
`No mock response registered for query containing operation. Query starts with: "${queryString.slice(0, 80)}..."`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
var MockStorageProvider = class {
|
|
77
|
+
constructor() {
|
|
78
|
+
this.calls = [];
|
|
79
|
+
}
|
|
80
|
+
async getFileUrl(path) {
|
|
81
|
+
this.calls.push({ method: "getFileUrl", args: [path] });
|
|
82
|
+
return { url: `https://mock-storage.test/${path}` };
|
|
83
|
+
}
|
|
84
|
+
async uploadFile(path, data, options) {
|
|
85
|
+
this.calls.push({ method: "uploadFile", args: [path, data, options] });
|
|
86
|
+
if (_optionalChain([options, 'optionalAccess', _ => _.onProgress])) {
|
|
87
|
+
options.onProgress({ loaded: 100, total: 100 });
|
|
88
|
+
}
|
|
89
|
+
return { path };
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
exports.MockAuthProvider = MockAuthProvider; exports.MockNetworkProvider = MockNetworkProvider; exports.MockStorageProvider = MockStorageProvider;
|
|
97
|
+
//# sourceMappingURL=testing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/orjok/orjok/packages/commons/dist/testing.cjs","../src/testing/mock-providers.ts"],"names":[],"mappings":"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","file":"/home/runner/work/orjok/orjok/packages/commons/dist/testing.cjs","sourcesContent":[null,"import type { AuthProvider, UserAttributes, AuthSession } from \"../providers/auth\";\nimport type { NetworkProvider, GraphQLResult } from \"../providers/network\";\nimport type { StorageProvider, UploadOptions } from \"../providers/storage\";\n\nexport class MockAuthProvider implements AuthProvider {\n private currentUserId: string | null = \"test-user-id\";\n\n setCurrentUserId(userId: string | null): void {\n this.currentUserId = userId;\n }\n\n async signIn(_username: string, _password: string) {\n return { isSignedIn: true };\n }\n\n async signUp(_username: string, _password: string, _attributes: Record<string, string>) {\n return { isSignUpComplete: true, userId: this.currentUserId ?? undefined };\n }\n\n async signOut() {}\n\n async signInWithRedirect(_provider: string) {}\n\n async fetchUserAttributes(): Promise<UserAttributes> {\n return { email: \"test@test.com\", sub: this.currentUserId ?? undefined };\n }\n\n async updateUserAttributes(_attributes: Record<string, string>) {}\n\n async fetchAuthSession(): Promise<AuthSession> {\n return {\n tokens: {\n accessToken: { toString: () => \"mock-access-token\" },\n idToken: { toString: () => \"mock-id-token\" },\n },\n };\n }\n\n async confirmSignUp(_username: string, _code: string) {\n return { isSignUpComplete: true };\n }\n\n async resendSignUpCode(_username: string) {}\n\n async resetPassword(_username: string) {}\n\n async confirmResetPassword(_username: string, _code: string, _newPassword: string) {}\n\n async getCurrentUserId(): Promise<string | null> {\n return this.currentUserId;\n }\n}\n\nexport class MockNetworkProvider implements NetworkProvider {\n private responses = new Map<string, unknown>();\n readonly calls: Array<{ type: \"query\" | \"mutation\"; query: string; variables?: Record<string, unknown> }> = [];\n\n setResponse<T>(operationKey: string, data: T): void {\n this.responses.set(operationKey, data);\n }\n\n reset(): void {\n this.responses.clear();\n this.calls.length = 0;\n }\n\n async query<T>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>> {\n this.calls.push({ type: \"query\", query, variables });\n return this.findResponse<T>(query);\n }\n\n async mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>> {\n this.calls.push({ type: \"mutation\", query: mutation, variables });\n return this.findResponse<T>(mutation);\n }\n\n private findResponse<T>(queryString: string): GraphQLResult<T> {\n for (const [key, value] of this.responses.entries()) {\n if (queryString.includes(key)) {\n return { data: value as T };\n }\n }\n throw new Error(\n `No mock response registered for query containing operation. Query starts with: \"${queryString.slice(0, 80)}...\"`\n );\n }\n}\n\nexport class MockStorageProvider implements StorageProvider {\n readonly calls: Array<{ method: string; args: unknown[] }> = [];\n\n async getFileUrl(path: string): Promise<{ url: string }> {\n this.calls.push({ method: \"getFileUrl\", args: [path] });\n return { url: `https://mock-storage.test/${path}` };\n }\n\n async uploadFile(\n path: string,\n data: Blob | ArrayBuffer | string,\n options?: UploadOptions\n ): Promise<{ path: string }> {\n this.calls.push({ method: \"uploadFile\", args: [path, data, options] });\n if (options?.onProgress) {\n options.onProgress({ loaded: 100, total: 100 });\n }\n return { path };\n }\n}\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { A as AuthProvider, U as UserAttributes, a as AuthSession, N as NetworkProvider, G as GraphQLResult, S as StorageProvider, b as UploadOptions } from './storage-DLqdJgQt.cjs';
|
|
2
|
+
|
|
3
|
+
declare class MockAuthProvider implements AuthProvider {
|
|
4
|
+
private currentUserId;
|
|
5
|
+
setCurrentUserId(userId: string | null): void;
|
|
6
|
+
signIn(_username: string, _password: string): Promise<{
|
|
7
|
+
isSignedIn: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
signUp(_username: string, _password: string, _attributes: Record<string, string>): Promise<{
|
|
10
|
+
isSignUpComplete: boolean;
|
|
11
|
+
userId: string | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
signOut(): Promise<void>;
|
|
14
|
+
signInWithRedirect(_provider: string): Promise<void>;
|
|
15
|
+
fetchUserAttributes(): Promise<UserAttributes>;
|
|
16
|
+
updateUserAttributes(_attributes: Record<string, string>): Promise<void>;
|
|
17
|
+
fetchAuthSession(): Promise<AuthSession>;
|
|
18
|
+
confirmSignUp(_username: string, _code: string): Promise<{
|
|
19
|
+
isSignUpComplete: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
resendSignUpCode(_username: string): Promise<void>;
|
|
22
|
+
resetPassword(_username: string): Promise<void>;
|
|
23
|
+
confirmResetPassword(_username: string, _code: string, _newPassword: string): Promise<void>;
|
|
24
|
+
getCurrentUserId(): Promise<string | null>;
|
|
25
|
+
}
|
|
26
|
+
declare class MockNetworkProvider implements NetworkProvider {
|
|
27
|
+
private responses;
|
|
28
|
+
readonly calls: Array<{
|
|
29
|
+
type: "query" | "mutation";
|
|
30
|
+
query: string;
|
|
31
|
+
variables?: Record<string, unknown>;
|
|
32
|
+
}>;
|
|
33
|
+
setResponse<T>(operationKey: string, data: T): void;
|
|
34
|
+
reset(): void;
|
|
35
|
+
query<T>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
36
|
+
mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<GraphQLResult<T>>;
|
|
37
|
+
private findResponse;
|
|
38
|
+
}
|
|
39
|
+
declare class MockStorageProvider implements StorageProvider {
|
|
40
|
+
readonly calls: Array<{
|
|
41
|
+
method: string;
|
|
42
|
+
args: unknown[];
|
|
43
|
+
}>;
|
|
44
|
+
getFileUrl(path: string): Promise<{
|
|
45
|
+
url: string;
|
|
46
|
+
}>;
|
|
47
|
+
uploadFile(path: string, data: Blob | ArrayBuffer | string, options?: UploadOptions): Promise<{
|
|
48
|
+
path: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { MockAuthProvider, MockNetworkProvider, MockStorageProvider };
|