import * as _googleapis_classroom from '@googleapis/classroom'; import { Firestore } from '@google-cloud/firestore'; import z from 'zod'; declare const codeSchema: z.ZodString; type Code = z.infer; declare const classroomAttachmentEntitySchema: z.ZodObject<{ courseId: z.ZodString; postId: z.ZodString; id: z.ZodString; title: z.ZodString; teacherViewUri: z.ZodObject<{ uri: z.ZodString; }, z.core.$strip>; studentViewUri: z.ZodObject<{ uri: z.ZodString; }, z.core.$strip>; studentWorkReviewUri: z.ZodOptional>; itemId: z.ZodString; maxPoints: z.ZodOptional>; attachmentId: z.ZodString; createdAt: z.ZodString; teacherLoginHint: z.ZodOptional; }, z.core.$strip>; type ClassroomAttachmentEntity = z.infer; declare const classroomCourseWorkEntitySchema: z.ZodObject<{ assignmentToken: z.ZodString; courseWorkId: z.ZodString; courseId: z.ZodString; teacherLoginHint: z.ZodString; lessonSlug: z.ZodString; programmeSlug: z.ZodString; unitSlug: z.ZodString; maxPoints: z.ZodNumber; createdAt: z.ZodString; }, z.core.$strip>; type ClassroomCourseWorkEntity = z.infer; declare const createAnnouncementAttachmentArgsSchema: z.ZodObject<{ courseId: z.ZodString; itemId: z.ZodString; addOnToken: z.ZodString; title: z.ZodString; lessonSlug: z.ZodString; programmeSlug: z.ZodString; unitSlug: z.ZodString; maxPoints: z.ZodOptional; teacherLoginHint: z.ZodOptional; }, z.core.$strip>; type CreateAnnouncementAttachmentArgs = z.infer; declare const courseWorkCreatedResultSchema: z.ZodObject<{ courseWorkId: z.ZodString; courseId: z.ZodString; alternateLink: z.ZodOptional; title: z.ZodString; }, z.core.$strip>; type CourseWorkCreatedResult = z.infer; declare const courseListItemSchema: z.ZodObject<{ id: z.ZodString; name: z.ZodString; section: z.ZodOptional; }, z.core.$strip>; type CourseListItem = z.infer; declare enum PostSubmissionState { SUBMISSION_STATE_UNSPECIFIED = "SUBMISSION_STATE_UNSPECIFIED", NEW = "NEW", CREATED = "CREATED", RECLAIMED_BY_STUDENT = "RECLAIMED_BY_STUDENT", TURNED_IN = "TURNED_IN", RETURNED = "RETURNED" } declare const pupilLessonProgressSchema: z.ZodObject<{ starterQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; exitQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; video: z.ZodOptional>; intro: z.ZodOptional; worksheetDownloaded: z.ZodOptional; isComplete: z.ZodBoolean; }, z.core.$strip>>; updatedAt: z.ZodString; createdAt: z.ZodString; postSubmissionState: z.ZodEnum; submissionId: z.ZodString; attachmentId: z.ZodString; courseId: z.ZodString; itemId: z.ZodString; pupilLoginHint: z.ZodString; }, z.core.$strip>; type PupilLessonProgress = z.infer; declare const upsertPupilLessonProgressArgsSchema: z.ZodObject<{ starterQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; exitQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; video: z.ZodOptional>; intro: z.ZodOptional; worksheetDownloaded: z.ZodOptional; isComplete: z.ZodBoolean; }, z.core.$strip>>; submissionId: z.ZodString; attachmentId: z.ZodString; courseId: z.ZodString; itemId: z.ZodString; pupilLoginHint: z.ZodString; }, z.core.$strip>; type UpsertPupilLessonProgressArgs = z.infer; declare const courseWorkPupilProgressSchema: z.ZodObject<{ starterQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; exitQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; video: z.ZodOptional>; intro: z.ZodOptional; worksheetDownloaded: z.ZodOptional; isComplete: z.ZodBoolean; }, z.core.$strip>>; updatedAt: z.ZodString; createdAt: z.ZodString; submissionId: z.ZodString; assignmentToken: z.ZodString; courseWorkId: z.ZodString; courseId: z.ZodString; pupilLoginHint: z.ZodString; gradeSubmitted: z.ZodOptional; resultsLinkAttached: z.ZodOptional; postSubmissionState: z.ZodOptional>; }, z.core.$strip>; type CourseWorkPupilProgress = z.infer; declare const upsertCourseWorkPupilProgressArgsSchema: z.ZodObject<{ starterQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; exitQuiz: z.ZodOptional; grade: z.ZodNumber; pupilAnswer: z.ZodNullable>>, z.ZodNull]>>>; feedback: z.ZodOptional, z.ZodArray>]>>; isPartiallyCorrect: z.ZodOptional; correctAnswer: z.ZodOptional>]>>; usedHint: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>>; video: z.ZodOptional>; intro: z.ZodOptional; worksheetDownloaded: z.ZodOptional; isComplete: z.ZodBoolean; }, z.core.$strip>>; submissionId: z.ZodString; assignmentToken: z.ZodString; courseWorkId: z.ZodString; courseId: z.ZodString; pupilLoginHint: z.ZodString; }, z.core.$strip>; type UpsertCourseWorkPupilProgressArgs = z.infer; type CreateCourseWorkServiceArgs = { courseId: string; title: string; description?: string; lessonSlug: string; programmeSlug: string; unitSlug: string; maxPoints: number; teacherLoginHint: string; }; type FetchPupilResponseArgs = { courseId: string; itemId: string; attachmentId: string; submissionId: string; }; type VerifiedAuthSession = { session: string; token: string; userProfilePicUrl?: string; loginHint?: string; }; type OakGoogleSignInCallback = { encryptedSession: string; accessToken: string; profilePictureUrl?: string; }; declare class OakGoogleClassroomAddOn { private oauthService; private sessionService; private classroomAttachmentService; private pupilProgressService; private courseWorkService; private courseWorkProgressService; private encryptionService; private firestoreClient; private baseUrl; constructor(encryptionSecret: string, firestore: Firestore, googleOAuthClientId: string, googleOAuthClientSecret: string, googleOAuthCallbackApiRoute: string, sessionSecret: string, baseUrl: string); /** * Generates the Google OAuth sign-in URL for user authentication. * This requests the scopes for a teacher account * @param loginHint - Optional login hint to attach to generated url * @param subscribeToNewsletter - Whether the user opted in to the newsletter */ getGoogleSignInUrl(loginHint?: string, subscribeToNewsletter?: boolean): Promise; /** * Generates the Google OAuth sign-in URL for pupil authentication. * This requests the scopes for a pupil, which are more limited than the teacher scopes. * @param loginHint */ getPupilGoogleSignInUrl(loginHint?: string): Promise; /** * Handles the Google OAuth callback by exchanging the authorization code for tokens, * creating an encrypted session, and persisting user credentials. * @param code - The authorization code from Google's OAuth callback * @param subscribeToNewsletterFn - Optional callback to subscribe the user to a newsletter */ handleGoogleSignInCallback(code: Code, subscribeToNewsletterFn?: (email: string) => Promise): Promise; /** * Checks if session exists and is authenticated. It will automatically attempt * to refresh the session if it has expired. * Returns null for an invalid session. * Returns the encrypted session (original or refreshed) if valid. * @param encryptedSession - The user's encrypted session string * @param accessToken - The user's current OAuth access token */ verifyAuthSession(encryptedSession?: string, accessToken?: string): Promise; /** * Validates the user's session and creates a Google Classroom attachment. * @param args - The attachment including course, item, and lesson details * @param accessToken - The user's current OAuth access token * @param session - The user's encrypted session string */ createAttachment(args: CreateAnnouncementAttachmentArgs, accessToken: string, session: string): Promise; /** * Gets the add-on context from Google Classroom for the current pupil. * Returns the studentContext including submissionId, plus the pupilLoginHint * extracted from the session. * @param courseId - The Google Classroom course ID * @param itemId - The courseWork item ID * @param attachmentId - The attachment ID * @param accessToken - The pupil's current OAuth access token * @param session - The pupil's encrypted session string */ getAddOnContext(courseId: string, itemId: string, attachmentId: string, accessToken: string, session: string): Promise<{ pupilLoginHint: string; courseId?: string | null; itemId?: string | null; postId?: string | null; studentContext?: _googleapis_classroom.classroom_v1.Schema$StudentContext; supportsStudentWork?: boolean | null; teacherContext?: _googleapis_classroom.classroom_v1.Schema$TeacherContext; }>; /** * Resolves a teacher OAuth client by looking up the attachment's teacherLoginHint * and fetching the teacher's stored credentials from Firestore. * Grade sync is intentionally skipped when the attachment's maxPoints is not a * positive number (null, undefined, or 0), allowing teachers to disable automatic * grading by setting the score to 0 or Unmarked. * In dev mode, falls back to GOOGLE_CLASSROOM_DEV_REFRESH_TOKEN if teacher credentials are not found. * @param attachmentId - The attachment ID to look up the teacher for. * @returns A GoogleOAuthClient authenticated with teacher credentials, or undefined if grade sync is disabled or credentials are unavailable. */ private resolveTeacherOAuthClient; /** * Upserts pupil lesson progress to Firestore and updates GC pointsEarned * when the exit quiz is newly completed, using the teacher's OAuth credentials. * @param args - The lesson progress data * @param accessToken - The pupil's current OAuth access token * @param session - The pupil's encrypted session string */ upsertPupilLessonProgress(args: UpsertPupilLessonProgressArgs, accessToken: string, session: string): Promise; /** * Retrieves pupil lesson progress from Firestore. * Does not require Google Classroom authentication. * @param submissionId - The Google Classroom submission ID */ getPupilLessonProgress(submissionId: string, attachmentId: string, itemId: string): Promise; /** * Resolves a teacher OAuth client by looking up the coursework's teacherLoginHint * from Firestore (keyed by assignmentToken) and fetching stored credentials. */ private resolveTeacherOAuthClientForCourseWork; private getTeacherRefreshToken; /** * Lists the active Google Classroom courses for the authenticated teacher. * @param accessToken - The teacher's current OAuth access token * @param session - The teacher's encrypted session string */ listCourses(accessToken: string, session: string): Promise; /** * Creates a CourseWork assignment with Link material and stores the * assignmentToken → courseWork mapping in Firestore. * @param args - Lesson and course details * @param accessToken - The teacher's current OAuth access token * @param session - The teacher's encrypted session string */ createCourseWork(args: Omit, accessToken: string, session: string): Promise; /** * Retrieves the pupil's submissionId for a given coursework item. * Must be called with the pupil's session (userId=me lookup). * @param courseId - The Google Classroom course ID * @param courseWorkId - The courseWork item ID * @param accessToken - The pupil's current OAuth access token * @param session - The pupil's encrypted session string */ getStudentSubmissionId(courseId: string, courseWorkId: string, accessToken: string, session: string): Promise; /** * Upserts pupil progress for a link-based CourseWork assignment and syncs * the grade to Google Classroom when the exit quiz is newly completed. * @param args - The pupil progress data * @param accessToken - The pupil's current OAuth access token * @param session - The pupil's encrypted session string */ upsertCourseWorkPupilProgress(args: UpsertCourseWorkPupilProgressArgs, accessToken: string, session: string): Promise; /** * Retrieves the stored CourseWork entity for a given assignmentToken. * Does not require Google Classroom authentication — Firestore-only lookup. * Returns null if the token is not found (caller should treat as 404). * @param assignmentToken - The opaque token embedded in the lesson URL */ getClassroomCourseWork(assignmentToken: string): Promise; /** * Retrieves pupil progress for a link-based CourseWork assignment. * Does not require Google Classroom authentication. * @param submissionId - The Google Classroom submission ID */ getCourseWorkPupilProgress(submissionId: string, assignmentToken: string): Promise; /** * Turns in a student's submission using the student's own OAuth credentials. * Must be called after grade sync (upsertCourseWorkPupilProgress) to ensure * the grade is patched before the submission state changes to TURNED_IN. * @param courseId - The Google Classroom course ID * @param courseWorkId - The courseWork item ID * @param submissionId - The student's submission ID * @param accessToken - The student's current OAuth access token * @param session - The student's encrypted session string */ turnInCourseWorkSubmission(courseId: string, courseWorkId: string, submissionId: string, assignmentToken: string, accessToken: string, session: string): Promise; getPostSubmissionState(args: FetchPupilResponseArgs, accessToken: string, session: string): Promise; } declare enum ExceptionType { GoogleOAuth = "google-oauth", Firestore = "firestore", Encryption = "encryption", OakGoogleClassroom = "oak-google-classroom" } declare enum ErrorSeverity { Error = "error", Warning = "warning", Info = "info" } interface ErrorContext { operation: string; service: ExceptionType; userId?: string; metadata?: Record; } interface ErrorMapping { userMessage: string; internalMessage: string; shouldRetry: boolean; severity: ErrorSeverity; } type OakGoogleClassroomExceptionOptions = { code?: string; severity?: ErrorSeverity; shouldRetry?: boolean; context?: ErrorContext; originalError?: Error; }; type OakGoogleClassroomExceptionObject = OakGoogleClassroomExceptionOptions & { name: string; message: string; type: ExceptionType; }; /** * Custom exception for Oak Google Classroom Addon errors */ declare class OakGoogleClassroomException extends Error { type: ExceptionType; code?: string; shouldRetry?: boolean; severity: ErrorSeverity; context?: ErrorContext; originalError?: Error; constructor(message: string, type: ExceptionType, options?: OakGoogleClassroomExceptionOptions); toObject(): OakGoogleClassroomExceptionObject; static GoogleOAuthError(message: string, operation: string, metadata?: Record, originalError?: Error, severity?: ErrorSeverity): OakGoogleClassroomException; static OakGoogleClassroomError(message: string, functionName: string, metadata?: Record, originalError?: Error, severity?: ErrorSeverity): OakGoogleClassroomException; } export { ErrorSeverity, ExceptionType, OakGoogleClassroomAddOn, OakGoogleClassroomException }; export type { ErrorContext, ErrorMapping, OakGoogleClassroomExceptionObject, OakGoogleSignInCallback, VerifiedAuthSession };