kampus 0.1.0
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 +420 -0
- package/dist/bin.mjs +7231 -0
- package/dist/bin.mjs.map +7 -0
- package/package.json +27 -0
package/dist/bin.mjs.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../packages/core/src/types.ts", "../../../../packages/core/src/errors.ts", "../../../../packages/core/src/secret.ts", "../../../../packages/core/src/normalize.ts", "../../../../packages/core/src/metadata.ts", "../../../../packages/core/src/config.ts", "../../../../packages/core/src/cache.ts", "../../../../packages/core/src/client.ts", "../../../../packages/core/src/index.ts", "../../../../packages/cli/src/commands/resolve.ts", "../../../../packages/cli/src/program.ts", "../../../../packages/cli/src/commands/class.ts", "../../../../packages/cli/src/client-factory.ts", "../../../../packages/providers/comcigan/src/provider.ts", "../../../../packages/providers/neis/src/provider.ts", "../../../../packages/cli/src/output.ts", "../../../../packages/cli/src/commands/auth.ts", "../../../../packages/cli/src/commands/config.ts", "../../../../packages/cli/src/commands/diag.ts", "../../../../packages/cli/src/errors.ts", "../../../../packages/cli/src/commands/meals.ts", "../../../../packages/cli/src/commands/neis.ts", "../../../../packages/cli/src/commands/profile.ts", "../../../../packages/cli/src/commands/school.ts", "../../../../packages/cli/src/commands/teacher.ts", "../../../../packages/cli/src/tui/index.tsx", "../../../../packages/cli/src/tui/logo.ts", "../../../../packages/cli/src/tui/components.tsx", "../../../../packages/cli/src/tui/types.ts", "../../../../packages/cli/src/tui/theme.ts", "../../../../packages/cli/src/tui/pages.tsx", "../../../../packages/cli/src/tui/shortcuts.ts", "../../../../packages/cli/src/tui/settings.ts", "../../../../packages/cli/src/usecases/human.ts", "../../../../packages/cli/src/commands/interactive.ts", "../../../../packages/cli/src/commands/util.ts", "../../../../packages/cli/src/runtime.ts", "../../../../packages/cli/src/bin.ts"],
|
|
4
|
+
"sourcesContent": ["export type ProviderId = 'comcigan' | 'neis';\nexport type AccessMode = 'official-full' | 'official-limited' | 'unofficial';\n\nexport interface ComciganSchoolRef {\n schoolCode: number;\n}\n\nexport interface NeisSchoolRef {\n officeCode: string;\n schoolCode: string;\n}\n\nexport interface ProviderRefs {\n comcigan?: ComciganSchoolRef;\n neis?: NeisSchoolRef;\n}\n\n// ---------------------------------------------------------------------------\n// School\n// ---------------------------------------------------------------------------\n\nexport interface SchoolRef {\n name: string;\n region?: string;\n schoolType?: string;\n providerRefs: ProviderRefs;\n}\n\nexport interface SchoolSearchResult extends SchoolRef {\n sourceProviders: ProviderId[];\n}\n\nexport interface ProviderWarning {\n provider: string;\n code: string;\n message: string;\n}\n\nexport interface DataStatus {\n accessMode: AccessMode;\n complete: boolean;\n sourceProviders: ProviderId[];\n warnings?: ProviderWarning[];\n}\n\nexport interface SchoolInfo extends SchoolRef {\n address?: string;\n phone?: string;\n website?: string;\n gradeCount?: number;\n classCounts?: Record<number, number>;\n teacherNames?: string[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Timetable\n// ---------------------------------------------------------------------------\n\nexport type PeriodStatus = 'class' | 'unknown-subject' | 'free';\n\nexport interface PeriodSource {\n provider: string;\n rawSubject?: string;\n rawTeacher?: string;\n rawCodes?: Record<string, number | string>;\n}\n\nexport interface PeriodItem {\n period: number;\n subject: string;\n teacher?: string;\n status: PeriodStatus;\n isFreePeriod: boolean;\n source: PeriodSource;\n warnings?: ProviderWarning[];\n}\n\nexport interface DayTimetable {\n weekday: number;\n weekdayName: string;\n date?: string;\n periods: PeriodItem[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\nexport interface WeekTimetable {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekStart?: string;\n days: DayTimetable[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\nexport interface TeacherTimetable {\n school: SchoolRef;\n teacherName: string;\n days: TeacherDayTimetable[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\nexport interface TeacherDayTimetable {\n weekday: number;\n weekdayName: string;\n date?: string;\n periods: TeacherPeriodItem[];\n}\n\nexport interface TeacherPeriodItem {\n period: number;\n subject: string;\n grade?: number;\n classNo?: number;\n classLabel?: string;\n status: PeriodStatus;\n isFreePeriod: boolean;\n source: PeriodSource;\n warnings?: ProviderWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Class times\n// ---------------------------------------------------------------------------\n\nexport interface ClassTimeSlot {\n period: number;\n startTime: string;\n endTime: string;\n}\n\n// ---------------------------------------------------------------------------\n// Meals\n// ---------------------------------------------------------------------------\n\nexport interface MealItem {\n name: string;\n allergyCodes?: number[];\n}\n\nexport interface DailyMealService {\n type: string;\n mealCode?: string;\n items: MealItem[];\n calories?: string;\n nutritionInfo?: string;\n originInfo?: string;\n rawMenuText?: string;\n rawRow?: Record<string, string>;\n}\n\nexport interface DailyMeals {\n date: string;\n weekdayName?: string;\n meals: DailyMealService[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\nexport interface WeeklyMeals {\n school: SchoolRef;\n weekStart?: string;\n fromDate?: string;\n toDate?: string;\n days: DailyMeals[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Teacher info\n// ---------------------------------------------------------------------------\n\nexport interface TeacherInfo {\n school: SchoolRef;\n name: string;\n subjects?: string[];\n classes?: string[];\n providerMetadata?: ProviderMetadata;\n dataStatus?: DataStatus;\n warnings?: ProviderWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Snapshot diff\n// ---------------------------------------------------------------------------\n\nexport interface SnapshotDiff {\n school: SchoolRef;\n grade: number;\n classNo: number;\n changes: PeriodChange[];\n}\n\nexport interface PeriodChange {\n weekday: number;\n weekdayName: string;\n period: number;\n before: { subject: string; teacher?: string; status?: PeriodStatus };\n after: { subject: string; teacher?: string; status?: PeriodStatus };\n}\n\n// ---------------------------------------------------------------------------\n// Provider metadata\n// ---------------------------------------------------------------------------\n\nexport interface ProviderMetadata {\n provider: string;\n fetchedAt: string;\n cached?: boolean;\n warnings?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Provider interface\n// ---------------------------------------------------------------------------\n\nexport type ProviderCapability =\n | 'schoolSearch'\n | 'schoolInfo'\n | 'studentTimetable'\n | 'teacherTimetable'\n | 'teacherInfo'\n | 'classTimes'\n | 'meals';\n\nexport interface KampusProvider {\n readonly name: string;\n readonly capabilities: ReadonlySet<ProviderCapability>;\n\n init?(): Promise<void>;\n\n searchSchools?(keyword: string): Promise<SchoolSearchResult[]>;\n\n getSchoolInfo?(school: SchoolRef): Promise<SchoolInfo>;\n\n getWeekTimetable?(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekOffset?: number;\n }): Promise<WeekTimetable>;\n\n getDayTimetable?(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekday: number;\n weekOffset?: number;\n }): Promise<DayTimetable>;\n\n getTeacherTimetable?(params: {\n school: SchoolRef;\n teacherName: string;\n weekday?: number;\n weekOffset?: number;\n }): Promise<TeacherTimetable>;\n\n getTeacherInfo?(params: {\n school: SchoolRef;\n teacherName: string;\n }): Promise<TeacherInfo>;\n\n getClassTimes?(school: SchoolRef): Promise<ClassTimeSlot[]>;\n\n getMealsToday?(params: {\n school: SchoolRef;\n date?: string;\n }): Promise<DailyMeals>;\n\n getMealsWeek?(params: {\n school: SchoolRef;\n weekOffset?: number;\n date?: string;\n }): Promise<WeeklyMeals>;\n\n getMealsRange?(params: {\n school: SchoolRef;\n fromDate: string;\n toDate: string;\n }): Promise<WeeklyMeals>;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const WEEKDAY_NAMES: Record<number, string> = {\n 1: '\\uC6D4\\uC694\\uC77C',\n 2: '\\uD654\\uC694\\uC77C',\n 3: '\\uC218\\uC694\\uC77C',\n 4: '\\uBAA9\\uC694\\uC77C',\n 5: '\\uAE08\\uC694\\uC77C',\n 6: '\\uD1A0\\uC694\\uC77C',\n 7: '\\uC77C\\uC694\\uC77C',\n};\n\nexport const WEEKDAY_SHORT: Record<number, string> = {\n 1: '\\uC6D4',\n 2: '\\uD654',\n 3: '\\uC218',\n 4: '\\uBAA9',\n 5: '\\uAE08',\n 6: '\\uD1A0',\n 7: '\\uC77C',\n};\n\nexport const UNKNOWN_SUBJECT = '\\uBBF8\\uD655\\uC778';\n", "import type { SchoolRef } from './types.js';\n\nexport class KampusError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown,\n ) {\n super(message);\n this.name = 'KampusError';\n }\n}\n\nexport class NetworkError extends KampusError {\n constructor(message: string, cause?: unknown) {\n super(message, 'NETWORK_ERROR', cause);\n this.name = 'NetworkError';\n }\n}\n\nexport class UpstreamChangedError extends KampusError {\n constructor(message: string, cause?: unknown) {\n super(message, 'UPSTREAM_CHANGED', cause);\n this.name = 'UpstreamChangedError';\n }\n}\n\nexport class SchoolNotFoundError extends KampusError {\n constructor(keyword: string) {\n super(`School not found: \"${keyword}\"`, 'SCHOOL_NOT_FOUND');\n this.name = 'SchoolNotFoundError';\n }\n}\n\nexport class AmbiguousSchoolError extends KampusError {\n constructor(\n public readonly keyword: string,\n public readonly matches: Array<Pick<SchoolRef, 'name' | 'region' | 'schoolType'>>,\n ) {\n const list = matches\n .map((match) => {\n const extras = [match.region, match.schoolType].filter(Boolean).join(', ');\n return extras ? `${match.name} (${extras})` : match.name;\n })\n .join(', ');\n\n super(`Multiple schools matched \"${keyword}\": ${list}`, 'AMBIGUOUS_SCHOOL');\n this.name = 'AmbiguousSchoolError';\n }\n}\n\nexport class TeacherNotFoundError extends KampusError {\n constructor(teacherName: string, schoolName: string) {\n super(`Teacher \"${teacherName}\" was not found in \"${schoolName}\"`, 'TEACHER_NOT_FOUND');\n this.name = 'TeacherNotFoundError';\n }\n}\n\nexport class MealsUnavailableError extends KampusError {\n constructor(message = 'Meals are unavailable for the requested school/date.') {\n super(message, 'MEALS_UNAVAILABLE');\n this.name = 'MealsUnavailableError';\n }\n}\n\nexport class TimetableUnavailableError extends KampusError {\n constructor(message = 'Timetable data is unavailable for the requested school/date.') {\n super(message, 'TIMETABLE_UNAVAILABLE');\n this.name = 'TimetableUnavailableError';\n }\n}\n\nexport class InvalidInputError extends KampusError {\n constructor(message: string) {\n super(message, 'INVALID_INPUT');\n this.name = 'InvalidInputError';\n }\n}\n\nexport class ProviderUnavailableError extends KampusError {\n constructor(providerName: string, cause?: unknown, message?: string) {\n super(message ?? `Provider unavailable: ${providerName}`, 'PROVIDER_UNAVAILABLE', cause);\n this.name = 'ProviderUnavailableError';\n }\n}\n", "import { spawnSync } from 'node:child_process';\n\nexport type KampusSecretStorage = 'plain-text' | 'windows-dpapi';\n\nexport interface KampusProtectedSecret {\n storage: KampusSecretStorage;\n value: string;\n warning?: string;\n}\n\nexport interface KampusResolvedSecret {\n storage: KampusSecretStorage;\n value?: string;\n readable: boolean;\n error?: string;\n}\n\nexport function getPreferredSecretStorage(platform: NodeJS.Platform = process.platform): KampusSecretStorage {\n return platform === 'win32' ? 'windows-dpapi' : 'plain-text';\n}\n\nexport function protectSecret(\n secret: string,\n options?: {\n storage?: KampusSecretStorage;\n platform?: NodeJS.Platform;\n },\n): KampusProtectedSecret {\n const trimmed = secret.trim();\n const preferredStorage = options?.storage ?? getPreferredSecretStorage(options?.platform);\n if (!trimmed) {\n return {\n storage: preferredStorage,\n value: '',\n };\n }\n\n if (preferredStorage !== 'windows-dpapi') {\n return {\n storage: 'plain-text',\n value: trimmed,\n };\n }\n\n if ((options?.platform ?? process.platform) !== 'win32') {\n return {\n storage: 'plain-text',\n value: trimmed,\n warning: 'windows-dpapi storage is only available on Windows. Falling back to plain-text config storage.',\n };\n }\n\n const result = runPowerShell(\n `$secure = ConvertTo-SecureString -String ${quotePowerShellLiteral(trimmed)} -AsPlainText -Force; ConvertFrom-SecureString -SecureString $secure`,\n );\n if (!result.ok || !result.stdout) {\n return {\n storage: 'plain-text',\n value: trimmed,\n warning:\n result.error ??\n 'Windows DPAPI protection failed. Falling back to plain-text config storage for this key.',\n };\n }\n\n return {\n storage: 'windows-dpapi',\n value: result.stdout,\n };\n}\n\nexport function resolveSecret(\n value: string | undefined,\n storage: KampusSecretStorage | undefined,\n options?: {\n platform?: NodeJS.Platform;\n },\n): KampusResolvedSecret {\n const normalizedStorage = storage ?? 'plain-text';\n const trimmed = value?.trim();\n if (!trimmed) {\n return {\n storage: normalizedStorage,\n readable: false,\n };\n }\n\n if (normalizedStorage !== 'windows-dpapi') {\n return {\n storage: 'plain-text',\n value: trimmed,\n readable: true,\n };\n }\n\n if ((options?.platform ?? process.platform) !== 'win32') {\n return {\n storage: 'windows-dpapi',\n readable: false,\n error:\n 'This NEIS key is stored with Windows DPAPI and cannot be decrypted on the current platform. Re-enter the key in this environment or use an environment variable override.',\n };\n }\n\n const result = runPowerShell(\n `$secure = ConvertTo-SecureString ${quotePowerShellLiteral(trimmed)}; [System.Net.NetworkCredential]::new('', $secure).Password`,\n );\n if (!result.ok || !result.stdout) {\n return {\n storage: 'windows-dpapi',\n readable: false,\n error:\n result.error ??\n 'Unable to decrypt the saved Windows DPAPI NEIS key. Re-enter the key with \"kps auth login\".',\n };\n }\n\n return {\n storage: 'windows-dpapi',\n value: result.stdout,\n readable: true,\n };\n}\n\nexport function describeSecretStorage(storage: KampusSecretStorage | undefined, source: 'env' | 'config' | 'none') {\n if (source === 'env') {\n return 'env';\n }\n if (storage === 'windows-dpapi') {\n return 'windows-dpapi';\n }\n return 'local-config-plain-text';\n}\n\nfunction runPowerShell(script: string): { ok: boolean; stdout?: string; error?: string } {\n for (const command of ['powershell.exe', 'powershell', 'pwsh.exe', 'pwsh']) {\n const result = spawnSync(command, ['-NoProfile', '-NonInteractive', '-Command', script], {\n encoding: 'utf8',\n windowsHide: true,\n });\n\n if (result.error && isMissingCommandError(result.error)) {\n continue;\n }\n\n if (result.status !== 0) {\n return {\n ok: false,\n error: [result.stderr, result.stdout]\n .filter(Boolean)\n .map((value) => value.trim())\n .filter(Boolean)\n .join(' ')\n .trim(),\n };\n }\n\n return {\n ok: true,\n stdout: result.stdout.trim(),\n };\n }\n\n return {\n ok: false,\n error: 'PowerShell is not available in this environment.',\n };\n}\n\nfunction quotePowerShellLiteral(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction isMissingCommandError(error: unknown): boolean {\n if (!error || typeof error !== 'object') {\n return false;\n }\n\n const code = (error as { code?: unknown }).code;\n return code === 'ENOENT';\n}\n", "import type {\n DayTimetable,\n PeriodChange,\n PeriodItem,\n PeriodSource,\n ProviderId,\n ProviderRefs,\n SchoolRef,\n SchoolSearchResult,\n SnapshotDiff,\n TeacherPeriodItem,\n WeekTimetable,\n} from './types.js';\nimport { UNKNOWN_SUBJECT, WEEKDAY_NAMES } from './types.js';\n\nconst REGION_SUFFIX_PATTERN =\n /(\uD2B9\uBCC4\uC790\uCE58\uC2DC|\uD2B9\uBCC4\uC790\uCE58\uB3C4|\uAD11\uC5ED\uC2DC|\uD2B9\uBCC4\uC2DC|\uC790\uCE58\uC2DC|\uC790\uCE58\uB3C4|\uB3C4)$/u;\n\nexport function normalizePeriod(raw: {\n period: number;\n subject?: string | null;\n teacher?: string | null;\n source?: Partial<PeriodSource>;\n rawSubject?: string | null;\n rawTeacher?: string | null;\n rawCodes?: Record<string, number | string>;\n}): PeriodItem {\n const teacher = raw.teacher?.trim() || undefined;\n const subjectText = raw.subject?.trim() || '';\n\n let subject = subjectText;\n let status: PeriodItem['status'] = 'class';\n let isFreePeriod = false;\n\n if (!subjectText && teacher) {\n subject = UNKNOWN_SUBJECT;\n status = 'unknown-subject';\n } else if (!subjectText) {\n subject = '';\n status = 'free';\n isFreePeriod = true;\n }\n\n return {\n period: raw.period,\n subject,\n teacher,\n status,\n isFreePeriod,\n source: {\n provider: raw.source?.provider ?? 'unknown',\n rawSubject: raw.rawSubject ?? raw.source?.rawSubject ?? raw.subject ?? undefined,\n rawTeacher: raw.rawTeacher ?? raw.source?.rawTeacher ?? raw.teacher ?? undefined,\n rawCodes: raw.rawCodes ?? raw.source?.rawCodes,\n },\n };\n}\n\nexport function normalizeTeacherPeriod(raw: {\n period: number;\n subject?: string | null;\n grade?: number;\n classNo?: number;\n source?: Partial<PeriodSource>;\n rawSubject?: string | null;\n rawCodes?: Record<string, number | string>;\n}): TeacherPeriodItem {\n const subjectText = raw.subject?.trim() || '';\n const hasClass = Number.isInteger(raw.grade) && Number.isInteger(raw.classNo);\n\n let subject = subjectText;\n let status: TeacherPeriodItem['status'] = 'class';\n let isFreePeriod = false;\n\n if (!subjectText && hasClass) {\n subject = UNKNOWN_SUBJECT;\n status = 'unknown-subject';\n } else if (!subjectText) {\n subject = '';\n status = 'free';\n isFreePeriod = true;\n }\n\n return {\n period: raw.period,\n subject,\n grade: raw.grade,\n classNo: raw.classNo,\n classLabel: hasClass ? `${raw.grade}-${raw.classNo}` : undefined,\n status,\n isFreePeriod,\n source: {\n provider: raw.source?.provider ?? 'unknown',\n rawSubject: raw.rawSubject ?? raw.source?.rawSubject ?? raw.subject ?? undefined,\n rawCodes: raw.rawCodes ?? raw.source?.rawCodes,\n },\n };\n}\n\nexport function weekdayName(weekday: number): string {\n return WEEKDAY_NAMES[weekday] ?? `${weekday}`;\n}\n\nexport function normalizeSchoolName(value: string): string {\n return value.replace(/\\s+/g, '').toLowerCase();\n}\n\nexport function normalizeRegionName(value?: string): string | undefined {\n if (!value) {\n return undefined;\n }\n\n return value.replace(/\\s+/g, '').replace(REGION_SUFFIX_PATTERN, '');\n}\n\nexport function schoolMatches(\n left: Pick<SchoolRef, 'name' | 'region' | 'schoolType'>,\n right: Pick<SchoolRef, 'name' | 'region' | 'schoolType'>,\n): boolean {\n if (normalizeSchoolName(left.name) !== normalizeSchoolName(right.name)) {\n return false;\n }\n\n const leftRegion = normalizeRegionName(left.region);\n const rightRegion = normalizeRegionName(right.region);\n if (leftRegion && rightRegion && leftRegion !== rightRegion) {\n return false;\n }\n\n if (left.schoolType && right.schoolType && left.schoolType !== right.schoolType) {\n return false;\n }\n\n return true;\n}\n\nexport function hasProviderRef(school: SchoolRef, providerId: ProviderId): boolean {\n return school.providerRefs[providerId] != null;\n}\n\nexport function mergeProviderRefs(base: ProviderRefs, incoming: ProviderRefs): ProviderRefs {\n return {\n comcigan: incoming.comcigan ?? base.comcigan,\n neis: incoming.neis ?? base.neis,\n };\n}\n\nexport function providerIdsFromRefs(providerRefs: ProviderRefs): ProviderId[] {\n const ids: ProviderId[] = [];\n\n if (providerRefs.comcigan) {\n ids.push('comcigan');\n }\n if (providerRefs.neis) {\n ids.push('neis');\n }\n\n return ids;\n}\n\nexport function mergeSchoolRefs(\n base: SchoolRef,\n incoming: SchoolRef | SchoolSearchResult,\n): SchoolSearchResult {\n const sourceProviders = new Set<ProviderId>([\n ...providerIdsFromRefs(base.providerRefs),\n ...providerIdsFromRefs(incoming.providerRefs),\n ...('sourceProviders' in incoming ? incoming.sourceProviders : []),\n ]);\n\n return {\n name: base.name || incoming.name,\n region: base.region ?? incoming.region,\n schoolType: base.schoolType ?? incoming.schoolType,\n providerRefs: mergeProviderRefs(base.providerRefs, incoming.providerRefs),\n sourceProviders: [...sourceProviders],\n };\n}\n\nexport function mergeSchoolSearchResults(results: SchoolSearchResult[]): SchoolSearchResult[] {\n const merged: SchoolSearchResult[] = [];\n\n for (const result of results) {\n const existing = merged.find((candidate) => schoolMatches(candidate, result));\n if (!existing) {\n merged.push({\n ...result,\n providerRefs: mergeProviderRefs({}, result.providerRefs),\n sourceProviders: [...new Set(result.sourceProviders)],\n });\n continue;\n }\n\n const combined = mergeSchoolRefs(existing, result);\n Object.assign(existing, combined);\n }\n\n return merged.sort((left, right) => {\n const regionA = normalizeRegionName(left.region) ?? '';\n const regionB = normalizeRegionName(right.region) ?? '';\n return regionA.localeCompare(regionB, 'ko') || left.name.localeCompare(right.name, 'ko');\n });\n}\n\nexport function diffSnapshots(a: WeekTimetable, b: WeekTimetable): SnapshotDiff {\n const changes: PeriodChange[] = [];\n\n for (const dayA of a.days) {\n const dayB = b.days.find((candidate) => candidate.weekday === dayA.weekday);\n if (!dayB) {\n continue;\n }\n\n for (const periodA of dayA.periods) {\n const periodB = dayB.periods.find((candidate) => candidate.period === periodA.period);\n if (!periodB) {\n continue;\n }\n\n if (\n periodA.subject !== periodB.subject ||\n periodA.teacher !== periodB.teacher ||\n periodA.status !== periodB.status\n ) {\n changes.push({\n weekday: dayA.weekday,\n weekdayName: dayA.weekdayName,\n period: periodA.period,\n before: {\n subject: periodA.subject,\n teacher: periodA.teacher,\n status: periodA.status,\n },\n after: {\n subject: periodB.subject,\n teacher: periodB.teacher,\n status: periodB.status,\n },\n });\n }\n }\n }\n\n return {\n school: a.school,\n grade: a.grade,\n classNo: a.classNo,\n changes,\n };\n}\n\nexport function extractDay(week: WeekTimetable, weekday: number): DayTimetable | undefined {\n return week.days.find((day) => day.weekday === weekday);\n}\n\nexport function todayWeekday(now?: Date): number {\n const date = now ?? new Date();\n return date.getDay() === 0 ? 7 : date.getDay();\n}\n\nexport function formatDate(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\nexport function getMonday(date: Date): Date {\n const monday = new Date(date);\n const weekday = monday.getDay();\n const offset = weekday === 0 ? -6 : 1 - weekday;\n monday.setDate(monday.getDate() + offset);\n monday.setHours(0, 0, 0, 0);\n return monday;\n}\n", "export interface KampusProjectInfo {\n name: string;\n description: string;\n repositoryUrl: string;\n homepageUrl: string;\n}\n\nexport interface KampusDeveloperInfo {\n name: string;\n email?: string;\n url?: string;\n}\n\nexport const KAMPUS_PROJECT_INFO: KampusProjectInfo = {\n name: 'Kampus',\n description: 'Korean Campus CLI - school information toolkit for Korea',\n repositoryUrl: 'https://github.com/4ndrxxs/Kampus',\n homepageUrl: 'https://github.com/4ndrxxs/Kampus#readme',\n};\n\nexport const KAMPUS_DEVELOPER_INFO: KampusDeveloperInfo = {\n name: 'Juwon Seo',\n email: 'contact@seojuwon.com',\n url: 'https://github.com/4ndrxxs',\n};\n", "import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { InvalidInputError } from './errors.js';\nimport { normalizeRegionName, normalizeSchoolName } from './normalize.js';\nimport {\n getPreferredSecretStorage,\n protectSecret,\n resolveSecret,\n type KampusSecretStorage,\n} from './secret.js';\nimport {\n KAMPUS_DEVELOPER_INFO,\n KAMPUS_PROJECT_INFO,\n type KampusDeveloperInfo,\n type KampusProjectInfo,\n} from './metadata.js';\nimport type { AccessMode, ProviderRefs, SchoolRef } from './types.js';\n\nexport interface KampusCachePolicy {\n datasetTtlMinutes?: number;\n staleIfErrorHours?: number;\n maxEntries?: number;\n}\n\nexport interface KampusNeisApiKeyStatus {\n checkedAt?: string;\n ok?: boolean;\n accessMode?: AccessMode;\n message?: string;\n source?: 'env' | 'config';\n}\n\nexport interface KampusConfig {\n neisApiKey?: string;\n neisApiKeyStoredValue?: string;\n neisApiKeyStorage?: KampusSecretStorage;\n neisApiKeyReadable?: boolean;\n neisApiKeyError?: string;\n neisApiKeyStatus?: KampusNeisApiKeyStatus;\n defaultSchool?: KampusStoredSchool;\n recentSchools?: KampusStoredSchool[];\n profiles?: Record<string, KampusProfile>;\n activeProfile?: string;\n cachePolicy?: KampusCachePolicy;\n}\n\nexport interface KampusStoredSchool extends SchoolRef {\n lastUsedAt?: string;\n}\n\nexport interface KampusProfile {\n name: string;\n school?: KampusStoredSchool;\n grade?: number;\n classNo?: number;\n teacherName?: string;\n notes?: string;\n updatedAt?: string;\n}\n\nexport interface KampusProfileInput {\n name: string;\n school?: SchoolRef;\n grade?: number;\n classNo?: number;\n teacherName?: string;\n notes?: string;\n updatedAt?: string;\n}\n\nexport interface KampusConfigOptions {\n configPath?: string;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface KampusConfigStatus {\n configPath: string;\n neisApiKeyConfigured: boolean;\n neisApiKeyStored: boolean;\n neisApiKeyReadable: boolean;\n neisApiKeySource: 'env' | 'config' | 'none';\n neisApiKeyStorage?: KampusSecretStorage;\n neisApiKeyPreview?: string;\n neisApiKeyError?: string;\n neisApiKeyStatus?: KampusNeisApiKeyStatus;\n projectInfo?: KampusProjectInfo;\n developerInfo?: KampusDeveloperInfo;\n defaultSchool?: KampusStoredSchool;\n recentSchools: KampusStoredSchool[];\n activeProfile?: KampusProfile;\n profiles: KampusProfile[];\n cachePolicy: Required<KampusCachePolicy>;\n}\n\nconst KAMPUS_DIR = 'Kampus';\nconst CONFIG_FILE = 'config.json';\nconst UTF8_BOM = '\\uFEFF';\n\nexport const DEFAULT_CACHE_POLICY: Required<KampusCachePolicy> = {\n datasetTtlMinutes: 15,\n staleIfErrorHours: 24,\n maxEntries: 250,\n};\n\nexport function resolveKampusConfigPath(env: NodeJS.ProcessEnv = process.env): string {\n const appData = env.APPDATA?.trim();\n if (appData) {\n return join(appData, KAMPUS_DIR, CONFIG_FILE);\n }\n\n return join(homedir(), '.kampus', CONFIG_FILE);\n}\n\nexport function resolveKampusDataDir(env: NodeJS.ProcessEnv = process.env): string {\n return dirname(resolveKampusConfigPath(env));\n}\n\nexport function loadKampusConfig(options?: KampusConfigOptions): KampusConfig {\n const configPath = options?.configPath ?? resolveKampusConfigPath(options?.env);\n if (!existsSync(configPath)) {\n return {};\n }\n\n let raw: string;\n try {\n raw = readFileSync(configPath, 'utf8');\n } catch (error) {\n throw new InvalidInputError(\n `Unable to read Kampus config at \"${configPath}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!raw.trim()) {\n return {};\n }\n\n raw = stripUtf8Bom(raw);\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new InvalidInputError(\n `Kampus config at \"${configPath}\" is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new InvalidInputError(`Kampus config at \"${configPath}\" must be a JSON object.`);\n }\n\n const config = parsed as {\n neisApiKey?: unknown;\n neisApiKeyStorage?: unknown;\n neisApiKeyStatus?: unknown;\n defaultSchool?: unknown;\n recentSchools?: unknown;\n profiles?: unknown;\n activeProfile?: unknown;\n cachePolicy?: unknown;\n };\n const rawNeisApiKey = typeof config.neisApiKey === 'string' ? config.neisApiKey.trim() : undefined;\n const neisApiKeyStorage = normalizeSecretStorage(config.neisApiKeyStorage) ?? (rawNeisApiKey ? 'plain-text' : undefined);\n const resolvedNeisApiKey = resolveSecret(rawNeisApiKey, neisApiKeyStorage);\n const profiles = normalizeProfiles(config.profiles);\n const activeProfileKey = normalizeProfileKey(\n typeof config.activeProfile === 'string' ? config.activeProfile : undefined,\n );\n\n return {\n neisApiKey: resolvedNeisApiKey.value,\n neisApiKeyStoredValue: rawNeisApiKey || undefined,\n neisApiKeyStorage,\n neisApiKeyReadable: resolvedNeisApiKey.readable,\n neisApiKeyError: resolvedNeisApiKey.error,\n neisApiKeyStatus: normalizeNeisApiKeyStatus(config.neisApiKeyStatus),\n defaultSchool: normalizeStoredSchool(config.defaultSchool),\n recentSchools: normalizeStoredSchools(config.recentSchools),\n profiles,\n activeProfile: activeProfileKey && profiles?.[activeProfileKey] ? activeProfileKey : undefined,\n cachePolicy: normalizeCachePolicy(config.cachePolicy),\n };\n}\n\nexport function saveKampusConfig(config: KampusConfig, options?: KampusConfigOptions): KampusConfig {\n const configPath = options?.configPath ?? resolveKampusConfigPath(options?.env);\n mkdirSync(dirname(configPath), { recursive: true });\n\n const normalized = normalizeConfig(config);\n writeFileSync(configPath, `${UTF8_BOM}${JSON.stringify(toPersistedConfig(normalized), null, 2)}\\n`, 'utf8');\n return loadKampusConfig(options);\n}\n\nexport function resolveNeisApiKey(options?: KampusConfigOptions): string | undefined {\n const envKey = options?.env?.NEIS_API_KEY?.trim() ?? process.env.NEIS_API_KEY?.trim();\n if (envKey) {\n return envKey;\n }\n\n return loadKampusConfig(options).neisApiKey;\n}\n\nexport function getKampusConfigStatus(options?: KampusConfigOptions): KampusConfigStatus {\n const configPath = options?.configPath ?? resolveKampusConfigPath(options?.env);\n const config = loadKampusConfig(options);\n const envKey = options?.env?.NEIS_API_KEY?.trim() ?? process.env.NEIS_API_KEY?.trim();\n const stored = Boolean(config.neisApiKeyStoredValue || config.neisApiKey);\n const readable = Boolean(config.neisApiKey || envKey);\n const keyStatus = envKey\n ? {\n ...(config.neisApiKeyStatus ?? {}),\n source: 'env' as const,\n }\n : config.neisApiKeyStatus;\n\n if (envKey) {\n return {\n configPath,\n neisApiKeyConfigured: true,\n neisApiKeyStored: stored,\n neisApiKeyReadable: true,\n neisApiKeySource: 'env',\n neisApiKeyStorage: config.neisApiKeyStorage,\n neisApiKeyPreview: maskSecret(envKey),\n neisApiKeyError: config.neisApiKeyError,\n neisApiKeyStatus: keyStatus,\n projectInfo: KAMPUS_PROJECT_INFO,\n developerInfo: KAMPUS_DEVELOPER_INFO,\n defaultSchool: config.defaultSchool,\n recentSchools: config.recentSchools ?? [],\n activeProfile: getActiveProfile(config),\n profiles: listProfiles(config),\n cachePolicy: resolveCachePolicy(config),\n };\n }\n\n if (config.neisApiKey) {\n return {\n configPath,\n neisApiKeyConfigured: true,\n neisApiKeyStored: stored,\n neisApiKeyReadable: true,\n neisApiKeySource: 'config',\n neisApiKeyStorage: config.neisApiKeyStorage,\n neisApiKeyPreview: maskSecret(config.neisApiKey),\n neisApiKeyError: config.neisApiKeyError,\n neisApiKeyStatus: keyStatus,\n projectInfo: KAMPUS_PROJECT_INFO,\n developerInfo: KAMPUS_DEVELOPER_INFO,\n defaultSchool: config.defaultSchool,\n recentSchools: config.recentSchools ?? [],\n activeProfile: getActiveProfile(config),\n profiles: listProfiles(config),\n cachePolicy: resolveCachePolicy(config),\n };\n }\n\n return {\n configPath,\n neisApiKeyConfigured: false,\n neisApiKeyStored: stored,\n neisApiKeyReadable: readable,\n neisApiKeySource: stored ? 'config' : 'none',\n neisApiKeyStorage: config.neisApiKeyStorage,\n neisApiKeyError: config.neisApiKeyError,\n neisApiKeyStatus: keyStatus,\n projectInfo: KAMPUS_PROJECT_INFO,\n developerInfo: KAMPUS_DEVELOPER_INFO,\n defaultSchool: config.defaultSchool,\n recentSchools: config.recentSchools ?? [],\n activeProfile: getActiveProfile(config),\n profiles: listProfiles(config),\n cachePolicy: resolveCachePolicy(config),\n };\n}\n\nexport function toStoredSchool(school: SchoolRef, lastUsedAt = new Date().toISOString()): KampusStoredSchool {\n return {\n name: school.name.trim(),\n region: school.region?.trim() || undefined,\n schoolType: school.schoolType?.trim() || undefined,\n providerRefs: normalizeProviderRefs(school.providerRefs),\n lastUsedAt,\n };\n}\n\nexport function rememberRecentSchool(\n config: KampusConfig,\n school: SchoolRef,\n options?: { now?: string; limit?: number },\n): KampusConfig {\n const stored = toStoredSchool(school, options?.now);\n const recent = [stored, ...(config.recentSchools ?? [])].filter((candidate, index, values) => {\n return values.findIndex((value) => schoolConfigKey(value) === schoolConfigKey(candidate)) === index;\n });\n\n return {\n ...config,\n recentSchools: recent.slice(0, options?.limit ?? 10),\n };\n}\n\nexport function setDefaultSchool(\n config: KampusConfig,\n school: SchoolRef,\n options?: { now?: string; recentLimit?: number },\n): KampusConfig {\n const stored = toStoredSchool(school, options?.now);\n return {\n ...rememberRecentSchool(config, school, {\n now: options?.now,\n limit: options?.recentLimit,\n }),\n defaultSchool: stored,\n };\n}\n\nexport function clearDefaultSchool(config: KampusConfig): KampusConfig {\n return {\n ...config,\n defaultSchool: undefined,\n };\n}\n\nexport function removeRecentSchool(\n config: KampusConfig,\n school: Pick<SchoolRef, 'name' | 'region'>,\n): KampusConfig {\n const recentSchools = (config.recentSchools ?? []).filter((candidate) => {\n return schoolConfigKey(candidate) !== schoolConfigKey({\n name: school.name,\n region: school.region,\n });\n });\n\n return {\n ...config,\n recentSchools: recentSchools.length ? recentSchools : undefined,\n };\n}\n\nexport function setNeisApiKeyStatus(\n config: KampusConfig,\n status: KampusNeisApiKeyStatus | undefined,\n): KampusConfig {\n return {\n ...config,\n neisApiKeyStatus: normalizeNeisApiKeyStatus(status),\n };\n}\n\nexport function getActiveProfile(config: KampusConfig = loadKampusConfig()): KampusProfile | undefined {\n const activeKey = normalizeProfileKey(config.activeProfile);\n if (!activeKey) {\n return undefined;\n }\n\n return config.profiles?.[activeKey];\n}\n\nexport function listProfiles(config: KampusConfig = loadKampusConfig()): KampusProfile[] {\n return Object.values(config.profiles ?? {}).sort((left, right) => left.name.localeCompare(right.name));\n}\n\nexport function upsertProfile(config: KampusConfig, profile: KampusProfileInput): KampusConfig {\n const normalized = normalizeProfileInput({\n ...profile,\n updatedAt: profile.updatedAt ?? new Date().toISOString(),\n });\n if (!normalized) {\n throw new InvalidInputError('Profile name is required.');\n }\n const profileKey = normalizeProfileKey(normalized.name);\n if (!profileKey) {\n throw new InvalidInputError('Profile name is required.');\n }\n\n return {\n ...config,\n profiles: {\n ...(config.profiles ?? {}),\n [profileKey]: normalized,\n },\n };\n}\n\nexport function removeProfile(config: KampusConfig, name: string): KampusConfig {\n const profileKey = normalizeProfileKey(name);\n if (!profileKey || !config.profiles?.[profileKey]) {\n return config;\n }\n\n const nextProfiles = { ...config.profiles };\n delete nextProfiles[profileKey];\n\n return {\n ...config,\n profiles: Object.keys(nextProfiles).length ? nextProfiles : undefined,\n activeProfile: config.activeProfile === profileKey ? undefined : config.activeProfile,\n };\n}\n\nexport function setActiveProfile(config: KampusConfig, name: string | undefined): KampusConfig {\n const profileKey = normalizeProfileKey(name);\n if (!profileKey) {\n return {\n ...config,\n activeProfile: undefined,\n };\n }\n if (!config.profiles?.[profileKey]) {\n throw new InvalidInputError(`Profile \"${name}\" does not exist.`);\n }\n\n return {\n ...config,\n activeProfile: profileKey,\n };\n}\n\nexport function resolveCachePolicy(config: KampusConfig = loadKampusConfig()): Required<KampusCachePolicy> {\n return {\n ...DEFAULT_CACHE_POLICY,\n ...(config.cachePolicy ?? {}),\n };\n}\n\nexport function maskSecret(secret: string): string {\n const trimmed = secret.trim();\n if (!trimmed) {\n return '';\n }\n if (trimmed.length <= 8) {\n return `${trimmed.slice(0, 2)}***${trimmed.slice(-2)}`;\n }\n return `${trimmed.slice(0, 4)}...${trimmed.slice(-4)}`;\n}\n\nfunction normalizeConfig(config: KampusConfig): KampusConfig {\n const profiles = normalizeProfiles(config.profiles);\n const activeProfile = normalizeProfileKey(config.activeProfile);\n const neisApiKey = config.neisApiKey?.trim() || undefined;\n const neisApiKeyStoredValue = config.neisApiKeyStoredValue?.trim() || undefined;\n const neisApiKeyStorage =\n normalizeSecretStorage(config.neisApiKeyStorage) ??\n (neisApiKey || neisApiKeyStoredValue ? getPreferredSecretStorage() : undefined);\n\n return {\n neisApiKey,\n neisApiKeyStoredValue,\n neisApiKeyStorage,\n neisApiKeyReadable: neisApiKey ? true : Boolean(config.neisApiKeyReadable),\n neisApiKeyError: typeof config.neisApiKeyError === 'string' ? config.neisApiKeyError.trim() || undefined : undefined,\n neisApiKeyStatus: normalizeNeisApiKeyStatus(config.neisApiKeyStatus),\n defaultSchool: normalizeStoredSchool(config.defaultSchool),\n recentSchools: normalizeStoredSchools(config.recentSchools),\n profiles,\n activeProfile: activeProfile && profiles?.[activeProfile] ? activeProfile : undefined,\n cachePolicy: normalizeCachePolicy(config.cachePolicy),\n };\n}\n\nfunction toPersistedConfig(config: KampusConfig) {\n const persistedKey = persistNeisApiKey(config);\n\n return {\n neisApiKey: persistedKey?.value,\n neisApiKeyStorage: persistedKey?.storage,\n neisApiKeyStatus: normalizeNeisApiKeyStatus(config.neisApiKeyStatus),\n defaultSchool: normalizeStoredSchool(config.defaultSchool),\n recentSchools: normalizeStoredSchools(config.recentSchools),\n profiles: normalizeProfiles(config.profiles),\n activeProfile: normalizeProfileKey(config.activeProfile),\n cachePolicy: normalizeCachePolicy(config.cachePolicy),\n };\n}\n\nfunction normalizeStoredSchools(value: unknown): KampusStoredSchool[] | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const normalized = value\n .map((entry) => normalizeStoredSchool(entry))\n .filter((entry): entry is KampusStoredSchool => entry != null);\n\n if (!normalized.length) {\n return undefined;\n }\n\n return normalized.filter((candidate, index, values) => {\n return values.findIndex((value) => schoolConfigKey(value) === schoolConfigKey(candidate)) === index;\n });\n}\n\nfunction persistNeisApiKey(\n config: KampusConfig,\n): { value: string; storage: KampusSecretStorage } | undefined {\n if (config.neisApiKey) {\n const protectedSecret = protectSecret(config.neisApiKey, {\n storage: config.neisApiKeyStorage,\n });\n return {\n value: protectedSecret.value,\n storage: protectedSecret.storage,\n };\n }\n\n if (config.neisApiKeyStoredValue && config.neisApiKeyStorage) {\n return {\n value: config.neisApiKeyStoredValue,\n storage: config.neisApiKeyStorage,\n };\n }\n\n return undefined;\n}\n\nfunction normalizeStoredSchool(value: unknown): KampusStoredSchool | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const raw = value as {\n name?: unknown;\n region?: unknown;\n schoolType?: unknown;\n providerRefs?: unknown;\n lastUsedAt?: unknown;\n };\n const name = typeof raw.name === 'string' ? raw.name.trim() : '';\n if (!name) {\n return undefined;\n }\n\n return {\n name,\n region: typeof raw.region === 'string' ? raw.region.trim() || undefined : undefined,\n schoolType: typeof raw.schoolType === 'string' ? raw.schoolType.trim() || undefined : undefined,\n providerRefs: normalizeProviderRefs(raw.providerRefs),\n lastUsedAt: typeof raw.lastUsedAt === 'string' ? raw.lastUsedAt.trim() || undefined : undefined,\n };\n}\n\nfunction normalizeProviderRefs(value: unknown): ProviderRefs {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n\n const raw = value as {\n comcigan?: { schoolCode?: unknown };\n neis?: { officeCode?: unknown; schoolCode?: unknown };\n };\n\n return {\n comcigan:\n raw.comcigan && Number.isFinite(Number(raw.comcigan.schoolCode))\n ? {\n schoolCode: Number(raw.comcigan.schoolCode),\n }\n : undefined,\n neis:\n raw.neis &&\n typeof raw.neis.officeCode === 'string' &&\n raw.neis.officeCode.trim() &&\n typeof raw.neis.schoolCode === 'string' &&\n raw.neis.schoolCode.trim()\n ? {\n officeCode: raw.neis.officeCode.trim(),\n schoolCode: raw.neis.schoolCode.trim(),\n }\n : undefined,\n };\n}\n\nfunction schoolConfigKey(school: Pick<KampusStoredSchool, 'name' | 'region'>): string {\n return `${normalizeSchoolName(school.name)}::${normalizeRegionName(school.region) ?? ''}`;\n}\n\nfunction stripUtf8Bom(value: string): string {\n return value.startsWith(UTF8_BOM) ? value.slice(UTF8_BOM.length) : value;\n}\n\nfunction normalizeNeisApiKeyStatus(value: unknown): KampusNeisApiKeyStatus | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const raw = value as {\n checkedAt?: unknown;\n ok?: unknown;\n accessMode?: unknown;\n message?: unknown;\n source?: unknown;\n };\n\n const checkedAt = typeof raw.checkedAt === 'string' ? raw.checkedAt.trim() || undefined : undefined;\n const accessMode = isAccessMode(raw.accessMode) ? raw.accessMode : undefined;\n const message = typeof raw.message === 'string' ? raw.message.trim() || undefined : undefined;\n const source = raw.source === 'env' || raw.source === 'config' ? raw.source : undefined;\n const ok = typeof raw.ok === 'boolean' ? raw.ok : undefined;\n\n if (!checkedAt && ok == null && !accessMode && !message && !source) {\n return undefined;\n }\n\n return {\n checkedAt,\n ok,\n accessMode,\n message,\n source,\n };\n}\n\nfunction normalizeProfiles(value: unknown): Record<string, KampusProfile> | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const profiles = Object.entries(value as Record<string, unknown>)\n .map(([, entry]) => normalizeProfileInput(entry))\n .filter((entry): entry is KampusProfile => entry != null);\n\n if (!profiles.length) {\n return undefined;\n }\n\n return Object.fromEntries(\n profiles.map((profile) => [normalizeProfileKey(profile.name)!, profile]),\n );\n}\n\nfunction normalizeProfileInput(value: unknown): KampusProfile | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const raw = value as {\n name?: unknown;\n school?: unknown;\n grade?: unknown;\n classNo?: unknown;\n teacherName?: unknown;\n notes?: unknown;\n updatedAt?: unknown;\n };\n\n const name = typeof raw.name === 'string' ? raw.name.trim() : '';\n if (!name) {\n return undefined;\n }\n\n return {\n name,\n school: normalizeStoredSchool(raw.school),\n grade: normalizePositiveInteger(raw.grade),\n classNo: normalizePositiveInteger(raw.classNo),\n teacherName: typeof raw.teacherName === 'string' ? raw.teacherName.trim() || undefined : undefined,\n notes: typeof raw.notes === 'string' ? raw.notes.trim() || undefined : undefined,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt.trim() || undefined : undefined,\n };\n}\n\nfunction normalizeProfileKey(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = value.trim().toLowerCase();\n return normalized || undefined;\n}\n\nfunction normalizePositiveInteger(value: unknown): number | undefined {\n const parsed = typeof value === 'string' ? Number.parseInt(value, 10) : Number(value);\n if (!Number.isInteger(parsed) || parsed < 1) {\n return undefined;\n }\n return parsed;\n}\n\nfunction normalizeCachePolicy(value: unknown): KampusCachePolicy | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const raw = value as {\n datasetTtlMinutes?: unknown;\n staleIfErrorHours?: unknown;\n maxEntries?: unknown;\n };\n\n const normalized: KampusCachePolicy = {\n datasetTtlMinutes: normalizePositiveInteger(raw.datasetTtlMinutes),\n staleIfErrorHours: normalizePositiveInteger(raw.staleIfErrorHours),\n maxEntries: normalizePositiveInteger(raw.maxEntries),\n };\n\n if (\n normalized.datasetTtlMinutes == null &&\n normalized.staleIfErrorHours == null &&\n normalized.maxEntries == null\n ) {\n return undefined;\n }\n\n return normalized;\n}\n\nfunction normalizeSecretStorage(value: unknown): KampusSecretStorage | undefined {\n return value === 'plain-text' || value === 'windows-dpapi' ? value : undefined;\n}\n\nfunction isAccessMode(value: unknown): value is AccessMode {\n return value === 'official-full' || value === 'official-limited' || value === 'unofficial';\n}\n\n", "import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { InvalidInputError } from './errors.js';\n\nexport interface KampusCacheEntry<T = unknown> {\n key: string;\n value: T;\n storedAt: string;\n expiresAt?: string;\n staleUntil?: string;\n hits?: number;\n lastAccessedAt?: string;\n meta?: Record<string, unknown>;\n}\n\nexport interface KampusCacheFile {\n entries: Record<string, KampusCacheEntry>;\n}\n\nexport interface KampusCacheOptions {\n cachePath?: string;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface KampusCacheReadResult<T = unknown> {\n state: 'missing' | 'fresh' | 'stale' | 'expired';\n entry?: KampusCacheEntry<T>;\n}\n\nconst KAMPUS_DIR = 'Kampus';\nconst CACHE_FILE = 'cache.json';\nconst UTF8_BOM = '\\uFEFF';\n\nexport function resolveKampusCachePath(env: NodeJS.ProcessEnv = process.env): string {\n const appData = env.APPDATA?.trim();\n if (appData) {\n return join(appData, KAMPUS_DIR, CACHE_FILE);\n }\n\n return join(homedir(), '.kampus', CACHE_FILE);\n}\n\nexport function loadKampusCache(options?: KampusCacheOptions): KampusCacheFile {\n const cachePath = options?.cachePath ?? resolveKampusCachePath(options?.env);\n if (!existsSync(cachePath)) {\n return { entries: {} };\n }\n\n let raw: string;\n try {\n raw = readFileSync(cachePath, 'utf8');\n } catch (error) {\n throw new InvalidInputError(\n `Unable to read Kampus cache at \"${cachePath}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!raw.trim()) {\n return { entries: {} };\n }\n\n raw = raw.startsWith(UTF8_BOM) ? raw.slice(UTF8_BOM.length) : raw;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new InvalidInputError(\n `Kampus cache at \"${cachePath}\" is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new InvalidInputError(`Kampus cache at \"${cachePath}\" must be a JSON object.`);\n }\n\n const rawEntries = (parsed as { entries?: unknown }).entries;\n if (!rawEntries || typeof rawEntries !== 'object' || Array.isArray(rawEntries)) {\n return { entries: {} };\n }\n\n return {\n entries: Object.fromEntries(\n Object.entries(rawEntries as Record<string, unknown>)\n .map(([key, value]) => [key, normalizeCacheEntry(key, value)])\n .filter((entry): entry is [string, KampusCacheEntry] => entry[1] != null),\n ),\n };\n}\n\nexport function saveKampusCache(cache: KampusCacheFile, options?: KampusCacheOptions): KampusCacheFile {\n const cachePath = options?.cachePath ?? resolveKampusCachePath(options?.env);\n mkdirSync(dirname(cachePath), { recursive: true });\n\n const normalized: KampusCacheFile = {\n entries: Object.fromEntries(\n Object.entries(cache.entries ?? {})\n .map(([key, value]) => [key, normalizeCacheEntry(key, value)])\n .filter((entry): entry is [string, KampusCacheEntry] => entry[1] != null),\n ),\n };\n\n writeFileSync(cachePath, `${UTF8_BOM}${JSON.stringify(normalized, null, 2)}\\n`, 'utf8');\n return normalized;\n}\n\nexport function readKampusCacheEntry<T = unknown>(\n key: string,\n options?: KampusCacheOptions & { now?: Date },\n): KampusCacheReadResult<T> {\n const cache = loadKampusCache(options);\n const entry = cache.entries[key] as KampusCacheEntry<T> | undefined;\n if (!entry) {\n return { state: 'missing' };\n }\n\n const now = options?.now ?? new Date();\n const expiresAt = entry.expiresAt ? new Date(entry.expiresAt) : undefined;\n const staleUntil = entry.staleUntil ? new Date(entry.staleUntil) : undefined;\n\n if (expiresAt && expiresAt.getTime() > now.getTime()) {\n return { state: 'fresh', entry };\n }\n\n if (staleUntil && staleUntil.getTime() > now.getTime()) {\n return { state: 'stale', entry };\n }\n\n return { state: 'expired', entry };\n}\n\nexport function writeKampusCacheEntry<T = unknown>(\n entry: KampusCacheEntry<T>,\n options?: KampusCacheOptions & { maxEntries?: number },\n): KampusCacheEntry<T> {\n const cache = loadKampusCache(options);\n const normalizedEntry = normalizeCacheEntry(entry.key, entry) as KampusCacheEntry<T>;\n cache.entries[entry.key] = normalizedEntry;\n\n const keysByFreshness = Object.entries(cache.entries)\n .sort((left, right) => {\n const leftTime = Date.parse(left[1].lastAccessedAt ?? left[1].storedAt ?? '') || 0;\n const rightTime = Date.parse(right[1].lastAccessedAt ?? right[1].storedAt ?? '') || 0;\n return rightTime - leftTime;\n })\n .map(([key]) => key);\n\n const maxEntries = Math.max(1, options?.maxEntries ?? Number.MAX_SAFE_INTEGER);\n for (const key of keysByFreshness.slice(maxEntries)) {\n delete cache.entries[key];\n }\n\n saveKampusCache(cache, options);\n return normalizedEntry;\n}\n\nexport function touchKampusCacheEntry(\n key: string,\n options?: KampusCacheOptions & { now?: Date },\n): KampusCacheEntry | undefined {\n const cache = loadKampusCache(options);\n const entry = cache.entries[key];\n if (!entry) {\n return undefined;\n }\n\n entry.hits = (entry.hits ?? 0) + 1;\n entry.lastAccessedAt = (options?.now ?? new Date()).toISOString();\n saveKampusCache(cache, options);\n return entry;\n}\n\nfunction normalizeCacheEntry(key: string, value: unknown): KampusCacheEntry | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const raw = value as {\n value?: unknown;\n storedAt?: unknown;\n expiresAt?: unknown;\n staleUntil?: unknown;\n hits?: unknown;\n lastAccessedAt?: unknown;\n meta?: unknown;\n };\n\n return {\n key,\n value: raw.value,\n storedAt:\n typeof raw.storedAt === 'string' && raw.storedAt.trim()\n ? raw.storedAt.trim()\n : new Date().toISOString(),\n expiresAt: typeof raw.expiresAt === 'string' ? raw.expiresAt.trim() || undefined : undefined,\n staleUntil: typeof raw.staleUntil === 'string' ? raw.staleUntil.trim() || undefined : undefined,\n hits: Number.isInteger(raw.hits) ? Number(raw.hits) : undefined,\n lastAccessedAt:\n typeof raw.lastAccessedAt === 'string' ? raw.lastAccessedAt.trim() || undefined : undefined,\n meta:\n raw.meta && typeof raw.meta === 'object' && !Array.isArray(raw.meta)\n ? (raw.meta as Record<string, unknown>)\n : undefined,\n };\n}\n", "import type {\n ClassTimeSlot,\n DailyMeals,\n DayTimetable,\n KampusProvider,\n PeriodItem,\n ProviderCapability,\n ProviderId,\n SchoolInfo,\n SchoolRef,\n SchoolSearchResult,\n SnapshotDiff,\n TeacherInfo,\n TeacherTimetable,\n WeekTimetable,\n WeeklyMeals,\n} from './types.js';\nimport {\n AmbiguousSchoolError,\n InvalidInputError,\n ProviderUnavailableError,\n SchoolNotFoundError,\n} from './errors.js';\nimport {\n diffSnapshots,\n extractDay,\n formatDate,\n getMonday,\n hasProviderRef,\n mergeSchoolRefs,\n mergeSchoolSearchResults,\n normalizeRegionName,\n normalizeSchoolName,\n schoolMatches,\n todayWeekday,\n} from './normalize.js';\n\nexport interface KampusClientOptions {\n providers: KampusProvider[];\n}\n\nconst PROVIDER_PREFERENCES: Partial<Record<ProviderCapability, string[]>> = {\n schoolInfo: ['neis'],\n studentTimetable: ['comcigan'],\n teacherTimetable: ['comcigan'],\n teacherInfo: ['comcigan'],\n classTimes: ['comcigan'],\n meals: ['neis'],\n};\n\nexport class KampusClient {\n private readonly providers: KampusProvider[];\n private readonly initPromises = new Map<KampusProvider, Promise<void>>();\n\n constructor(options: KampusClientOptions) {\n if (!options.providers.length) {\n throw new InvalidInputError('At least one provider is required.');\n }\n\n this.providers = options.providers;\n }\n\n async init(): Promise<void> {\n await Promise.all(this.providers.map((provider) => this.initializeProvider(provider)));\n }\n\n async searchSchools(keyword: string): Promise<SchoolSearchResult[]> {\n if (!keyword.trim()) {\n throw new InvalidInputError('A school keyword is required.');\n }\n\n const providers = this.getProviders('schoolSearch');\n const searchResults = await Promise.all(\n providers.map(async (provider) => this.trySearchWithProvider(provider, keyword)),\n );\n\n const successes = searchResults.flatMap((result) => result.results);\n if (successes.length > 0) {\n return mergeSchoolSearchResults(successes);\n }\n\n const firstError = searchResults.find((result) => result.error)?.error;\n if (firstError) {\n throw firstError;\n }\n\n return [];\n }\n\n async resolveSchool(name: string, region?: string): Promise<SchoolSearchResult> {\n const keyword = name.trim();\n if (!keyword) {\n throw new InvalidInputError('A school name is required.');\n }\n\n const results = await this.searchSchools(keyword);\n return this.selectSchool(results, keyword, region);\n }\n\n async getSchoolByExactMatch(name: string, region?: string): Promise<SchoolSearchResult> {\n return this.resolveSchool(name, region);\n }\n\n async getSchoolInfo(school: SchoolRef): Promise<SchoolInfo> {\n const provider = this.getPreferredProvider('schoolInfo');\n const resolvedSchool = await this.resolveSchoolForProvider(school, provider.name);\n return provider.getSchoolInfo!(resolvedSchool);\n }\n\n async getWeekTimetable(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekOffset?: number;\n }): Promise<WeekTimetable> {\n this.validateGradeClass(params.grade, params.classNo);\n const provider = this.getPreferredProvider('studentTimetable');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getWeekTimetable!({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getDayTimetable(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekday: number;\n weekOffset?: number;\n }): Promise<DayTimetable> {\n this.validateGradeClass(params.grade, params.classNo);\n this.validateWeekday(params.weekday);\n\n const provider = this.getPreferredProvider('studentTimetable');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n\n if (provider.getDayTimetable) {\n return provider.getDayTimetable({\n ...params,\n school: resolvedSchool,\n });\n }\n\n const week = await provider.getWeekTimetable!({\n school: resolvedSchool,\n grade: params.grade,\n classNo: params.classNo,\n weekOffset: params.weekOffset,\n });\n\n const day = extractDay(week, params.weekday);\n if (!day) {\n throw new InvalidInputError(`No timetable exists for weekday ${params.weekday}.`);\n }\n\n return day;\n }\n\n async getTodayTimetable(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n date?: Date;\n }): Promise<DayTimetable> {\n return this.getDayTimetable({\n school: params.school,\n grade: params.grade,\n classNo: params.classNo,\n weekday: todayWeekday(params.date),\n });\n }\n\n async getTeacherTimetable(params: {\n school: SchoolRef;\n teacherName: string;\n weekday?: number;\n weekOffset?: number;\n }): Promise<TeacherTimetable> {\n if (!params.teacherName.trim()) {\n throw new InvalidInputError('A teacher name is required.');\n }\n if (params.weekday != null) {\n this.validateWeekday(params.weekday);\n }\n\n const provider = this.getPreferredProvider('teacherTimetable');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getTeacherTimetable!({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getTeacherInfo(params: {\n school: SchoolRef;\n teacherName: string;\n }): Promise<TeacherInfo> {\n if (!params.teacherName.trim()) {\n throw new InvalidInputError('A teacher name is required.');\n }\n\n const provider = this.getPreferredProvider('teacherInfo');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getTeacherInfo!({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getClassTimes(school: SchoolRef): Promise<ClassTimeSlot[]> {\n const provider = this.getPreferredProvider('classTimes');\n const resolvedSchool = await this.resolveSchoolForProvider(school, provider.name);\n return provider.getClassTimes!(resolvedSchool);\n }\n\n async getMealsToday(params: {\n school: SchoolRef;\n date?: string;\n }): Promise<DailyMeals> {\n const provider = this.getPreferredProvider('meals');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getMealsToday!({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getMealsWeek(params: {\n school: SchoolRef;\n weekOffset?: number;\n date?: string;\n }): Promise<WeeklyMeals> {\n const provider = this.getPreferredProvider('meals');\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getMealsWeek!({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getMealsRange(params: {\n school: SchoolRef;\n fromDate: string;\n toDate: string;\n }): Promise<WeeklyMeals> {\n const provider = this.getPreferredProvider('meals');\n if (!provider.getMealsRange) {\n throw new ProviderUnavailableError(\n provider.name,\n undefined,\n `Provider \"${provider.name}\" does not support ranged meal queries.`,\n );\n }\n\n const resolvedSchool = await this.resolveSchoolForProvider(params.school, provider.name);\n return provider.getMealsRange({\n ...params,\n school: resolvedSchool,\n });\n }\n\n async getNextClass(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n now?: Date;\n }): Promise<{ period: PeriodItem; minutesUntil?: number } | null> {\n const now = params.now ?? new Date();\n const timetable = await this.getTodayTimetable({\n school: params.school,\n grade: params.grade,\n classNo: params.classNo,\n date: now,\n });\n\n let classTimes: ClassTimeSlot[] | null = null;\n try {\n classTimes = await this.getClassTimes(params.school);\n } catch {\n classTimes = null;\n }\n\n if (!classTimes) {\n return timetable.periods.find((period) => !period.isFreePeriod)\n ? { period: timetable.periods.find((period) => !period.isFreePeriod)! }\n : null;\n }\n\n const currentMinutes = now.getHours() * 60 + now.getMinutes();\n for (const period of timetable.periods) {\n if (period.isFreePeriod) {\n continue;\n }\n\n const slot = classTimes.find((candidate) => candidate.period === period.period);\n if (!slot) {\n continue;\n }\n\n const [hour, minute] = slot.startTime.split(':').map(Number);\n const startMinutes = hour * 60 + minute;\n if (startMinutes > currentMinutes) {\n return {\n period,\n minutesUntil: startMinutes - currentMinutes,\n };\n }\n }\n\n return null;\n }\n\n diffSnapshots(a: WeekTimetable, b: WeekTimetable): SnapshotDiff {\n return diffSnapshots(a, b);\n }\n\n private async initializeProvider(provider: KampusProvider): Promise<void> {\n let initPromise = this.initPromises.get(provider);\n if (!initPromise) {\n initPromise = Promise.resolve(provider.init?.());\n this.initPromises.set(provider, initPromise);\n }\n\n try {\n await initPromise;\n } catch (error) {\n this.initPromises.delete(provider);\n throw error;\n }\n }\n\n private getProviders(capability: ProviderCapability): KampusProvider[] {\n const providers = this.providers.filter((provider) => provider.capabilities.has(capability));\n if (!providers.length) {\n throw new ProviderUnavailableError(\n capability,\n undefined,\n `No provider is registered for capability \"${capability}\".`,\n );\n }\n\n const preferences = PROVIDER_PREFERENCES[capability] ?? [];\n return [...providers].sort((left, right) => {\n const leftIndex = this.preferenceIndex(preferences, left.name);\n const rightIndex = this.preferenceIndex(preferences, right.name);\n return leftIndex - rightIndex;\n });\n }\n\n private getPreferredProvider(capability: Exclude<ProviderCapability, 'schoolSearch'>): KampusProvider {\n const provider = this.getProviders(capability)[0];\n return provider;\n }\n\n private preferenceIndex(preferences: string[], providerName: string): number {\n const index = preferences.indexOf(providerName);\n return index === -1 ? Number.MAX_SAFE_INTEGER : index;\n }\n\n private async trySearchWithProvider(\n provider: KampusProvider,\n keyword: string,\n ): Promise<{ results: SchoolSearchResult[]; error?: Error }> {\n try {\n await this.initializeProvider(provider);\n return {\n results: (await provider.searchSchools?.(keyword)) ?? [],\n };\n } catch (error) {\n return {\n results: [],\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n }\n\n private selectSchool(\n results: SchoolSearchResult[],\n name: string,\n region?: string,\n ): SchoolSearchResult {\n const normalizedName = normalizeSchoolName(name);\n const exactNameMatches = results.filter(\n (result) => normalizeSchoolName(result.name) === normalizedName,\n );\n const partialNameMatches = results.filter((result) =>\n normalizeSchoolName(result.name).includes(normalizedName),\n );\n\n const normalizedRegion = normalizeRegionName(region);\n const applyRegion = (candidates: SchoolSearchResult[]) =>\n normalizedRegion\n ? candidates.filter((result) => {\n const resultRegion = normalizeRegionName(result.region);\n return !resultRegion || resultRegion === normalizedRegion;\n })\n : candidates;\n\n const regionMatches = applyRegion(exactNameMatches);\n\n if (regionMatches.length === 1) {\n return regionMatches[0];\n }\n\n if (!region && exactNameMatches.length === 1) {\n return exactNameMatches[0];\n }\n\n if (!exactNameMatches.length) {\n const partialRegionMatches = applyRegion(partialNameMatches);\n if (partialRegionMatches.length === 1) {\n return partialRegionMatches[0];\n }\n if (!region && partialNameMatches.length === 1) {\n return partialNameMatches[0];\n }\n throw new SchoolNotFoundError(name);\n }\n\n throw new AmbiguousSchoolError(\n name,\n (regionMatches.length > 0 ? regionMatches : exactNameMatches).map((match) => ({\n name: match.name,\n region: match.region,\n schoolType: match.schoolType,\n })),\n );\n }\n\n private async resolveSchoolForProvider(school: SchoolRef, providerName: string): Promise<SchoolRef> {\n if (providerName !== 'comcigan' && providerName !== 'neis') {\n return school;\n }\n\n if (hasProviderRef(school, providerName)) {\n return school;\n }\n\n const provider = this.providers.find((candidate) => candidate.name === providerName);\n if (provider?.capabilities.has('schoolSearch') && provider.searchSchools) {\n const providerResults = await this.trySearchWithProvider(provider, school.name);\n if (providerResults.error && providerResults.results.length === 0) {\n throw providerResults.error;\n }\n const selected = this.trySelectMatchingSchool(providerResults.results, school, providerName);\n if (selected) {\n return mergeSchoolRefs(school, selected);\n }\n }\n\n const aggregated = await this.searchSchools(school.name);\n const selected = this.trySelectMatchingSchool(aggregated, school, providerName);\n if (selected) {\n return mergeSchoolRefs(school, selected);\n }\n\n throw new ProviderUnavailableError(\n providerName,\n undefined,\n `Unable to resolve a ${providerName} school reference for \"${school.name}\".`,\n );\n }\n\n private trySelectMatchingSchool(\n candidates: SchoolSearchResult[],\n target: SchoolRef,\n providerName: ProviderId,\n ): SchoolSearchResult | null {\n const matches = candidates.filter((candidate) => schoolMatches(candidate, target));\n const withProviderRef = matches.filter((candidate) => hasProviderRef(candidate, providerName));\n\n if (withProviderRef.length === 1) {\n return withProviderRef[0];\n }\n\n if (withProviderRef.length > 1) {\n throw new AmbiguousSchoolError(\n target.name,\n withProviderRef.map((match) => ({\n name: match.name,\n region: match.region,\n schoolType: match.schoolType,\n })),\n );\n }\n\n return null;\n }\n\n private validateGradeClass(grade: number, classNo: number): void {\n if (!Number.isInteger(grade) || grade < 1 || grade > 6) {\n throw new InvalidInputError('Grade must be an integer from 1 to 6.');\n }\n if (!Number.isInteger(classNo) || classNo < 1 || classNo > 30) {\n throw new InvalidInputError('Class number must be an integer from 1 to 30.');\n }\n }\n\n private validateWeekday(weekday: number): void {\n if (!Number.isInteger(weekday) || weekday < 1 || weekday > 7) {\n throw new InvalidInputError('Weekday must be an integer from 1 to 7.');\n }\n }\n}\n\nexport type KampusSnapshot = {\n school: SchoolRef;\n capturedAt: string;\n weekStart: string;\n grade: number;\n classNo: number;\n timetable: WeekTimetable;\n};\n\nexport function createSnapshot(week: WeekTimetable): KampusSnapshot {\n return {\n school: week.school,\n capturedAt: new Date().toISOString(),\n weekStart: week.weekStart ?? formatDate(getMonday(new Date())),\n grade: week.grade,\n classNo: week.classNo,\n timetable: week,\n };\n}\n", "\uFEFFexport type {\n AccessMode,\n ClassTimeSlot,\n ComciganSchoolRef,\n DataStatus,\n DailyMealService,\n DailyMeals,\n DayTimetable,\n KampusProvider,\n MealItem,\n NeisSchoolRef,\n PeriodChange,\n PeriodItem,\n PeriodSource,\n PeriodStatus,\n ProviderCapability,\n ProviderId,\n ProviderMetadata,\n ProviderRefs,\n ProviderWarning,\n SchoolInfo,\n SchoolRef,\n SchoolSearchResult,\n SnapshotDiff,\n TeacherDayTimetable,\n TeacherInfo,\n TeacherPeriodItem,\n TeacherTimetable,\n WeekTimetable,\n WeeklyMeals,\n} from './types.js';\n\nexport { UNKNOWN_SUBJECT, WEEKDAY_NAMES, WEEKDAY_SHORT } from './types.js';\n\nexport {\n AmbiguousSchoolError,\n InvalidInputError,\n KampusError,\n MealsUnavailableError,\n NetworkError,\n ProviderUnavailableError,\n SchoolNotFoundError,\n TeacherNotFoundError,\n TimetableUnavailableError,\n UpstreamChangedError,\n} from './errors.js';\n\nexport {\n describeSecretStorage,\n getPreferredSecretStorage,\n protectSecret,\n resolveSecret,\n} from './secret.js';\nexport type { KampusProtectedSecret, KampusResolvedSecret, KampusSecretStorage } from './secret.js';\n\nexport {\n getKampusConfigStatus,\n getActiveProfile,\n clearDefaultSchool,\n loadKampusConfig,\n listProfiles,\n maskSecret,\n rememberRecentSchool,\n removeRecentSchool,\n removeProfile,\n resolveCachePolicy,\n resolveKampusConfigPath,\n resolveKampusDataDir,\n resolveNeisApiKey,\n saveKampusConfig,\n setActiveProfile,\n setDefaultSchool,\n setNeisApiKeyStatus,\n upsertProfile,\n} from './config.js';\nexport type {\n KampusCachePolicy,\n KampusConfig,\n KampusConfigOptions,\n KampusConfigStatus,\n KampusNeisApiKeyStatus,\n KampusProfile,\n KampusProfileInput,\n KampusStoredSchool,\n} from './config.js';\n\nexport { KAMPUS_DEVELOPER_INFO, KAMPUS_PROJECT_INFO } from './metadata.js';\nexport type { KampusDeveloperInfo, KampusProjectInfo } from './metadata.js';\n\nexport {\n loadKampusCache,\n readKampusCacheEntry,\n resolveKampusCachePath,\n saveKampusCache,\n touchKampusCacheEntry,\n writeKampusCacheEntry,\n} from './cache.js';\nexport type { KampusCacheEntry, KampusCacheFile, KampusCacheOptions, KampusCacheReadResult } from './cache.js';\n\nexport {\n diffSnapshots,\n extractDay,\n formatDate,\n getMonday,\n hasProviderRef,\n mergeProviderRefs,\n mergeSchoolRefs,\n mergeSchoolSearchResults,\n normalizePeriod,\n normalizeRegionName,\n normalizeSchoolName,\n normalizeTeacherPeriod,\n providerIdsFromRefs,\n schoolMatches,\n todayWeekday,\n weekdayName,\n} from './normalize.js';\n\nexport { KampusClient, createSnapshot } from './client.js';\nexport type { KampusClientOptions, KampusSnapshot } from './client.js';\n", "import {\n getActiveProfile,\n InvalidInputError,\n KampusClient,\n loadKampusConfig,\n normalizeSchoolName,\n providerIdsFromRefs,\n rememberRecentSchool,\n saveKampusConfig,\n type KampusStoredSchool,\n type SchoolSearchResult,\n} from '@kampus/core';\n\nexport async function resolveSchool(\n client: KampusClient,\n name?: string,\n region?: string,\n): Promise<SchoolSearchResult> {\n const config = loadKampusConfig();\n const activeProfile = getActiveProfile(config);\n const defaultSchool = activeProfile?.school ?? config.defaultSchool;\n const trimmedName = name?.trim();\n\n if (!trimmedName) {\n if (!defaultSchool) {\n throw new InvalidInputError(\n 'School name is required. Pass --school or set a default school with \"kps config set default-school <name>\".',\n );\n }\n\n const stored = storedSchoolToSearchResult(defaultSchool);\n persistRecentSchool(stored);\n return stored;\n }\n\n const regionHint =\n region?.trim() ||\n (defaultSchool &&\n normalizeSchoolName(defaultSchool.name) === normalizeSchoolName(trimmedName)\n ? defaultSchool.region\n : undefined);\n\n const resolved = await client.resolveSchool(trimmedName, regionHint);\n persistRecentSchool(resolved);\n return resolved;\n}\n\nexport function getDefaultSchool(): SchoolSearchResult | undefined {\n const config = loadKampusConfig();\n const defaultSchool = getActiveProfile(config)?.school ?? config.defaultSchool;\n return defaultSchool ? storedSchoolToSearchResult(defaultSchool) : undefined;\n}\n\nexport function getActiveProfileContext() {\n const config = loadKampusConfig();\n return getActiveProfile(config);\n}\n\nexport function resolveGradeClassDefaults(\n grade?: number,\n classNo?: number,\n): { grade: number; classNo: number } {\n const profile = getActiveProfileContext();\n return {\n grade: grade ?? profile?.grade ?? 0,\n classNo: classNo ?? profile?.classNo ?? 0,\n };\n}\n\nexport function resolveTeacherDefault(teacherName?: string): string | undefined {\n return teacherName?.trim() || getActiveProfileContext()?.teacherName;\n}\n\nfunction persistRecentSchool(school: SchoolSearchResult): void {\n const current = loadKampusConfig();\n saveKampusConfig(rememberRecentSchool(current, school));\n}\n\nfunction storedSchoolToSearchResult(school: KampusStoredSchool): SchoolSearchResult {\n return {\n name: school.name,\n region: school.region,\n schoolType: school.schoolType,\n providerRefs: school.providerRefs,\n sourceProviders: providerIdsFromRefs(school.providerRefs),\n };\n}\n", "import { Command } from 'commander';\nimport { classCommands } from './commands/class.js';\nimport { authCommands } from './commands/auth.js';\nimport { configCommands } from './commands/config.js';\nimport { diagCommands } from './commands/diag.js';\nimport { mealsCommands } from './commands/meals.js';\nimport { neisCommands } from './commands/neis.js';\nimport { profileCommands } from './commands/profile.js';\nimport { schoolCommands } from './commands/school.js';\nimport { teacherCommands } from './commands/teacher.js';\nimport { interactiveCommands } from './commands/interactive.js';\nimport { utilCommands } from './commands/util.js';\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('kps')\n .description('Kampus CLI for Korean school timetable and meal lookups')\n .version('0.1.0');\n\n interactiveCommands(program);\n authCommands(program);\n configCommands(program);\n profileCommands(program);\n schoolCommands(program);\n neisCommands(program);\n classCommands(program);\n teacherCommands(program);\n mealsCommands(program);\n utilCommands(program);\n diagCommands(program);\n\n return program;\n}\n", "import type { Command } from 'commander';\nimport { InvalidInputError } from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport {\n getFormat,\n printClassTimes,\n printDayTimetable,\n printNextClass,\n printWeekTimetable,\n} from '../output.js';\nimport { resolveGradeClassDefaults, resolveSchool } from './resolve.js';\n\nexport function classCommands(program: Command): void {\n const cls = program.command('class').description('Student timetable commands');\n\n cls\n .command('today')\n .description('Fetch the current-day timetable')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Grade (falls back to active profile)', parseInt)\n .option('--class <n>', 'Class number (falls back to active profile)', parseInt)\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps class today --school \"<school>\" --region \"<region>\" --grade 3 --class 5')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const { grade, classNo } = requireGradeClass(opts.grade, opts.class);\n const timetable = await client.getTodayTimetable({\n school,\n grade,\n classNo,\n });\n printDayTimetable(\n timetable,\n getFormat(opts),\n `${school.name} ${grade}-${classNo} today`,\n );\n });\n\n cls\n .command('day')\n .description('Fetch a timetable for a specific weekday')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Grade (falls back to active profile)', parseInt)\n .option('--class <n>', 'Class number (falls back to active profile)', parseInt)\n .requiredOption('--weekday <n>', 'Weekday (1-7)', parseInt)\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps class day --school \"<school>\" --region \"<region>\" --grade 3 --class 5 --weekday 1')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const { grade, classNo } = requireGradeClass(opts.grade, opts.class);\n const timetable = await client.getDayTimetable({\n school,\n grade,\n classNo,\n weekday: opts.weekday,\n });\n printDayTimetable(timetable, getFormat(opts));\n });\n\n cls\n .command('week')\n .description('Fetch a weekly timetable')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Grade (falls back to active profile)', parseInt)\n .option('--class <n>', 'Class number (falls back to active profile)', parseInt)\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps class week --school \"<school>\" --region \"<region>\" --grade 3 --class 5')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const { grade, classNo } = requireGradeClass(opts.grade, opts.class);\n const timetable = await client.getWeekTimetable({\n school,\n grade,\n classNo,\n });\n printWeekTimetable(timetable, getFormat(opts));\n });\n\n program\n .command('next')\n .description('Find the next class')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Grade (falls back to active profile)', parseInt)\n .option('--class <n>', 'Class number (falls back to active profile)', parseInt)\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .addHelpText('after', '\\nExample:\\n kps next --school \"<school>\" --region \"<region>\" --grade 3 --class 5')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const { grade, classNo } = requireGradeClass(opts.grade, opts.class);\n const result = await client.getNextClass({\n school,\n grade,\n classNo,\n });\n printNextClass(result, getFormat(opts));\n });\n\n program\n .command('class-times')\n .description('Fetch class time slots')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps class-times --school \"<school>\" --region \"<region>\"')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const times = await client.getClassTimes(school);\n printClassTimes(times, getFormat(opts));\n });\n}\n\nfunction requireGradeClass(grade?: number, classNo?: number): { grade: number; classNo: number } {\n const resolved = resolveGradeClassDefaults(grade, classNo);\n if (!resolved.grade || !resolved.classNo) {\n throw new InvalidInputError(\n 'Grade and class are required. Pass --grade/--class or save them in the active profile.',\n );\n }\n return resolved;\n}\n", "import { KampusClient, resolveCachePolicy, resolveKampusCachePath, resolveNeisApiKey } from '@kampus/core';\nimport { ComciganProvider } from '@kampus/provider-comcigan';\nimport { NeisProvider } from '@kampus/provider-neis';\n\nlet cachedClient: KampusClient | null = null;\n\n/**\n * Create or return a cached KampusClient with default providers.\n */\nexport function createClient(): KampusClient {\n if (cachedClient) return cachedClient;\n\n const cachePolicy = resolveCachePolicy();\n const comcigan = new ComciganProvider();\n const neis = new NeisProvider({\n apiKey: resolveNeisApiKey(),\n cachePath: resolveKampusCachePath(),\n cacheTtlMs: cachePolicy.datasetTtlMinutes * 60 * 1000,\n staleIfErrorMs: cachePolicy.staleIfErrorHours * 60 * 60 * 1000,\n cacheMaxEntries: cachePolicy.maxEntries,\n });\n\n cachedClient = new KampusClient({\n providers: [comcigan, neis],\n });\n\n return cachedClient;\n}\n", "import type {\n ClassTimeSlot,\n DataStatus,\n DayTimetable,\n KampusProvider,\n PeriodItem,\n ProviderCapability,\n ProviderMetadata,\n SchoolInfo,\n SchoolRef,\n SchoolSearchResult,\n TeacherDayTimetable,\n TeacherInfo,\n TeacherTimetable,\n TeacherPeriodItem,\n WeekTimetable,\n} from '@kampus/core';\nimport {\n NetworkError,\n TeacherNotFoundError,\n TimetableUnavailableError,\n UpstreamChangedError,\n extractDay,\n formatDate,\n getMonday,\n normalizePeriod,\n normalizeTeacherPeriod,\n weekdayName,\n} from '@kampus/core';\nimport iconv from 'iconv-lite';\n\nconst COMCIGAN_BASE = 'http://comci.net:4082';\nconst KEY_SCHOOL_SEARCH = '\\uD559\\uAD50\\uAC80\\uC0C9';\nconst KEY_CLASS_COUNTS = '\\uD559\\uAE09\\uC218';\nconst KEY_TEACHERS = '\\uC790\\uB8CC446';\nconst KEY_SUBJECTS = '\\uC790\\uB8CC492';\nconst KEY_ORIGINAL_TIMETABLE = '\\uC790\\uB8CC481';\nconst KEY_CURRENT_TIMETABLE = '\\uC790\\uB8CC147';\nconst KEY_SPLIT = '\\uBD84\\uB9AC';\nconst KEY_TOTAL_GRADES = '\\uC804\\uCCB4\\uD559\\uB144';\nconst KEY_CLASS_TIMES = '\\uC77C\\uACFC\\uC2DC\\uAC04';\nconst ST_PATH = '/st';\n\ntype RawComciganData = Record<string, unknown>;\n\nexport interface ComciganProviderOptions {\n baseUrl?: string;\n}\n\nexport class ComciganProvider implements KampusProvider {\n readonly name = 'comcigan';\n readonly capabilities: ReadonlySet<ProviderCapability> = new Set([\n 'schoolSearch',\n 'studentTimetable',\n 'teacherTimetable',\n 'teacherInfo',\n 'classTimes',\n ]);\n\n private readonly baseUrl: string;\n private readonly schoolDataCache = new Map<number, ParsedSchoolData>();\n private routeCache?: ComciganRouteInfo;\n\n constructor(options?: ComciganProviderOptions) {\n this.baseUrl = options?.baseUrl ?? COMCIGAN_BASE;\n }\n\n async searchSchools(keyword: string): Promise<SchoolSearchResult[]> {\n const routes = await this.loadRouteInfo();\n const encodedKeyword = this.encodeSearchKeyword(keyword);\n const url = `${this.baseUrl}/${routes.mainRoute}?${routes.searchRoute}l${encodedKeyword}`;\n const response = (await this.fetchBuffer(url)).toString('utf-8');\n const cleaned = this.stripNulls(response);\n\n let payload: RawComciganData;\n try {\n payload = JSON.parse(cleaned);\n } catch (error) {\n throw new UpstreamChangedError('Comcigan search response is no longer valid JSON.', error);\n }\n\n const matches = payload[KEY_SCHOOL_SEARCH];\n if (!Array.isArray(matches)) {\n return [];\n }\n\n return matches\n .filter(\n (entry): entry is [number, string, string, number?] => Array.isArray(entry) && entry.length >= 3,\n )\n .map((entry) => ({\n name: String(entry[2]).trim(),\n region: entry[1] ? String(entry[1]).trim() : undefined,\n providerRefs: {\n comcigan: {\n schoolCode: Number(entry[3] ?? entry[0]),\n },\n },\n sourceProviders: ['comcigan'],\n }));\n }\n\n async getSchoolInfo(school: SchoolRef): Promise<SchoolInfo> {\n const data = await this.loadSchoolData(school);\n return {\n name: school.name,\n region: school.region,\n schoolType: school.schoolType,\n providerRefs: school.providerRefs,\n gradeCount: data.gradeCount,\n classCounts: data.classCounts,\n teacherNames: data.teacherNames.filter((name, index) => index > 0 && name !== '*'),\n providerMetadata: this.meta(),\n dataStatus: this.dataStatus(),\n };\n }\n\n async getWeekTimetable(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekOffset?: number;\n }): Promise<WeekTimetable> {\n const data = await this.loadSchoolData(params.school);\n const monday = getMonday(new Date());\n if (params.weekOffset) {\n monday.setDate(monday.getDate() + params.weekOffset * 7);\n }\n\n const days: DayTimetable[] = [];\n for (let weekday = 1; weekday <= 5; weekday++) {\n const date = new Date(monday);\n date.setDate(date.getDate() + (weekday - 1));\n days.push({\n weekday,\n weekdayName: weekdayName(weekday),\n date: formatDate(date),\n periods: this.extractPeriods(data, params.grade, params.classNo, weekday),\n providerMetadata: this.meta(),\n dataStatus: this.dataStatus(),\n });\n }\n\n return {\n school: params.school,\n grade: params.grade,\n classNo: params.classNo,\n weekStart: formatDate(monday),\n days,\n providerMetadata: this.meta(),\n dataStatus: this.dataStatus(),\n };\n }\n\n async getDayTimetable(params: {\n school: SchoolRef;\n grade: number;\n classNo: number;\n weekday: number;\n weekOffset?: number;\n }): Promise<DayTimetable> {\n const week = await this.getWeekTimetable(params);\n const day = extractDay(week, params.weekday);\n if (!day) {\n throw new TimetableUnavailableError(`No timetable exists for weekday ${params.weekday}.`);\n }\n return day;\n }\n\n async getTeacherTimetable(params: {\n school: SchoolRef;\n teacherName: string;\n weekday?: number;\n weekOffset?: number;\n }): Promise<TeacherTimetable> {\n const data = await this.loadSchoolData(params.school);\n const teacherIndex = data.teacherNames.indexOf(params.teacherName);\n if (teacherIndex === -1) {\n throw new TeacherNotFoundError(params.teacherName, params.school.name);\n }\n\n const monday = getMonday(new Date());\n if (params.weekOffset) {\n monday.setDate(monday.getDate() + params.weekOffset * 7);\n }\n\n const days: TeacherDayTimetable[] = [];\n for (let weekday = 1; weekday <= 5; weekday++) {\n if (params.weekday && params.weekday !== weekday) {\n continue;\n }\n\n const date = new Date(monday);\n date.setDate(date.getDate() + (weekday - 1));\n\n days.push({\n weekday,\n weekdayName: weekdayName(weekday),\n date: formatDate(date),\n periods: this.extractTeacherPeriods(data, teacherIndex, weekday),\n });\n }\n\n return {\n school: params.school,\n teacherName: params.teacherName,\n days,\n providerMetadata: this.meta(),\n dataStatus: this.dataStatus(),\n };\n }\n\n async getTeacherInfo(params: {\n school: SchoolRef;\n teacherName: string;\n }): Promise<TeacherInfo> {\n const data = await this.loadSchoolData(params.school);\n const teacherIndex = data.teacherNames.indexOf(params.teacherName);\n if (teacherIndex === -1) {\n throw new TeacherNotFoundError(params.teacherName, params.school.name);\n }\n\n const subjects = new Set<string>();\n const classes = new Set<string>();\n\n for (let grade = 1; grade <= data.gradeCount; grade++) {\n const classCount = data.classCounts[grade] ?? 0;\n for (let classNo = 1; classNo <= classCount; classNo++) {\n for (let weekday = 1; weekday <= 5; weekday++) {\n for (const period of this.extractPeriods(data, grade, classNo, weekday)) {\n if (period.source.rawCodes?.teacherIdx === teacherIndex && !period.isFreePeriod) {\n subjects.add(period.subject);\n classes.add(`${grade}-${classNo}`);\n }\n }\n }\n }\n }\n\n return {\n school: params.school,\n name: params.teacherName,\n subjects: [...subjects],\n classes: [...classes].sort(),\n providerMetadata: this.meta(),\n dataStatus: this.dataStatus(),\n };\n }\n\n async getClassTimes(school: SchoolRef): Promise<ClassTimeSlot[]> {\n const data = await this.loadSchoolData(school);\n if (!data.classTimes?.length) {\n throw new TimetableUnavailableError('Class times are not exposed by the current Comcigan payload.');\n }\n return data.classTimes;\n }\n\n private async loadSchoolData(school: SchoolRef): Promise<ParsedSchoolData> {\n const schoolCode = school.providerRefs.comcigan?.schoolCode;\n if (!schoolCode) {\n throw new TimetableUnavailableError(`Comcigan school reference is missing for \"${school.name}\".`);\n }\n\n const cached = this.schoolDataCache.get(schoolCode);\n if (cached) {\n return cached;\n }\n\n const routes = await this.loadRouteInfo();\n const payload = Buffer.from(`${routes.dataPrefix}${schoolCode}_0_1`).toString('base64');\n const url = `${this.baseUrl}/${routes.mainRoute}_T?${payload}`;\n const cleaned = this.stripNulls((await this.fetchBuffer(url)).toString('utf-8'));\n\n let raw: RawComciganData;\n try {\n raw = JSON.parse(cleaned);\n } catch (error) {\n throw new UpstreamChangedError('Comcigan timetable payload is no longer valid JSON.', error);\n }\n\n const data = this.parseSchoolData(raw, school);\n this.schoolDataCache.set(schoolCode, data);\n return data;\n }\n\n private parseSchoolData(raw: RawComciganData, school: SchoolRef): ParsedSchoolData {\n const originalTimetable = raw[KEY_ORIGINAL_TIMETABLE];\n if (!Array.isArray(originalTimetable)) {\n throw new UpstreamChangedError('Comcigan timetable structure is missing.');\n }\n\n const currentTimetable = Array.isArray(raw[KEY_CURRENT_TIMETABLE])\n ? raw[KEY_CURRENT_TIMETABLE]\n : originalTimetable;\n const teacherNames = Array.isArray(raw[KEY_TEACHERS])\n ? raw[KEY_TEACHERS].filter((value): value is string => typeof value === 'string')\n : [];\n\n const rawSubjects = Array.isArray(raw[KEY_SUBJECTS])\n ? raw[KEY_SUBJECTS].filter((value): value is string => typeof value === 'string')\n : [];\n const subjects = ['', ...rawSubjects];\n\n const rawClassCounts = Array.isArray(raw[KEY_CLASS_COUNTS]) ? raw[KEY_CLASS_COUNTS] : [];\n const gradeCount =\n Number(raw[KEY_TOTAL_GRADES]) ||\n Number(currentTimetable[0]) ||\n Number(originalTimetable[0]) ||\n Math.max(0, rawClassCounts.length - 1);\n const classCounts: Record<number, number> = {};\n for (let grade = 1; grade <= gradeCount; grade++) {\n classCounts[grade] = Number(rawClassCounts[grade]) || 0;\n }\n\n return {\n school,\n teacherNames,\n subjects,\n gradeCount,\n classCounts,\n splitValue: this.resolveSplitValue(raw, teacherNames.length),\n originalTimetable,\n currentTimetable,\n classTimes: this.extractClassTimes(raw),\n };\n }\n\n private extractClassTimes(raw: RawComciganData): ClassTimeSlot[] | undefined {\n const candidates = [raw[KEY_CLASS_TIMES], raw['\\uC218\\uC5C5\\uC2DC\\uAC04'], raw['classTimes']];\n\n for (const candidate of candidates) {\n if (!Array.isArray(candidate)) {\n continue;\n }\n\n const slots = this.extractNumericClassTimes(candidate) ?? this.extractStringClassTimes(candidate);\n\n if (slots.length) {\n return slots;\n }\n }\n\n return undefined;\n }\n\n private extractPeriods(\n data: ParsedSchoolData,\n grade: number,\n classNo: number,\n weekday: number,\n ): PeriodItem[] {\n const gradeData = data.currentTimetable[grade];\n if (!Array.isArray(gradeData)) {\n return [];\n }\n\n const classData = gradeData[classNo];\n if (!Array.isArray(classData)) {\n return [];\n }\n\n const dayData = classData[weekday];\n if (!Array.isArray(dayData)) {\n return [];\n }\n\n const periodCount = Number(dayData[0]) || Math.max(0, dayData.length - 1);\n const periods: PeriodItem[] = [];\n\n for (let period = 1; period <= periodCount; period++) {\n const encoded = Number(dayData[period] ?? 0);\n if (!encoded) {\n continue;\n }\n\n const { subjectIdx, teacherIdx, subjectSection } = this.decodePeriodValue(encoded, data.splitValue);\n const subject = this.formatSubjectLabel(data.subjects[subjectIdx] ?? '', subjectSection);\n const teacher = data.teacherNames[teacherIdx] ?? '';\n const originalEncoded = this.lookupOriginalCode(data, grade, classNo, weekday, period);\n\n periods.push(\n normalizePeriod({\n period,\n subject,\n teacher,\n source: { provider: 'comcigan' },\n rawSubject: subject,\n rawTeacher: teacher,\n rawCodes: {\n encoded,\n originalEncoded: originalEncoded ?? '',\n subjectIdx,\n teacherIdx,\n splitValue: data.splitValue,\n subjectSection,\n },\n }),\n );\n }\n\n return periods;\n }\n\n private extractTeacherPeriods(\n data: ParsedSchoolData,\n teacherIndex: number,\n weekday: number,\n ): TeacherPeriodItem[] {\n const periods: TeacherPeriodItem[] = [];\n\n for (let grade = 1; grade <= data.gradeCount; grade++) {\n const classCount = data.classCounts[grade] ?? 0;\n for (let classNo = 1; classNo <= classCount; classNo++) {\n for (const period of this.extractPeriods(data, grade, classNo, weekday)) {\n if (period.source.rawCodes?.teacherIdx !== teacherIndex) {\n continue;\n }\n\n periods.push(\n normalizeTeacherPeriod({\n period: period.period,\n subject: period.subject,\n grade,\n classNo,\n source: { provider: 'comcigan' },\n rawSubject: period.source.rawSubject,\n rawCodes: period.source.rawCodes,\n }),\n );\n }\n }\n }\n\n periods.sort((left, right) => left.period - right.period);\n if (!periods.length) {\n return [];\n }\n\n const maxPeriod = Math.max(...periods.map((period) => period.period));\n const filled: TeacherPeriodItem[] = [];\n for (let period = 1; period <= maxPeriod; period++) {\n const existing = periods.find((candidate) => candidate.period === period);\n filled.push(\n existing ??\n normalizeTeacherPeriod({\n period,\n source: { provider: 'comcigan' },\n }),\n );\n }\n\n return filled;\n }\n\n private decodePeriodValue(\n value: number,\n splitValue: number,\n ): {\n subjectIdx: number;\n teacherIdx: number;\n subjectSection: number;\n } {\n if (splitValue === 100) {\n return {\n subjectIdx: value % splitValue,\n teacherIdx: Math.floor(value / splitValue),\n subjectSection: 0,\n };\n }\n\n const teacherIdx = value % splitValue;\n const subjectCode = Math.floor(value / splitValue);\n return {\n subjectIdx: subjectCode % splitValue,\n teacherIdx,\n subjectSection: Math.floor(subjectCode / splitValue),\n };\n }\n\n private formatSubjectLabel(subject: string, subjectSection: number): string {\n if (!subject) {\n return '';\n }\n\n if (subjectSection < 1) {\n return subject;\n }\n\n if (subjectSection <= 26) {\n return `${String.fromCharCode(64 + subjectSection)}_${subject}`;\n }\n\n return `${subjectSection}_${subject}`;\n }\n\n private encodeSearchKeyword(keyword: string): string {\n return [...iconv.encode(keyword, 'euc-kr')]\n .map((byte) => `%${byte.toString(16).toUpperCase().padStart(2, '0')}`)\n .join('');\n }\n\n private stripNulls(value: string): string {\n return value.replace(/\\u0000+/g, '').trim();\n }\n\n private minutesToTime(totalMinutes: number): string {\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n }\n\n private async fetchBuffer(url: string): Promise<Buffer> {\n try {\n const response = await globalThis.fetch(url);\n if (!response.ok) {\n throw new NetworkError(`Comcigan request failed with HTTP ${response.status}.`);\n }\n return Buffer.from(await response.arrayBuffer());\n } catch (error) {\n if (error instanceof NetworkError || error instanceof UpstreamChangedError) {\n throw error;\n }\n throw new NetworkError('Comcigan request failed.', error);\n }\n }\n\n private meta(): ProviderMetadata {\n return {\n provider: 'comcigan',\n fetchedAt: new Date().toISOString(),\n };\n }\n\n private dataStatus(): DataStatus {\n return {\n accessMode: 'unofficial',\n complete: true,\n sourceProviders: ['comcigan'],\n };\n }\n\n private async loadRouteInfo(): Promise<ComciganRouteInfo> {\n const today = new Date().toISOString().slice(0, 10);\n if (this.routeCache?.cacheKey === today) {\n return this.routeCache;\n }\n\n const source = await this.fetchRouteSource();\n const routeInfo = this.parseRouteInfo(source, today);\n this.routeCache = routeInfo;\n return routeInfo;\n }\n\n private async fetchRouteSource(): Promise<string> {\n let lastSource = '';\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const buffer = await this.fetchBuffer(`${this.baseUrl}${ST_PATH}`);\n lastSource = this.stripNulls(iconv.decode(buffer, 'euc-kr'));\n if (!lastSource.includes('refresh')) {\n return lastSource;\n }\n }\n\n return lastSource;\n }\n\n private parseRouteInfo(source: string, cacheKey: string): ComciganRouteInfo {\n const mainRoute = source.match(/(?<=\\.\\/)\\d+(?=\\?\\d+l)/)?.[0];\n const searchRoute = source.match(/(?<=\\?)\\d+(?=l)/)?.[0];\n const dataPrefix = source.match(/sc_data\\('([^']+)'/)?.[1];\n\n if (!mainRoute || !searchRoute || !dataPrefix) {\n throw new UpstreamChangedError('Comcigan route page no longer exposes the expected search/data routes.');\n }\n\n return {\n mainRoute,\n searchRoute,\n dataPrefix,\n cacheKey,\n };\n }\n\n private resolveSplitValue(raw: RawComciganData, teacherCount: number): number {\n const splitValue = Number(raw[KEY_SPLIT]);\n if (Number.isFinite(splitValue) && splitValue > 1) {\n return splitValue;\n }\n\n const digits = Math.max(2, String(Math.max(teacherCount - 1, 0)).length);\n return 10 ** digits;\n }\n\n private extractNumericClassTimes(candidate: unknown[]): ClassTimeSlot[] | undefined {\n const slots: ClassTimeSlot[] = [];\n\n for (let index = 0; index < candidate.length; index++) {\n const entry = candidate[index];\n if (!Array.isArray(entry) || entry.length < 2) {\n continue;\n }\n\n const start = Number(entry[0]);\n const end = Number(entry[1]);\n if (!Number.isFinite(start) || !Number.isFinite(end)) {\n continue;\n }\n\n slots.push({\n period: index + 1,\n startTime: this.minutesToTime(start),\n endTime: this.minutesToTime(end),\n });\n }\n\n return slots.length ? slots : undefined;\n }\n\n private extractStringClassTimes(candidate: unknown[]): ClassTimeSlot[] {\n const parsed = candidate\n .map((entry, index) => this.parseClassTimeString(entry, index + 1))\n .filter((entry): entry is { period: number; startTime: string } => entry != null);\n\n return parsed.map((entry, index) => ({\n period: entry.period,\n startTime: entry.startTime,\n endTime: parsed[index + 1]?.startTime ?? entry.startTime,\n }));\n }\n\n private parseClassTimeString(\n entry: unknown,\n defaultPeriod: number,\n ): { period: number; startTime: string } | undefined {\n if (typeof entry !== 'string') {\n return undefined;\n }\n\n const match = entry.match(/^\\s*(\\d+)\\((\\d{1,2}:\\d{2})\\)\\s*$/);\n if (match) {\n return {\n period: Number(match[1]) || defaultPeriod,\n startTime: match[2],\n };\n }\n\n const timeMatch = entry.match(/(\\d{1,2}:\\d{2})/);\n if (!timeMatch) {\n return undefined;\n }\n\n return {\n period: defaultPeriod,\n startTime: timeMatch[1],\n };\n }\n\n private lookupOriginalCode(\n data: ParsedSchoolData,\n grade: number,\n classNo: number,\n weekday: number,\n period: number,\n ): number | undefined {\n const gradeData = data.originalTimetable[grade];\n if (!Array.isArray(gradeData)) {\n return undefined;\n }\n\n const classData = gradeData[classNo];\n if (!Array.isArray(classData)) {\n return undefined;\n }\n\n const dayData = classData[weekday];\n if (!Array.isArray(dayData)) {\n return undefined;\n }\n\n const encoded = Number(dayData[period] ?? 0);\n return encoded || undefined;\n }\n}\n\ninterface ParsedSchoolData {\n school: SchoolRef;\n teacherNames: string[];\n subjects: string[];\n gradeCount: number;\n classCounts: Record<number, number>;\n splitValue: number;\n originalTimetable: unknown[];\n currentTimetable: unknown[];\n classTimes?: ClassTimeSlot[];\n}\n\ninterface ComciganRouteInfo {\n mainRoute: string;\n searchRoute: string;\n dataPrefix: string;\n cacheKey: string;\n}\n", "import type {\n DailyMealService,\n DailyMeals,\n DataStatus,\n KampusProvider,\n MealItem,\n ProviderCapability,\n ProviderMetadata,\n ProviderWarning,\n SchoolInfo,\n SchoolRef,\n SchoolSearchResult,\n WeeklyMeals,\n} from '@kampus/core';\nimport {\n MealsUnavailableError,\n NetworkError,\n ProviderUnavailableError,\n SchoolNotFoundError,\n formatDate,\n getMonday,\n readKampusCacheEntry,\n touchKampusCacheEntry,\n weekdayName,\n writeKampusCacheEntry,\n} from '@kampus/core';\n\nconst NEIS_BASE = 'https://open.neis.go.kr/hub';\n\ntype NeisRow = Record<string, string>;\ntype NeisQueryValue = string | number | undefined;\n\nexport type NeisDatasetName =\n | 'schoolInfo'\n | 'mealServiceDietInfo'\n | 'classInfo'\n | 'schoolMajorinfo'\n | 'schulAflcoinfo'\n | 'SchoolSchedule'\n | 'elsTimetable'\n | 'misTimetable'\n | 'hisTimetable'\n | 'spsTimetable'\n | 'tiClrminfo'\n | 'acaInsTiInfo';\n\nexport interface NeisDatasetResult<T> {\n rows: T[];\n totalCount?: number;\n providerMetadata?: ProviderMetadata;\n dataStatus: DataStatus;\n}\n\nexport interface NeisClassInfoRecord {\n year?: string;\n grade?: number;\n className?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisMajorInfoRecord {\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisTrackInfoRecord {\n dayNightCourseName?: string;\n trackName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisAcademicScheduleRecord {\n date?: string;\n eventName?: string;\n eventContent?: string;\n schoolYear?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n gradeEventYears: number[];\n raw: NeisRow;\n}\n\nexport interface NeisOfficialTimetableRecord {\n date?: string;\n year?: string;\n semester?: string;\n grade?: number;\n className?: string;\n period?: number;\n content?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n classroomName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisClassroomInfoRecord {\n year?: string;\n grade?: number;\n semester?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n classroomName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisAcademyInfoRecord {\n academyName?: string;\n academyNumber?: string;\n adminZoneName?: string;\n fieldName?: string;\n seriesName?: string;\n courseName?: string;\n raw: NeisRow;\n}\n\nexport interface NeisProviderOptions {\n apiKey?: string;\n maxAutoPages?: number;\n cachePath?: string;\n cacheTtlMs?: number;\n staleIfErrorMs?: number;\n cacheMaxEntries?: number;\n}\n\ntype NeisTimetableServiceName = 'elsTimetable' | 'misTimetable' | 'hisTimetable' | 'spsTimetable';\n\ninterface OfficialTimetableQueryParams {\n school: SchoolRef;\n year?: string;\n semester?: string;\n date?: string;\n fromDate?: string;\n toDate?: string;\n dayNightCourseName?: string;\n schoolCourseName?: string;\n grade?: number;\n className?: string;\n period?: number;\n trackName?: string;\n departmentName?: string;\n classroomName?: string;\n}\n\ninterface OfficialTimetableProbe {\n year?: number;\n date?: string;\n}\n\ninterface NeisDatasetEnvelope {\n rows: NeisRow[];\n totalCount?: number;\n providerMetadata?: ProviderMetadata;\n dataStatus: DataStatus;\n}\n\nexport class NeisProvider implements KampusProvider {\n readonly name = 'neis';\n readonly capabilities: ReadonlySet<ProviderCapability> = new Set([\n 'schoolSearch',\n 'schoolInfo',\n 'meals',\n ]);\n\n private readonly apiKey: string;\n private readonly maxAutoPages: number;\n private readonly cachePath?: string;\n private readonly cacheTtlMs: number;\n private readonly staleIfErrorMs: number;\n private readonly cacheMaxEntries: number;\n\n constructor(options?: NeisProviderOptions) {\n this.apiKey = options?.apiKey?.trim() ?? process.env.NEIS_API_KEY?.trim() ?? '';\n this.maxAutoPages = Math.max(1, options?.maxAutoPages ?? 25);\n this.cachePath = options?.cachePath;\n this.cacheTtlMs = Math.max(0, options?.cacheTtlMs ?? 15 * 60 * 1000);\n this.staleIfErrorMs = Math.max(0, options?.staleIfErrorMs ?? 24 * 60 * 60 * 1000);\n this.cacheMaxEntries = Math.max(1, options?.cacheMaxEntries ?? 250);\n }\n\n async searchSchools(keyword: string): Promise<SchoolSearchResult[]> {\n const result = await this.requestDataset(\n 'schoolInfo',\n this.createQuery({\n SCHUL_NM: keyword,\n pSize: 30,\n }),\n );\n\n return result.rows.map((row) => ({\n name: row.SCHUL_NM,\n region: row.LCTN_SC_NM || row.ATPT_OFCDC_SC_NM,\n schoolType: row.SCHUL_KND_SC_NM,\n providerRefs: {\n neis: {\n officeCode: row.ATPT_OFCDC_SC_CODE,\n schoolCode: row.SD_SCHUL_CODE,\n },\n },\n sourceProviders: ['neis'],\n }));\n }\n\n async getSchoolInfo(school: SchoolRef): Promise<SchoolInfo> {\n const ref = this.getNeisRef(school);\n const result = await this.requestDataset(\n 'schoolInfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n }),\n );\n const row = result.rows[0];\n if (!row) {\n throw new SchoolNotFoundError(school.name);\n }\n\n return {\n name: row.SCHUL_NM,\n region: row.LCTN_SC_NM || row.ATPT_OFCDC_SC_NM,\n schoolType: row.SCHUL_KND_SC_NM,\n providerRefs: {\n neis: ref,\n },\n address: row.ORG_RDNMA,\n phone: row.ORG_TELNO,\n website: row.HMPG_ADRES,\n providerMetadata: result.providerMetadata,\n dataStatus: result.dataStatus,\n warnings: result.dataStatus.warnings,\n };\n }\n\n async getMealsToday(params: {\n school: SchoolRef;\n date?: string;\n }): Promise<DailyMeals> {\n const ref = this.getNeisRef(params.school);\n const date = params.date ?? formatDate(new Date());\n const result = await this.requestDataset(\n 'mealServiceDietInfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n MLSV_YMD: date.replace(/-/g, ''),\n }),\n );\n\n if (!result.rows.length) {\n throw new MealsUnavailableError(`No meals were published for ${date}.`);\n }\n\n return this.parseDailyMeals(result.rows, date, result.providerMetadata, result.dataStatus);\n }\n\n async getMealsWeek(params: {\n school: SchoolRef;\n weekOffset?: number;\n date?: string;\n }): Promise<WeeklyMeals> {\n const baseDate = params.date ? new Date(params.date) : new Date();\n if (params.weekOffset) {\n baseDate.setDate(baseDate.getDate() + params.weekOffset * 7);\n }\n\n const monday = getMonday(baseDate);\n const friday = new Date(monday);\n friday.setDate(friday.getDate() + 4);\n\n return this.getMealsRangeInternal({\n school: params.school,\n fromDate: formatDate(monday),\n toDate: formatDate(friday),\n weekStart: formatDate(monday),\n });\n }\n\n async getMealsRange(params: {\n school: SchoolRef;\n fromDate: string;\n toDate: string;\n }): Promise<WeeklyMeals> {\n return this.getMealsRangeInternal(params);\n }\n\n async getDatasetRows(\n serviceName: NeisDatasetName,\n query: Record<string, NeisQueryValue>,\n ): Promise<NeisRow[]> {\n return (await this.getDatasetResult(serviceName, query)).rows;\n }\n\n async getDatasetResult(\n serviceName: NeisDatasetName,\n query: Record<string, NeisQueryValue>,\n ): Promise<NeisDatasetResult<NeisRow>> {\n const result = await this.requestDataset(serviceName, this.createQuery(query));\n return {\n rows: result.rows,\n totalCount: result.totalCount,\n providerMetadata: result.providerMetadata,\n dataStatus: result.dataStatus,\n };\n }\n\n async getClassInfoRows(params: {\n school: SchoolRef;\n year?: string;\n grade?: number;\n dayNightCourseName?: string;\n schoolCourseName?: string;\n trackName?: string;\n departmentName?: string;\n }): Promise<NeisClassInfoRecord[]> {\n return (await this.getClassInfoResult(params)).rows;\n }\n\n async getClassInfoResult(params: {\n school: SchoolRef;\n year?: string;\n grade?: number;\n dayNightCourseName?: string;\n schoolCourseName?: string;\n trackName?: string;\n departmentName?: string;\n }): Promise<NeisDatasetResult<NeisClassInfoRecord>> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'classInfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n AY: params.year,\n GRADE: stringifyNumber(params.grade),\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n SCHUL_CRSE_SC_NM: params.schoolCourseName,\n ORD_SC_NM: params.trackName,\n DDDEP_NM: params.departmentName,\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n year: row.AY,\n grade: parseInteger(row.GRADE),\n className: row.CLASS_NM,\n schoolCourseName: row.SCHUL_CRSE_SC_NM,\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n trackName: row.ORD_SC_NM,\n departmentName: row.DDDEP_NM,\n raw: row,\n }));\n }\n\n async getMajorInfoRows(params: {\n school: SchoolRef;\n dayNightCourseName?: string;\n trackName?: string;\n }): Promise<NeisMajorInfoRecord[]> {\n return (await this.getMajorInfoResult(params)).rows;\n }\n\n async getMajorInfoResult(params: {\n school: SchoolRef;\n dayNightCourseName?: string;\n trackName?: string;\n }): Promise<NeisDatasetResult<NeisMajorInfoRecord>> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'schoolMajorinfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n ORD_SC_NM: params.trackName,\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n trackName: row.ORD_SC_NM,\n departmentName: row.DDDEP_NM,\n raw: row,\n }));\n }\n\n async getTrackInfoRows(params: {\n school: SchoolRef;\n dayNightCourseName?: string;\n }): Promise<NeisTrackInfoRecord[]> {\n return (await this.getTrackInfoResult(params)).rows;\n }\n\n async getTrackInfoResult(params: {\n school: SchoolRef;\n dayNightCourseName?: string;\n }): Promise<NeisDatasetResult<NeisTrackInfoRecord>> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'schulAflcoinfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n trackName: row.ORD_SC_NM,\n raw: row,\n }));\n }\n\n async getAcademicScheduleRows(params: {\n school: SchoolRef;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n date?: string;\n fromDate?: string;\n toDate?: string;\n }): Promise<NeisAcademicScheduleRecord[]> {\n return (await this.getAcademicScheduleResult(params)).rows;\n }\n\n async getAcademicScheduleResult(params: {\n school: SchoolRef;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n date?: string;\n fromDate?: string;\n toDate?: string;\n }): Promise<NeisDatasetResult<NeisAcademicScheduleRecord>> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'SchoolSchedule',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n SCHUL_CRSE_SC_NM: params.schoolCourseName,\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n AA_YMD: compactDate(params.date),\n AA_FROM_YMD: compactDate(params.fromDate),\n AA_TO_YMD: compactDate(params.toDate),\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n date: expandDate(row.AA_YMD),\n eventName: row.EVENT_NM,\n eventContent: row.EVENT_CNTNT,\n schoolYear: row.AY,\n schoolCourseName: row.SCHUL_CRSE_SC_NM,\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n gradeEventYears: extractGradeEventYears(row),\n raw: row,\n }));\n }\n\n async getOfficialTimetableRows(params: OfficialTimetableQueryParams): Promise<NeisOfficialTimetableRecord[]> {\n return (await this.getOfficialTimetableResult(params)).rows;\n }\n\n async getOfficialTimetableResult(\n params: OfficialTimetableQueryParams,\n ): Promise<NeisDatasetResult<NeisOfficialTimetableRecord>> {\n const ref = this.getNeisRef(params.school);\n const serviceName = await this.resolveTimetableServiceName(params.school);\n const result = await this.requestDataset(\n serviceName,\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n AY: params.year,\n SEM: params.semester,\n ALL_TI_YMD: compactDate(params.date),\n TI_FROM_YMD: compactDate(params.fromDate),\n TI_TO_YMD: compactDate(params.toDate),\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n SCHUL_CRSE_SC_NM: params.schoolCourseName,\n GRADE: stringifyNumber(params.grade),\n CLASS_NM: params.className,\n PERIO: stringifyNumber(params.period),\n ORD_SC_NM: params.trackName,\n DDDEP_NM: params.departmentName,\n CLRM_NM: params.classroomName,\n }),\n );\n\n const diagnosedResult = await this.diagnoseOfficialTimetableResult(result, params, serviceName);\n\n return this.mapDatasetResult(diagnosedResult, (row) => ({\n date: expandDate(row.ALL_TI_YMD),\n year: row.AY,\n semester: row.SEM,\n grade: parseInteger(row.GRADE),\n className: row.CLASS_NM,\n period: parseInteger(row.PERIO),\n content: row.ITRT_CNTNT,\n schoolCourseName: row.SCHUL_CRSE_SC_NM,\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n trackName: row.ORD_SC_NM,\n departmentName: row.DDDEP_NM,\n classroomName: row.CLRM_NM,\n raw: row,\n }));\n }\n\n async getClassroomInfoRows(params: {\n school: SchoolRef;\n year?: string;\n grade?: number;\n semester?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n }): Promise<NeisClassroomInfoRecord[]> {\n return (await this.getClassroomInfoResult(params)).rows;\n }\n\n async getClassroomInfoResult(params: {\n school: SchoolRef;\n year?: string;\n grade?: number;\n semester?: string;\n schoolCourseName?: string;\n dayNightCourseName?: string;\n trackName?: string;\n departmentName?: string;\n }): Promise<NeisDatasetResult<NeisClassroomInfoRecord>> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'tiClrminfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n AY: params.year,\n GRADE: stringifyNumber(params.grade),\n SEM: params.semester,\n SCHUL_CRSE_SC_NM: params.schoolCourseName,\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n ORD_SC_NM: params.trackName,\n DDDEP_NM: params.departmentName,\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n year: row.AY,\n grade: parseInteger(row.GRADE),\n semester: row.SEM,\n schoolCourseName: row.SCHUL_CRSE_SC_NM,\n dayNightCourseName: row.DGHT_CRSE_SC_NM,\n trackName: row.ORD_SC_NM,\n departmentName: row.DDDEP_NM,\n classroomName: row.CLRM_NM,\n raw: row,\n }));\n }\n\n async searchAcademyInfoRows(params: {\n officeCode?: string;\n adminZoneName?: string;\n academyNumber?: string;\n academyName?: string;\n fieldName?: string;\n seriesName?: string;\n courseName?: string;\n }): Promise<NeisAcademyInfoRecord[]> {\n return (await this.searchAcademyInfoResult(params)).rows;\n }\n\n async searchAcademyInfoResult(params: {\n officeCode?: string;\n adminZoneName?: string;\n academyNumber?: string;\n academyName?: string;\n fieldName?: string;\n seriesName?: string;\n courseName?: string;\n }): Promise<NeisDatasetResult<NeisAcademyInfoRecord>> {\n const result = await this.requestDataset(\n 'acaInsTiInfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: params.officeCode,\n ADMST_ZONE_NM: params.adminZoneName,\n ACA_ASNUM: params.academyNumber,\n ACA_NM: params.academyName,\n REALM_SC_NM: params.fieldName,\n LE_ORD_NM: params.seriesName,\n LE_CRSE_NM: params.courseName,\n }),\n );\n\n return this.mapDatasetResult(result, (row) => ({\n academyName: row.ACA_NM,\n academyNumber: row.ACA_ASNUM,\n adminZoneName: row.ADMST_ZONE_NM,\n fieldName: row.REALM_SC_NM,\n seriesName: row.LE_ORD_NM,\n courseName: row.LE_CRSE_NM,\n raw: row,\n }));\n }\n\n private getNeisRef(school: SchoolRef) {\n const ref = school.providerRefs.neis;\n if (!ref) {\n throw new MealsUnavailableError(\n `NEIS school reference is missing for \"${school.name}\". Resolve the school through search first.`,\n );\n }\n return ref;\n }\n\n private async getMealsRangeInternal(params: {\n school: SchoolRef;\n fromDate: string;\n toDate: string;\n weekStart?: string;\n }): Promise<WeeklyMeals> {\n const ref = this.getNeisRef(params.school);\n const result = await this.requestDataset(\n 'mealServiceDietInfo',\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n MLSV_FROM_YMD: compactDate(params.fromDate),\n MLSV_TO_YMD: compactDate(params.toDate),\n }),\n );\n\n const grouped = new Map<string, NeisRow[]>();\n for (const row of result.rows) {\n const rawDate = row.MLSV_YMD;\n if (!rawDate || rawDate.length !== 8) {\n continue;\n }\n\n const isoDate = `${rawDate.slice(0, 4)}-${rawDate.slice(4, 6)}-${rawDate.slice(6, 8)}`;\n const bucket = grouped.get(isoDate);\n if (bucket) {\n bucket.push(row);\n } else {\n grouped.set(isoDate, [row]);\n }\n }\n\n const days = [...grouped.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([date, rows]) => this.parseDailyMeals(rows, date));\n\n if (!days.length) {\n throw new MealsUnavailableError(\n `No meals were published between ${params.fromDate} and ${params.toDate}.`,\n );\n }\n\n return {\n school: {\n ...params.school,\n providerRefs: {\n ...params.school.providerRefs,\n neis: ref,\n },\n },\n weekStart: params.weekStart,\n fromDate: params.fromDate,\n toDate: params.toDate,\n days,\n providerMetadata: result.providerMetadata,\n dataStatus: result.dataStatus,\n warnings: result.dataStatus.warnings,\n };\n }\n\n private parseDailyMeals(\n rows: NeisRow[],\n date: string,\n providerMetadata?: ProviderMetadata,\n dataStatus?: DataStatus,\n ): DailyMeals {\n return {\n date,\n weekdayName: weekdayName(new Date(date).getDay() || 7),\n meals: rows.map((row) => this.parseMealService(row)),\n providerMetadata,\n dataStatus,\n warnings: dataStatus?.warnings,\n };\n }\n\n private parseMealService(row: NeisRow): DailyMealService {\n return {\n type: row.MMEAL_SC_NM,\n mealCode: row.MMEAL_SC_CODE,\n items: this.parseDishNames(row.DDISH_NM ?? ''),\n calories: row.CAL_INFO || undefined,\n nutritionInfo: row.NTR_INFO || undefined,\n originInfo: row.ORPLC_INFO || undefined,\n rawMenuText: row.DDISH_NM || undefined,\n rawRow: row,\n };\n }\n\n private parseDishNames(raw: string): MealItem[] {\n if (!raw.trim()) {\n return [];\n }\n\n return raw\n .split(/<br\\/?>/i)\n .map((line) => line.replace(/\\*/g, '').trim())\n .filter(Boolean)\n .map((line) => {\n const allergyMatch = line.match(/\\(([0-9.]+)\\)\\s*$/);\n return {\n name: line.replace(/\\s*\\([0-9.]+\\)\\s*$/, '').trim(),\n allergyCodes: allergyMatch\n ? allergyMatch[1]\n .split('.')\n .map((value) => Number(value))\n .filter((value) => Number.isInteger(value))\n : undefined,\n };\n })\n .filter((item) => item.name.length > 0);\n }\n\n private createQuery(query: Record<string, NeisQueryValue>): URLSearchParams {\n const params = new URLSearchParams({\n Type: 'json',\n pSize: '1000',\n });\n\n if (this.apiKey) {\n params.set('KEY', this.apiKey);\n }\n\n for (const [key, value] of Object.entries(query)) {\n if (value == null) {\n continue;\n }\n const stringValue = `${value}`.trim();\n if (!stringValue) {\n continue;\n }\n params.set(key, stringValue);\n }\n\n return params;\n }\n\n private async resolveTimetableServiceName(\n school: SchoolRef,\n ): Promise<NeisTimetableServiceName> {\n const schoolType = (\n school.schoolType ??\n (await this.getSchoolInfo(school)).schoolType ??\n ''\n ).replace(/\\s+/g, '');\n\n if (schoolType.includes('\\uCD08\\uB4F1\\uD559\\uAD50')) {\n return 'elsTimetable';\n }\n if (schoolType.includes('\\uC911\\uD559\\uAD50')) {\n return 'misTimetable';\n }\n if (schoolType.includes('\\uD2B9\\uC218\\uD559\\uAD50')) {\n return 'spsTimetable';\n }\n return 'hisTimetable';\n }\n\n private async diagnoseOfficialTimetableResult(\n result: NeisDatasetEnvelope,\n params: OfficialTimetableQueryParams,\n serviceName: NeisTimetableServiceName,\n ): Promise<NeisDatasetEnvelope> {\n if (result.rows.length > 0) {\n return result;\n }\n\n const warnings: ProviderWarning[] = [\n {\n provider: 'neis',\n code: 'NEIS_TIMETABLE_NO_DATA',\n message: 'NEIS returned no official timetable rows for this query.',\n },\n ];\n\n const requestedYear = detectRequestedAcademicYear(params);\n if (requestedYear != null && requestedYear > 1) {\n try {\n const sameYearSample = await this.probeOfficialTimetableYear(params, serviceName, requestedYear);\n if (sameYearSample) {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_TIMETABLE_FILTER_NO_MATCH',\n message:\n `No official timetable rows matched this exact query, but NEIS does expose timetable data for academic year ${sameYearSample.year ?? requestedYear}. ` +\n `The requested date, class, or period filters may be too narrow.${sameYearSample.date ? ` Sample row date: ${sameYearSample.date}.` : ''}`,\n });\n } else {\n const previousYearSample = await this.probeOfficialTimetableYear(\n params,\n serviceName,\n requestedYear - 1,\n );\n if (previousYearSample) {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_TIMETABLE_YEAR_LAG',\n message:\n `No official timetable rows matched academic year ${requestedYear}. ` +\n `This school currently appears to expose ${previousYearSample.year ?? requestedYear - 1} timetable data in NEIS.` +\n `${previousYearSample.date ? ` Sample row date: ${previousYearSample.date}.` : ''}`,\n });\n }\n }\n } catch {\n // Diagnostic probes are best-effort and should not turn an empty result into a hard failure.\n }\n }\n\n return this.withMergedWarnings(result, warnings);\n }\n\n private async requestDataset(serviceName: NeisDatasetName, params: URLSearchParams): Promise<NeisDatasetEnvelope> {\n const cacheKey = this.buildCacheKey(serviceName, params);\n const cachedRead = this.cachePath\n ? readKampusCacheEntry<NeisDatasetEnvelope>(cacheKey, { cachePath: this.cachePath })\n : { state: 'missing' as const };\n const cacheState = this.resolveCacheState(cachedRead.entry);\n\n if (cacheState === 'fresh' && cachedRead.entry?.value) {\n touchKampusCacheEntry(cacheKey, { cachePath: this.cachePath });\n return this.withCacheState(cachedRead.entry.value, 'fresh');\n }\n\n try {\n const firstPage = await this.fetchDatasetPage(serviceName, params);\n const aggregated = await this.fetchRemainingPages(serviceName, params, firstPage);\n const dataStatus = this.buildDataStatus(aggregated.totalCount, aggregated.rows.length, {\n pageLimitReached: aggregated.pageLimitReached,\n });\n\n const envelope: NeisDatasetEnvelope = {\n rows: aggregated.rows,\n totalCount: aggregated.totalCount,\n dataStatus,\n providerMetadata: this.meta(dataStatus),\n };\n\n this.storeEnvelope(cacheKey, envelope, serviceName, params);\n return envelope;\n } catch (error) {\n if (cacheState === 'stale' && cachedRead.entry?.value) {\n touchKampusCacheEntry(cacheKey, { cachePath: this.cachePath });\n return this.withCacheState(cachedRead.entry.value, 'stale');\n }\n throw error;\n }\n }\n\n private async probeOfficialTimetableYear(\n params: OfficialTimetableQueryParams,\n serviceName: NeisTimetableServiceName,\n year: number,\n ): Promise<OfficialTimetableProbe | null> {\n if (!Number.isInteger(year) || year < 1) {\n return null;\n }\n\n const ref = this.getNeisRef(params.school);\n const result = await this.fetchDatasetPage(\n serviceName,\n this.createQuery({\n ATPT_OFCDC_SC_CODE: ref.officeCode,\n SD_SCHUL_CODE: ref.schoolCode,\n AY: String(year),\n SCHUL_CRSE_SC_NM: params.schoolCourseName,\n DGHT_CRSE_SC_NM: params.dayNightCourseName,\n ORD_SC_NM: params.trackName,\n DDDEP_NM: params.departmentName,\n pSize: 1,\n }),\n );\n\n const row = result.rows[0];\n if (!row) {\n return null;\n }\n\n return {\n year: parseInteger(row.AY) ?? year,\n date: expandDate(row.ALL_TI_YMD),\n };\n }\n\n private withMergedWarnings(\n result: NeisDatasetEnvelope,\n extraWarnings: ProviderWarning[],\n ): NeisDatasetEnvelope {\n const mergedWarnings = dedupeWarnings([...(result.dataStatus.warnings ?? []), ...extraWarnings]);\n const dataStatus: DataStatus = {\n ...result.dataStatus,\n warnings: mergedWarnings.length ? mergedWarnings : undefined,\n };\n\n return {\n ...result,\n dataStatus,\n providerMetadata: result.providerMetadata\n ? {\n ...result.providerMetadata,\n warnings: dataStatus.warnings?.map((warning) => warning.message),\n }\n : this.meta(dataStatus),\n };\n }\n\n private buildDataStatus(\n totalCount: number | undefined,\n rowCount: number,\n options?: { pageLimitReached?: boolean; cacheState?: 'fresh' | 'stale' },\n ): DataStatus {\n const warnings: ProviderWarning[] = [];\n const complete = totalCount == null || totalCount <= rowCount;\n\n if (!this.apiKey) {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_KEYLESS_LIMITED',\n message:\n 'NEIS is running without an API key. The official sample mode may return at most a small subset of rows.',\n });\n }\n\n if (totalCount != null && totalCount > rowCount) {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_TRUNCATED',\n message: `NEIS returned ${rowCount} row(s) out of ${totalCount}. Add a NEIS API key or narrow the query for a complete result.`,\n });\n }\n\n if (options?.pageLimitReached) {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_PAGE_LIMIT',\n message: `NEIS auto-pagination stopped after ${this.maxAutoPages} page(s). Narrow the query or increase the page limit in the provider configuration.`,\n });\n }\n\n if (options?.cacheState === 'stale') {\n warnings.push({\n provider: 'neis',\n code: 'NEIS_STALE_CACHE',\n message:\n 'Kampus returned a stale cached NEIS response because the live request failed. Re-run later to refresh the official data.',\n });\n }\n\n return {\n accessMode: this.apiKey ? 'official-full' : 'official-limited',\n complete,\n sourceProviders: ['neis'],\n warnings: warnings.length ? warnings : undefined,\n };\n }\n\n private async fetchRemainingPages(\n serviceName: NeisDatasetName,\n params: URLSearchParams,\n firstPage: { rows: NeisRow[]; totalCount?: number },\n ): Promise<{ rows: NeisRow[]; totalCount?: number; pageLimitReached: boolean }> {\n const totalCount = firstPage.totalCount;\n if (!this.apiKey || totalCount == null || totalCount <= firstPage.rows.length) {\n return {\n rows: firstPage.rows,\n totalCount,\n pageLimitReached: false,\n };\n }\n\n const pageSize = Math.max(parseInteger(params.get('pSize') ?? undefined) ?? 1000, 1);\n const startPage = Math.max(parseInteger(params.get('pIndex') ?? undefined) ?? 1, 1);\n const totalPages = Math.max(Math.ceil(totalCount / pageSize), startPage);\n const lastPage = Math.min(totalPages, startPage + this.maxAutoPages - 1);\n const rows = [...firstPage.rows];\n\n for (let page = startPage + 1; page <= lastPage && rows.length < totalCount; page += 1) {\n const pageParams = new URLSearchParams(params);\n pageParams.set('pIndex', String(page));\n const nextPage = await this.fetchDatasetPage(serviceName, pageParams);\n if (!nextPage.rows.length) {\n break;\n }\n rows.push(...nextPage.rows);\n }\n\n return {\n rows: rows.slice(0, totalCount),\n totalCount,\n pageLimitReached: lastPage < totalPages && rows.length < totalCount,\n };\n }\n\n private async fetchDatasetPage(\n serviceName: NeisDatasetName,\n params: URLSearchParams,\n ): Promise<{ rows: NeisRow[]; totalCount?: number }> {\n const payload = await this.fetchJson(`${NEIS_BASE}/${serviceName}?${params}`);\n const apiError = this.extractApiError(payload, serviceName);\n if (apiError) {\n if (apiError.code === 'INFO-200') {\n return {\n rows: [],\n totalCount: 0,\n };\n }\n\n if (apiError.code === 'ERROR-290') {\n if (!this.apiKey) {\n throw new ProviderUnavailableError(\n 'neis',\n undefined,\n 'NEIS sample mode is currently unavailable. Configure a NEIS API key and retry.',\n );\n }\n\n throw new ProviderUnavailableError(\n 'neis',\n undefined,\n 'NEIS_API_KEY is missing or invalid. Set a valid NEIS API key to use NEIS-backed features.',\n );\n }\n\n throw new ProviderUnavailableError(\n 'neis',\n undefined,\n `NEIS API error ${apiError.code}: ${apiError.message}`,\n );\n }\n\n return {\n rows: this.extractRows(payload, serviceName),\n totalCount: this.extractTotalCount(payload, serviceName),\n };\n }\n\n private async fetchJson(url: string): Promise<unknown> {\n try {\n const response = await globalThis.fetch(url);\n if (!response.ok) {\n throw new NetworkError(`NEIS request failed with HTTP ${response.status}.`);\n }\n return response.json();\n } catch (error) {\n if (error instanceof NetworkError) {\n throw error;\n }\n throw new NetworkError('NEIS request failed.', error);\n }\n }\n\n private extractRows(payload: unknown, serviceName: string): NeisRow[] {\n const service = (payload as Record<string, unknown>)[serviceName];\n if (!Array.isArray(service)) {\n return [];\n }\n\n const rowBlock = service.find(\n (entry): entry is { row?: NeisRow[] } =>\n typeof entry === 'object' && entry !== null && 'row' in entry,\n );\n\n return rowBlock?.row ?? [];\n }\n\n private extractTotalCount(payload: unknown, serviceName: string): number | undefined {\n const service = (payload as Record<string, unknown>)[serviceName];\n if (!Array.isArray(service)) {\n return undefined;\n }\n\n for (const entry of service) {\n if (!entry || typeof entry !== 'object' || !('head' in entry)) {\n continue;\n }\n\n const head = (entry as { head?: unknown }).head;\n if (!Array.isArray(head)) {\n continue;\n }\n\n for (const headEntry of head) {\n if (!headEntry || typeof headEntry !== 'object') {\n continue;\n }\n\n const count = (headEntry as { list_total_count?: unknown }).list_total_count;\n const parsed = Number(count);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n }\n\n return undefined;\n }\n\n private extractApiError(payload: unknown, serviceName: string): { code: string; message: string } | null {\n const topLevel = (payload as Record<string, unknown>).RESULT;\n const parsedTopLevel = this.parseApiErrorBlock(topLevel);\n if (parsedTopLevel) {\n return parsedTopLevel;\n }\n\n const service = (payload as Record<string, unknown>)[serviceName];\n if (!Array.isArray(service)) {\n return null;\n }\n\n for (const entry of service) {\n if (!entry || typeof entry !== 'object' || !('head' in entry)) {\n continue;\n }\n\n const head = (entry as { head?: unknown }).head;\n if (!Array.isArray(head)) {\n continue;\n }\n\n for (const headEntry of head) {\n if (!headEntry || typeof headEntry !== 'object' || !('RESULT' in headEntry)) {\n continue;\n }\n\n const result = this.parseApiErrorBlock((headEntry as { RESULT?: unknown }).RESULT);\n if (result && result.code !== 'INFO-000') {\n return result;\n }\n }\n }\n\n return null;\n }\n\n private parseApiErrorBlock(value: unknown): { code: string; message: string } | null {\n if (!value || typeof value !== 'object') {\n return null;\n }\n\n const code = (value as Record<string, unknown>).CODE;\n const message = (value as Record<string, unknown>).MESSAGE;\n if (typeof code === 'string' && typeof message === 'string') {\n return { code, message };\n }\n\n return null;\n }\n\n private mapDatasetResult<T>(\n result: NeisDatasetEnvelope,\n mapper: (row: NeisRow) => T,\n ): NeisDatasetResult<T> {\n return {\n rows: result.rows.map(mapper),\n totalCount: result.totalCount,\n providerMetadata: result.providerMetadata,\n dataStatus: result.dataStatus,\n };\n }\n\n private meta(dataStatus: DataStatus): ProviderMetadata {\n return {\n provider: 'neis',\n fetchedAt: new Date().toISOString(),\n warnings: dataStatus.warnings?.map((warning: ProviderWarning) => warning.message),\n };\n }\n\n private withCacheState(\n envelope: NeisDatasetEnvelope,\n cacheState: 'fresh' | 'stale',\n ): NeisDatasetEnvelope {\n const warnings =\n cacheState === 'stale'\n ? dedupeWarnings([\n ...(envelope.dataStatus.warnings ?? []),\n {\n provider: 'neis',\n code: 'NEIS_STALE_CACHE',\n message:\n 'Kampus returned a stale cached NEIS response because the live request failed. Re-run later to refresh the official data.',\n },\n ])\n : envelope.dataStatus.warnings;\n\n return {\n ...envelope,\n dataStatus: {\n ...envelope.dataStatus,\n warnings,\n },\n providerMetadata: {\n ...(envelope.providerMetadata ?? this.meta(envelope.dataStatus)),\n cached: true,\n warnings: warnings?.map((warning) => warning.message),\n },\n };\n }\n\n private storeEnvelope(\n cacheKey: string,\n envelope: NeisDatasetEnvelope,\n serviceName: NeisDatasetName,\n params: URLSearchParams,\n ): void {\n if (!this.cachePath || (this.cacheTtlMs <= 0 && this.staleIfErrorMs <= 0)) {\n return;\n }\n\n const now = new Date();\n const expiresAt =\n this.cacheTtlMs > 0 ? new Date(now.getTime() + this.cacheTtlMs).toISOString() : undefined;\n const staleUntil =\n this.staleIfErrorMs > 0\n ? new Date(now.getTime() + Math.max(this.cacheTtlMs, 0) + this.staleIfErrorMs).toISOString()\n : undefined;\n\n writeKampusCacheEntry<NeisDatasetEnvelope>(\n {\n key: cacheKey,\n value: envelope,\n storedAt: now.toISOString(),\n expiresAt,\n staleUntil,\n meta: {\n provider: 'neis',\n serviceName,\n params: params.toString(),\n },\n },\n {\n cachePath: this.cachePath,\n maxEntries: this.cacheMaxEntries,\n },\n );\n }\n\n private resolveCacheState(\n entry?: { storedAt?: string } | undefined,\n ): 'missing' | 'fresh' | 'stale' | 'expired' {\n if (!entry?.storedAt) {\n return 'missing';\n }\n\n const storedAt = Date.parse(entry.storedAt);\n if (!Number.isFinite(storedAt)) {\n return 'expired';\n }\n\n const ageMs = Date.now() - storedAt;\n if (this.cacheTtlMs > 0 && ageMs <= this.cacheTtlMs) {\n return 'fresh';\n }\n\n if (this.staleIfErrorMs > 0 && ageMs <= Math.max(this.cacheTtlMs, 0) + this.staleIfErrorMs) {\n return 'stale';\n }\n\n return 'expired';\n }\n\n private buildCacheKey(serviceName: NeisDatasetName, params: URLSearchParams): string {\n const filtered = new URLSearchParams(params);\n if (filtered.get('KEY')) {\n filtered.set('KEY', this.apiKey ? '__configured__' : '__none__');\n }\n\n const ordered = [...filtered.entries()].sort(([left], [right]) => left.localeCompare(right));\n return `neis:${serviceName}:${new URLSearchParams(ordered).toString()}`;\n }\n}\n\nfunction compactDate(value?: string): string | undefined {\n const trimmed = value?.trim();\n if (!trimmed) {\n return undefined;\n }\n return trimmed.replace(/-/g, '');\n}\n\nfunction expandDate(value?: string): string | undefined {\n if (!value || value.length !== 8) {\n return value || undefined;\n }\n return `${value.slice(0, 4)}-${value.slice(4, 6)}-${value.slice(6, 8)}`;\n}\n\nfunction stringifyNumber(value?: number): string | undefined {\n return value == null ? undefined : String(value);\n}\n\nfunction parseInteger(value?: string): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction detectRequestedAcademicYear(params: OfficialTimetableQueryParams): number | undefined {\n return (\n parseInteger(params.year) ??\n extractYearFromDate(params.date) ??\n extractYearFromDate(params.fromDate) ??\n extractYearFromDate(params.toDate)\n );\n}\n\nfunction extractYearFromDate(value?: string): number | undefined {\n const match = value?.trim().match(/^(\\d{4})/);\n return match ? parseInteger(match[1]) : undefined;\n}\n\nfunction extractGradeEventYears(row: NeisRow): number[] {\n const flags: Array<[number, string | undefined]> = [\n [1, row.ONE_GRADE_EVENT_YN],\n [2, row.TW_GRADE_EVENT_YN],\n [3, row.THREE_GRADE_EVENT_YN],\n [4, row.FR_GRADE_EVENT_YN],\n [5, row.FIV_GRADE_EVENT_YN],\n [6, row.SIX_GRADE_EVENT_YN],\n ];\n\n return flags.filter(([, value]) => value === 'Y').map(([grade]) => grade);\n}\n\nfunction dedupeWarnings(warnings: ProviderWarning[]): ProviderWarning[] {\n return warnings.filter((warning, index, values) => {\n return values.findIndex((candidate) => {\n return (\n candidate.provider === warning.provider &&\n candidate.code === warning.code &&\n candidate.message === warning.message\n );\n }) === index;\n });\n}\n", "import chalk from 'chalk';\nimport type {\n ClassTimeSlot,\n DataStatus,\n DailyMeals,\n DayTimetable,\n PeriodItem,\n ProviderMetadata,\n SchoolInfo,\n SchoolRef,\n SchoolSearchResult,\n SnapshotDiff,\n TeacherInfo,\n TeacherTimetable,\n WeekTimetable,\n WeeklyMeals,\n} from '@kampus/core';\n\nexport type OutputFormat = 'human' | 'json' | 'markdown' | 'yaml' | 'csv' | 'table' | 'ndjson';\n\nexport function getFormat(opts: { format?: string; json?: boolean; markdown?: boolean }): OutputFormat {\n const explicitFormat = opts.format?.trim().toLowerCase();\n if (explicitFormat) {\n if (isOutputFormat(explicitFormat)) {\n return explicitFormat;\n }\n throw new Error(`Unsupported output format \"${opts.format}\".`);\n }\n if (opts.json) {\n return 'json';\n }\n if (opts.markdown) {\n return 'markdown';\n }\n return 'human';\n}\n\nexport function printJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function printStructured(data: unknown, format: Exclude<OutputFormat, 'human' | 'markdown'>): void {\n switch (format) {\n case 'json':\n printJson(data);\n return;\n case 'yaml':\n console.log(renderYaml(data));\n return;\n case 'ndjson':\n printNdjson(data);\n return;\n case 'csv':\n console.log(renderCsv(data));\n return;\n case 'table':\n console.log(renderTable(data));\n return;\n }\n}\n\n/* \u2500\u2500 Chalk helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction accessBadge(mode: string): string {\n switch (mode) {\n case 'official-full':\n return chalk.green.bold('OFFICIAL');\n case 'official-limited':\n return chalk.yellow.bold('LIMITED');\n case 'unofficial':\n return chalk.dim('UNOFFICIAL');\n default:\n return chalk.dim(mode);\n }\n}\n\nfunction completeBadge(complete: boolean): string {\n return complete ? chalk.green('complete') : chalk.yellow('incomplete');\n}\n\nfunction kv(key: string, value: string): string {\n return `${chalk.cyan(key)} ${value}`;\n}\n\nfunction heading(text: string): string {\n return chalk.bold(text);\n}\n\nfunction separator(width = 48): string {\n return chalk.dim('\u2500'.repeat(width));\n}\n\nfunction warningLine(code: string, message: string): string {\n return chalk.yellow(` \u26A0 ${chalk.bold(`[${code}]`)} ${message}`);\n}\n\nfunction renderStatusBanner(value: {\n dataStatus?: DataStatus;\n providerMetadata?: ProviderMetadata;\n}): string[] {\n const lines: string[] = [];\n if (value.dataStatus) {\n const parts = [\n accessBadge(value.dataStatus.accessMode),\n completeBadge(value.dataStatus.complete),\n chalk.dim(`via ${value.dataStatus.sourceProviders.join(', ')}`),\n ];\n if (value.providerMetadata?.cached) {\n parts.push(chalk.blue('cached'));\n }\n lines.push(` ${parts.join(chalk.dim(' \u00B7 '))}`);\n for (const warning of value.dataStatus.warnings ?? []) {\n lines.push(warningLine(warning.code, warning.message));\n }\n } else if (value.providerMetadata?.cached) {\n lines.push(` ${chalk.blue('cached')}`);\n }\n return lines;\n}\n\nfunction printBanner(value: {\n dataStatus?: DataStatus;\n providerMetadata?: ProviderMetadata;\n}): void {\n for (const line of renderStatusBanner(value)) {\n console.log(line);\n }\n}\n\n/* \u2500\u2500 Human label helpers (unchanged contract) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderProviderRefs(school: SchoolRef): string {\n const refs: string[] = [];\n\n if (school.providerRefs.neis) {\n refs.push(`neis:${school.providerRefs.neis.officeCode}/${school.providerRefs.neis.schoolCode}`);\n }\n if (school.providerRefs.comcigan) {\n refs.push(`comcigan:${school.providerRefs.comcigan.schoolCode}`);\n }\n\n return refs.join(', ') || '(unresolved)';\n}\n\nfunction renderProviderRefsColored(school: SchoolRef): string {\n const refs: string[] = [];\n if (school.providerRefs.neis) {\n refs.push(chalk.magenta(`neis:${school.providerRefs.neis.officeCode}/${school.providerRefs.neis.schoolCode}`));\n }\n if (school.providerRefs.comcigan) {\n refs.push(chalk.magenta(`comcigan:${school.providerRefs.comcigan.schoolCode}`));\n }\n return refs.join(chalk.dim(' \u00B7 ')) || chalk.dim('(unresolved)');\n}\n\nfunction renderSchoolLabel(school: Pick<SchoolRef, 'name' | 'region' | 'schoolType'>): string {\n const extras = [school.region, school.schoolType].filter(Boolean).join(', ');\n return extras ? `${school.name} (${extras})` : school.name;\n}\n\nfunction renderSchoolLabelColored(school: Pick<SchoolRef, 'name' | 'region' | 'schoolType'>): string {\n const extras = [school.region, school.schoolType].filter(Boolean).join(', ');\n return extras\n ? `${chalk.bold(school.name)} ${chalk.dim(`(${extras})`)}`\n : chalk.bold(school.name);\n}\n\nfunction renderPeriod(period: PeriodItem): string {\n if (period.isFreePeriod) {\n return '(free)';\n }\n\n const teacher = period.teacher ? ` [${period.teacher}]` : '';\n return `${period.subject}${teacher}`;\n}\n\nfunction renderPeriodColored(period: PeriodItem): string {\n if (period.isFreePeriod) {\n return chalk.dim('(free)');\n }\n if (period.status === 'unknown-subject') {\n const teacher = period.teacher ? chalk.dim(` [${period.teacher}]`) : '';\n return `${chalk.yellow('???')}${teacher}`;\n }\n const teacher = period.teacher ? chalk.dim(` [${period.teacher}]`) : '';\n return `${chalk.white(period.subject)}${teacher}`;\n}\n\nfunction renderStatusLines(value: {\n dataStatus?: DataStatus;\n providerMetadata?: ProviderMetadata;\n}): string[] {\n const lines: string[] = [];\n\n if (value.dataStatus) {\n lines.push(`mode: ${value.dataStatus.accessMode}`);\n lines.push(`complete: ${value.dataStatus.complete ? 'yes' : 'no'}`);\n lines.push(`sources: ${value.dataStatus.sourceProviders.join(', ')}`);\n for (const warning of value.dataStatus.warnings ?? []) {\n lines.push(`warning: [${warning.code}] ${warning.message}`);\n }\n }\n\n if (value.providerMetadata?.cached) {\n lines.push('cached: yes');\n }\n\n return lines;\n}\n\nfunction printStatusLines(\n value: {\n dataStatus?: DataStatus;\n providerMetadata?: ProviderMetadata;\n },\n format: Exclude<OutputFormat, 'json'>,\n): void {\n const lines = renderStatusLines(value);\n if (!lines.length) {\n return;\n }\n\n if (format === 'markdown') {\n for (const line of lines) {\n console.log(`> ${line}`);\n }\n console.log();\n return;\n }\n\n for (const line of lines) {\n console.log(line);\n }\n}\n\n/* \u2500\u2500 Print functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport function printSchoolSearch(results: SchoolSearchResult[], format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(results, format);\n return;\n }\n\n if (!results.length) {\n if (format === 'markdown') {\n console.log('No schools matched.');\n } else {\n console.log(chalk.dim('No schools matched.'));\n }\n return;\n }\n\n if (format === 'markdown') {\n console.log('| School | Type | Provider refs | Sources |');\n console.log('| --- | --- | --- | --- |');\n for (const school of results) {\n console.log(\n `| ${renderSchoolLabel(school)} | ${school.schoolType ?? '-'} | ${renderProviderRefs(\n school,\n )} | ${school.sourceProviders.join(', ')} |`,\n );\n }\n return;\n }\n\n console.log(heading(`Matched ${results.length} school(s)`));\n console.log();\n for (const school of results) {\n console.log(` ${renderSchoolLabelColored(school)}`);\n console.log(` ${renderProviderRefsColored(school)}`);\n console.log(` ${chalk.dim(`sources: ${school.sourceProviders.join(', ')}`)}`);\n console.log();\n }\n}\n\nexport function printSchoolInfo(info: SchoolInfo, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(info, format);\n return;\n }\n\n const lines = [\n `School: ${info.name}`,\n info.region ? `Region: ${info.region}` : undefined,\n info.schoolType ? `Type: ${info.schoolType}` : undefined,\n info.address ? `Address: ${info.address}` : undefined,\n info.phone ? `Phone: ${info.phone}` : undefined,\n info.website ? `Website: ${info.website}` : undefined,\n `Provider refs: ${renderProviderRefs(info)}`,\n info.gradeCount ? `Grades: ${info.gradeCount}` : undefined,\n info.teacherNames?.length ? `Teachers: ${info.teacherNames.length}` : undefined,\n ].filter(Boolean);\n\n if (format === 'markdown') {\n console.log(`# ${info.name}`);\n console.log();\n printStatusLines(info, 'markdown');\n for (const line of lines.slice(1)) {\n console.log(`- ${line}`);\n }\n if (info.classCounts) {\n console.log('- Class counts:');\n for (const [grade, count] of Object.entries(info.classCounts)) {\n console.log(` ${grade}: ${count}`);\n }\n }\n return;\n }\n\n console.log();\n console.log(` ${heading(info.name)}`);\n console.log(` ${separator()}`);\n printBanner(info);\n console.log();\n if (info.region) console.log(` ${kv('Region', info.region)}`);\n if (info.schoolType) console.log(` ${kv('Type', info.schoolType)}`);\n if (info.address) console.log(` ${kv('Address', info.address)}`);\n if (info.phone) console.log(` ${kv('Phone', info.phone)}`);\n if (info.website) console.log(` ${kv('Website', chalk.underline(info.website))}`);\n console.log(` ${kv('Refs', renderProviderRefsColored(info))}`);\n if (info.gradeCount) console.log(` ${kv('Grades', String(info.gradeCount))}`);\n if (info.teacherNames?.length) console.log(` ${kv('Teachers', String(info.teacherNames.length))}`);\n if (info.classCounts) {\n console.log();\n console.log(` ${chalk.dim('Class counts')}`);\n for (const [grade, count] of Object.entries(info.classCounts)) {\n console.log(` ${chalk.cyan(`grade ${grade}`)} ${count}`);\n }\n }\n console.log();\n}\n\nexport function printDayTimetable(day: DayTimetable, format: OutputFormat, header?: string): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(day, format);\n return;\n }\n\n const title = header ?? `${day.weekdayName}${day.date ? ` (${day.date})` : ''}`;\n if (format === 'markdown') {\n console.log(`## ${title}`);\n console.log();\n printStatusLines(day, 'markdown');\n console.log('| Period | Class | Status |');\n console.log('| --- | --- | --- |');\n for (const period of day.periods) {\n console.log(`| ${period.period} | ${renderPeriod(period)} | ${period.status} |`);\n }\n return;\n }\n\n console.log(` ${heading(title)}`);\n printBanner(day);\n console.log();\n const padWidth = String(day.periods.length).length + 1;\n for (const period of day.periods) {\n const num = chalk.cyan(`P${String(period.period).padStart(padWidth)}`);\n const content = renderPeriodColored(period);\n const status = period.isFreePeriod\n ? chalk.dim(period.status)\n : period.status === 'unknown-subject'\n ? chalk.yellow(period.status)\n : chalk.dim(period.status);\n console.log(` ${num} ${content.padEnd(36)}${status}`);\n }\n}\n\nexport function printWeekTimetable(week: WeekTimetable, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(week, format);\n return;\n }\n\n const header = `${week.school.name} ${week.grade}-${week.classNo}`;\n if (format === 'markdown') {\n console.log(`# ${header}`);\n console.log();\n printStatusLines(week, 'markdown');\n } else {\n console.log();\n console.log(` ${heading(header)}`);\n console.log(` ${separator()}`);\n if (week.weekStart) {\n console.log(` ${chalk.dim(`Week of ${week.weekStart}`)}`);\n }\n printBanner(week);\n console.log();\n }\n\n for (const day of week.days) {\n printDayTimetable(day, format);\n console.log();\n }\n}\n\nexport function printTeacherTimetable(timetable: TeacherTimetable, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(timetable, format);\n return;\n }\n\n const header = `${timetable.school.name} \u2014 ${timetable.teacherName}`;\n if (format === 'markdown') {\n console.log(`# ${header}`);\n console.log();\n printStatusLines(timetable, 'markdown');\n } else {\n console.log();\n console.log(` ${heading(header)}`);\n console.log(` ${separator()}`);\n printBanner(timetable);\n console.log();\n }\n\n for (const day of timetable.days) {\n if (format === 'markdown') {\n console.log(`## ${day.weekdayName}${day.date ? ` (${day.date})` : ''}`);\n console.log();\n console.log('| Period | Subject | Class | Status |');\n console.log('| --- | --- | --- | --- |');\n for (const period of day.periods) {\n console.log(\n `| ${period.period} | ${period.isFreePeriod ? '(free)' : period.subject} | ${\n period.classLabel ?? '-'\n } | ${period.status} |`,\n );\n }\n } else {\n console.log(` ${heading(day.weekdayName)}${day.date ? chalk.dim(` (${day.date})`) : ''}`);\n const padWidth = String(day.periods.length).length + 1;\n for (const period of day.periods) {\n const num = chalk.cyan(`P${String(period.period).padStart(padWidth)}`);\n const subject = period.isFreePeriod\n ? chalk.dim('(free)')\n : period.status === 'unknown-subject'\n ? chalk.yellow('???')\n : chalk.white(period.subject);\n const classLabel = period.classLabel ? chalk.dim(` [${period.classLabel}]`) : '';\n const status = period.isFreePeriod\n ? chalk.dim(period.status)\n : period.status === 'unknown-subject'\n ? chalk.yellow(period.status)\n : chalk.dim(period.status);\n console.log(` ${num} ${(subject + classLabel).padEnd(36)}${status}`);\n }\n }\n console.log();\n }\n}\n\nexport function printTeacherInfo(info: TeacherInfo, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(info, format);\n return;\n }\n\n const lines = [\n `Teacher: ${info.name}`,\n `School: ${info.school.name}`,\n info.subjects?.length ? `Subjects: ${info.subjects.join(', ')}` : undefined,\n info.classes?.length ? `Classes: ${info.classes.join(', ')}` : undefined,\n ].filter(Boolean);\n\n if (format === 'markdown') {\n console.log(`# ${info.name}`);\n console.log();\n printStatusLines(info, 'markdown');\n for (const line of lines.slice(1)) {\n console.log(`- ${line}`);\n }\n return;\n }\n\n console.log();\n console.log(` ${heading(info.name)}`);\n console.log(` ${separator()}`);\n printBanner(info);\n console.log();\n console.log(` ${kv('School', info.school.name)}`);\n if (info.subjects?.length) console.log(` ${kv('Subjects', info.subjects.join(', '))}`);\n if (info.classes?.length) console.log(` ${kv('Classes', info.classes.join(', '))}`);\n console.log();\n}\n\nexport function printDailyMeals(daily: DailyMeals, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(daily, format);\n return;\n }\n\n const title = `${daily.date}${daily.weekdayName ? ` (${daily.weekdayName})` : ''}`;\n if (format === 'markdown') {\n console.log(`## ${title}`);\n console.log();\n printStatusLines(daily, 'markdown');\n for (const meal of daily.meals) {\n console.log(`### ${meal.type}`);\n console.log();\n for (const item of meal.items) {\n const allergies = item.allergyCodes?.length ? ` (${item.allergyCodes.join('.')})` : '';\n console.log(`- ${item.name}${allergies}`);\n }\n if (meal.calories) {\n console.log();\n console.log(`> ${meal.calories}`);\n }\n if (meal.nutritionInfo) {\n console.log();\n console.log(`> nutrition: ${meal.nutritionInfo}`);\n }\n if (meal.originInfo) {\n console.log();\n console.log(`> origin: ${meal.originInfo}`);\n }\n console.log();\n }\n return;\n }\n\n console.log(` ${heading(title)}`);\n printBanner(daily);\n for (const meal of daily.meals) {\n console.log();\n console.log(` ${chalk.cyan.bold(`[${meal.type}]`)}`);\n for (const item of meal.items) {\n const allergies = item.allergyCodes?.length\n ? chalk.dim(` (${item.allergyCodes.join('.')})`)\n : '';\n console.log(` ${item.name}${allergies}`);\n }\n if (meal.calories) console.log(` ${chalk.dim(meal.calories)}`);\n if (meal.nutritionInfo) console.log(` ${chalk.dim(`nutrition: ${meal.nutritionInfo}`)}`);\n if (meal.originInfo) console.log(` ${chalk.dim(`origin: ${meal.originInfo}`)}`);\n }\n}\n\nexport function printWeeklyMeals(weekly: WeeklyMeals, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(weekly, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log(`# ${weekly.school.name} meals`);\n console.log();\n printStatusLines(weekly, 'markdown');\n } else {\n console.log();\n console.log(` ${heading(`${weekly.school.name} meals`)}`);\n console.log(` ${separator()}`);\n if (weekly.weekStart) {\n console.log(` ${chalk.dim(`Week of ${weekly.weekStart}`)}`);\n }\n if (weekly.fromDate && weekly.toDate && weekly.fromDate !== weekly.toDate) {\n console.log(` ${chalk.dim(`${weekly.fromDate} \u2014 ${weekly.toDate}`)}`);\n }\n printBanner(weekly);\n console.log();\n }\n\n for (const day of weekly.days) {\n printDailyMeals(day, format);\n console.log();\n }\n}\n\nexport function printClassTimes(slots: ClassTimeSlot[], format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(slots, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log('| Period | Start | End |');\n console.log('| --- | --- | --- |');\n for (const slot of slots) {\n console.log(`| ${slot.period} | ${slot.startTime} | ${slot.endTime} |`);\n }\n return;\n }\n\n console.log();\n console.log(` ${heading('Class Times')}`);\n console.log(` ${separator()}`);\n console.log();\n for (const slot of slots) {\n console.log(` ${chalk.cyan(`P${slot.period}`)} ${slot.startTime} ${chalk.dim('\u2014')} ${slot.endTime}`);\n }\n console.log();\n}\n\nexport function printSnapshotDiff(diff: SnapshotDiff, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(diff, format);\n return;\n }\n\n if (!diff.changes.length) {\n if (format === 'markdown') {\n console.log('No timetable changes detected.');\n } else {\n console.log(chalk.dim(' No timetable changes detected.'));\n }\n return;\n }\n\n if (format === 'markdown') {\n console.log('| Day | Period | Before | After |');\n console.log('| --- | --- | --- | --- |');\n for (const change of diff.changes) {\n const before = `${change.before.subject}${change.before.teacher ? ` [${change.before.teacher}]` : ''}`;\n const after = `${change.after.subject}${change.after.teacher ? ` [${change.after.teacher}]` : ''}`;\n console.log(`| ${change.weekdayName} | ${change.period} | ${before} | ${after} |`);\n }\n return;\n }\n\n console.log();\n console.log(` ${heading('Timetable Changes')}`);\n console.log(` ${separator()}`);\n console.log();\n for (const change of diff.changes) {\n const before = `${change.before.subject}${change.before.teacher ? chalk.dim(` [${change.before.teacher}]`) : ''}`;\n const after = `${change.after.subject}${change.after.teacher ? chalk.dim(` [${change.after.teacher}]`) : ''}`;\n console.log(` ${chalk.cyan(change.weekdayName)} P${change.period} ${chalk.red(before)} ${chalk.dim('\u2192')} ${chalk.green(after)}`);\n }\n console.log();\n}\n\nexport function printNextClass(\n result: { period: PeriodItem; minutesUntil?: number } | null,\n format: OutputFormat,\n): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(result, format);\n return;\n }\n\n if (!result) {\n if (format === 'markdown') {\n console.log('No upcoming class found.');\n } else {\n console.log(chalk.dim(' No upcoming class found.'));\n }\n return;\n }\n\n if (format === 'markdown') {\n const eta = result.minutesUntil != null ? ` in ${result.minutesUntil} min` : '';\n console.log(`Next class: P${result.period.period} ${renderPeriod(result.period)}${eta}`);\n return;\n }\n\n const eta = result.minutesUntil != null\n ? chalk.blue(` in ${result.minutesUntil} min`)\n : '';\n console.log();\n console.log(` ${chalk.bold('Next')} ${chalk.cyan(`P${result.period.period}`)} ${renderPeriodColored(result.period)}${eta}`);\n console.log();\n}\n\n/* \u2500\u2500 Format detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction isOutputFormat(value: string): value is OutputFormat {\n return ['human', 'json', 'markdown', 'yaml', 'csv', 'table', 'ndjson'].includes(value);\n}\n\n/* \u2500\u2500 YAML renderer (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderYaml(data: unknown, depth = 0): string {\n const indent = ' '.repeat(depth);\n\n if (data == null) {\n return 'null';\n }\n if (typeof data === 'string') {\n return JSON.stringify(data);\n }\n if (typeof data === 'number' || typeof data === 'boolean') {\n return String(data);\n }\n if (Array.isArray(data)) {\n if (!data.length) {\n return '[]';\n }\n return data\n .map((item) => {\n const rendered = renderYaml(item, depth + 1);\n if (typeof item === 'object' && item != null) {\n return `${indent}- ${rendered.startsWith('\\n') ? rendered.slice(1) : rendered}`;\n }\n return `${indent}- ${rendered}`;\n })\n .join('\\n');\n }\n\n const entries = Object.entries(data as Record<string, unknown>);\n if (!entries.length) {\n return '{}';\n }\n\n return entries\n .map(([key, value]) => {\n if (value && typeof value === 'object') {\n const child = renderYaml(value, depth + 1);\n return `${indent}${key}:\\n${child}`;\n }\n return `${indent}${key}: ${renderYaml(value, depth + 1)}`;\n })\n .join('\\n');\n}\n\n/* \u2500\u2500 NDJSON renderer (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction printNdjson(data: unknown): void {\n if (Array.isArray(data)) {\n for (const item of data) {\n console.log(JSON.stringify(item));\n }\n return;\n }\n\n console.log(JSON.stringify(data));\n}\n\n/* \u2500\u2500 CSV renderer (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderCsv(data: unknown): string {\n const rows = toTabularRows(data);\n const columns = collectColumns(rows);\n const header = columns.join(',');\n const body = rows.map((row) => columns.map((column) => escapeCsv(row[column])).join(','));\n return [header, ...body].join('\\n');\n}\n\n/* \u2500\u2500 Table renderer (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderTable(data: unknown): string {\n const rows = toTabularRows(data);\n const columns = collectColumns(rows);\n const widths = Object.fromEntries(\n columns.map((column) => [\n column,\n Math.max(column.length, ...rows.map((row) => String(row[column] ?? '').length)),\n ]),\n ) as Record<string, number>;\n\n const header = columns.map((column) => padCell(column, widths[column])).join(' | ');\n const divider = columns.map((column) => '-'.repeat(widths[column])).join('-|-');\n const body = rows.map((row) =>\n columns.map((column) => padCell(String(row[column] ?? ''), widths[column])).join(' | '),\n );\n\n return [header, divider, ...body].join('\\n');\n}\n\n/* \u2500\u2500 Shared tabular helpers (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction toTabularRows(data: unknown): Array<Record<string, string>> {\n if (Array.isArray(data)) {\n return data.map((entry) => flattenRecord(entry));\n }\n return [flattenRecord(data)];\n}\n\nfunction flattenRecord(value: unknown, prefix = ''): Record<string, string> {\n if (value == null) {\n return prefix ? { [prefix]: '' } : { value: '' };\n }\n\n if (typeof value !== 'object' || value instanceof Date) {\n return prefix ? { [prefix]: String(value) } : { value: String(value) };\n }\n\n if (Array.isArray(value)) {\n return prefix ? { [prefix]: JSON.stringify(value) } : { value: JSON.stringify(value) };\n }\n\n const flattened = Object.entries(value as Record<string, unknown>).flatMap(([key, entry]) => {\n const nextPrefix = prefix ? `${prefix}.${key}` : key;\n return Object.entries(flattenRecord(entry, nextPrefix));\n });\n\n if (!flattened.length) {\n return prefix ? { [prefix]: '{}' } : { value: '{}' };\n }\n\n return Object.fromEntries(flattened);\n}\n\nfunction collectColumns(rows: Array<Record<string, string>>): string[] {\n const columns = new Set<string>();\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n columns.add(key);\n }\n }\n return [...columns];\n}\n\nfunction escapeCsv(value: string | undefined): string {\n const text = value ?? '';\n if (/[\",\\n]/.test(text)) {\n return `\"${text.replace(/\"/g, '\"\"')}\"`;\n }\n return text;\n}\n\nfunction padCell(value: string, width: number): string {\n return `${value}${' '.repeat(Math.max(0, width - value.length))}`;\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport {\n describeSecretStorage,\n getPreferredSecretStorage,\n getKampusConfigStatus,\n InvalidInputError,\n loadKampusConfig,\n maskSecret,\n resolveCachePolicy,\n resolveKampusCachePath,\n resolveNeisApiKey,\n saveKampusConfig,\n setNeisApiKeyStatus,\n} from '@kampus/core';\nimport { NeisProvider } from '@kampus/provider-neis';\nimport { getFormat, printStructured } from '../output.js';\n\nconst SMOKE_KEYWORD = '\\uACBD\\uAE30\\uBD81\\uACFC\\uD559\\uACE0';\n\nexport function authCommands(program: Command): void {\n const auth = program.command('auth').description('Manage NEIS authentication and validation');\n\n auth\n .command('status')\n .description('Show the current NEIS authentication status')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action((opts) => {\n const format = getFormat(opts);\n const status = getKampusConfigStatus();\n const payload = {\n configPath: status.configPath,\n configured: status.neisApiKeyConfigured,\n stored: status.neisApiKeyStored,\n readable: status.neisApiKeyReadable,\n source: status.neisApiKeySource,\n storageMode: status.neisApiKeyStorage,\n preview: status.neisApiKeyPreview,\n error: status.neisApiKeyError,\n validation: status.neisApiKeyStatus,\n storage: describeSecretStorage(status.neisApiKeyStorage, status.neisApiKeySource),\n warnings: buildAuthWarnings({\n source: status.neisApiKeySource,\n storageMode: status.neisApiKeyStorage,\n readable: status.neisApiKeyReadable,\n error: status.neisApiKeyError,\n }),\n };\n\n if (format !== 'human') {\n printStructured(payload, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold('Auth Status')}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n console.log(` ${chalk.dim('configured')} ${payload.configured ? chalk.green('yes') : chalk.yellow('no')}`);\n console.log(` ${chalk.dim('stored')} ${payload.stored ? 'yes' : 'no'}`);\n console.log(` ${chalk.dim('readable')} ${payload.readable ? chalk.green('yes') : chalk.red('no')}`);\n console.log(` ${chalk.dim('source')} ${payload.source}`);\n if (payload.storageMode) {\n console.log(` ${chalk.dim('storage')} ${payload.storageMode}`);\n }\n if (payload.preview) {\n console.log(` ${chalk.dim('preview')} ${chalk.cyan(payload.preview)}`);\n }\n if (payload.error) {\n console.log(` ${chalk.dim('error')} ${chalk.red(payload.error)}`);\n }\n if (payload.validation?.checkedAt) {\n console.log(` ${chalk.dim('validated')} ${payload.validation.checkedAt}`);\n }\n if (payload.validation?.accessMode) {\n const modeColor = payload.validation.accessMode === 'official-full' ? chalk.green : chalk.yellow;\n console.log(` ${chalk.dim('access mode')} ${modeColor(payload.validation.accessMode)}`);\n }\n if (payload.validation?.message) {\n console.log(` ${chalk.dim('message')} ${payload.validation.message}`);\n }\n console.log(` ${chalk.dim('storage')} ${payload.storage}`);\n for (const warning of payload.warnings) {\n console.log(chalk.yellow(` \u26A0 ${warning}`));\n }\n console.log();\n });\n\n auth\n .command('login')\n .description('Save a NEIS API key to local config and optionally validate it')\n .requiredOption('--api-key <key>', 'NEIS API key')\n .option('--storage <type>', 'Storage mode (auto|windows-dpapi|plain-text)', 'auto')\n .option('--skip-validate', 'Skip the live validation check')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action(async (opts) => {\n const format = getFormat(opts);\n const preferredStorage = parseStorageMode(opts.storage);\n let nextConfig = saveKampusConfig({\n ...loadKampusConfig(),\n neisApiKey: opts.apiKey,\n neisApiKeyStoredValue: undefined,\n neisApiKeyStorage: preferredStorage === 'auto' ? getPreferredSecretStorage() : preferredStorage,\n neisApiKeyReadable: true,\n neisApiKeyError: undefined,\n });\n\n let validation = undefined;\n if (!opts.skipValidate) {\n validation = await validateKey(opts.apiKey, 'config');\n nextConfig = saveKampusConfig(setNeisApiKeyStatus(nextConfig, validation));\n }\n\n const payload = {\n ok: true,\n configured: true,\n preview: maskSecret(opts.apiKey),\n storageMode: nextConfig.neisApiKeyStorage,\n storage: describeSecretStorage(nextConfig.neisApiKeyStorage, 'config'),\n validation,\n warnings: buildAuthWarnings({\n source: 'config',\n storageMode: nextConfig.neisApiKeyStorage,\n readable: true,\n }),\n };\n\n if (format !== 'human') {\n printStructured(payload, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log(` ${chalk.green('\u2713')} Saved NEIS API key to local config.`);\n console.log(` ${chalk.dim('preview')} ${chalk.cyan(payload.preview)}`);\n console.log(` ${chalk.dim('storage')} ${payload.storage}`);\n if (validation?.message) {\n console.log(` ${chalk.dim('validation')} ${validation.message}`);\n }\n for (const warning of payload.warnings) {\n console.log(chalk.yellow(` \u26A0 ${warning}`));\n }\n });\n\n auth\n .command('migrate')\n .description('Re-save the current config key using the preferred protected storage when available')\n .option('--storage <type>', 'Storage mode (auto|windows-dpapi|plain-text)', 'auto')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action((opts) => {\n const format = getFormat(opts);\n const current = loadKampusConfig();\n if (!current.neisApiKey) {\n if (current.neisApiKeyStoredValue && current.neisApiKeyError) {\n throw new InvalidInputError(current.neisApiKeyError);\n }\n throw new InvalidInputError('No saved config NEIS API key is available to migrate.');\n }\n\n const preferredStorage = parseStorageMode(opts.storage);\n const next = saveKampusConfig({\n ...current,\n neisApiKey: current.neisApiKey,\n neisApiKeyStoredValue: undefined,\n neisApiKeyStorage: preferredStorage === 'auto' ? getPreferredSecretStorage() : preferredStorage,\n neisApiKeyReadable: true,\n neisApiKeyError: undefined,\n });\n\n const payload = {\n ok: true,\n configured: true,\n preview: maskSecret(current.neisApiKey),\n storageMode: next.neisApiKeyStorage,\n storage: describeSecretStorage(next.neisApiKeyStorage, 'config'),\n warnings: buildAuthWarnings({\n source: 'config',\n storageMode: next.neisApiKeyStorage,\n readable: true,\n }),\n };\n\n if (format !== 'human') {\n printStructured(payload, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log(` ${chalk.green('\u2713')} Re-saved the NEIS API key using the requested storage mode.`);\n console.log(` ${chalk.dim('storage')} ${payload.storage}`);\n console.log(` ${chalk.dim('preview')} ${chalk.cyan(payload.preview)}`);\n for (const warning of payload.warnings) {\n console.log(chalk.yellow(` \u26A0 ${warning}`));\n }\n });\n\n auth\n .command('validate')\n .description('Run a live NEIS validation check against the configured key')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action(async (opts) => {\n const format = getFormat(opts);\n const status = getKampusConfigStatus();\n const apiKey = resolveNeisApiKey();\n if (!apiKey) {\n if (status.neisApiKeyStored && !status.neisApiKeyReadable && status.neisApiKeyError) {\n throw new InvalidInputError(status.neisApiKeyError);\n }\n throw new InvalidInputError('No NEIS API key is configured. Use \"kps auth login --api-key <key>\" first.');\n }\n\n const source = process.env.NEIS_API_KEY?.trim() ? 'env' : 'config';\n const validation = await validateKey(apiKey, source);\n\n if (source === 'config') {\n saveKampusConfig(setNeisApiKeyStatus(loadKampusConfig(), validation));\n }\n\n if (format !== 'human') {\n printStructured(validation, format === 'markdown' ? 'json' : format);\n return;\n }\n\n const icon = validation.ok ? chalk.green('\u2713') : chalk.red('\u2716');\n console.log(` ${icon} ${validation.ok ? 'Validation passed' : 'Validation failed'}`);\n console.log(` ${chalk.dim('validated')} ${validation.checkedAt}`);\n if (validation.accessMode) {\n const modeColor = validation.accessMode === 'official-full' ? chalk.green : chalk.yellow;\n console.log(` ${chalk.dim('access mode')} ${modeColor(validation.accessMode)}`);\n }\n if (validation.message) {\n console.log(` ${chalk.dim('message')} ${validation.message}`);\n }\n });\n\n auth\n .command('logout')\n .description('Remove the saved NEIS API key from local config')\n .action(() => {\n saveKampusConfig({\n ...loadKampusConfig(),\n neisApiKey: undefined,\n neisApiKeyStoredValue: undefined,\n neisApiKeyStorage: undefined,\n neisApiKeyReadable: false,\n neisApiKeyError: undefined,\n neisApiKeyStatus: undefined,\n });\n console.log(` ${chalk.green('\u2713')} Removed the saved NEIS API key from local config.`);\n });\n\n auth\n .command('export')\n .description('Print a shell command that exports the current NEIS API key')\n .option('--shell <type>', 'Shell type (powershell|bash)', 'powershell')\n .action((opts) => {\n const apiKey = resolveNeisApiKey();\n if (!apiKey) {\n throw new InvalidInputError('No NEIS API key is configured.');\n }\n\n if (opts.shell === 'bash') {\n console.log(`export NEIS_API_KEY=\"${apiKey}\"`);\n return;\n }\n\n console.log(`$env:NEIS_API_KEY=\"${apiKey}\"`);\n });\n}\n\nasync function validateKey(apiKey: string, source: 'env' | 'config') {\n const cachePolicy = resolveCachePolicy();\n const provider = new NeisProvider({\n apiKey,\n cachePath: resolveKampusCachePath(),\n cacheTtlMs: cachePolicy.datasetTtlMinutes * 60 * 1000,\n staleIfErrorMs: cachePolicy.staleIfErrorHours * 60 * 60 * 1000,\n cacheMaxEntries: cachePolicy.maxEntries,\n });\n const checkedAt = new Date().toISOString();\n\n try {\n const result = await provider.getDatasetResult('schoolInfo', {\n SCHUL_NM: SMOKE_KEYWORD,\n pSize: 1,\n });\n\n return {\n checkedAt,\n ok: true,\n accessMode: result.dataStatus.accessMode,\n message: `Validated against schoolInfo smoke query for \"${SMOKE_KEYWORD}\".`,\n source,\n } as const;\n } catch (error) {\n return {\n checkedAt,\n ok: false,\n message: error instanceof Error ? error.message : String(error),\n source,\n } as const;\n }\n}\n\nfunction parseStorageMode(value: string): 'auto' | 'windows-dpapi' | 'plain-text' {\n if (value === 'auto' || value === 'windows-dpapi' || value === 'plain-text') {\n return value;\n }\n\n throw new InvalidInputError('Storage mode must be one of: auto, windows-dpapi, plain-text.');\n}\n\nfunction buildAuthWarnings(input: {\n source: 'env' | 'config' | 'none';\n storageMode?: 'windows-dpapi' | 'plain-text';\n readable: boolean;\n error?: string;\n}): string[] {\n const warnings: string[] = [];\n\n if (input.error) {\n warnings.push(input.error);\n }\n\n if (input.source === 'config' && input.storageMode === 'plain-text') {\n warnings.push(\n process.platform === 'win32'\n ? 'This key is still stored as plain text. Run \"kps auth migrate\" to upgrade it to Windows DPAPI protection.'\n : 'This key is stored in plain-text config on this platform. Prefer NEIS_API_KEY environment variables or an external secret manager for production use.',\n );\n }\n\n if (input.source === 'config' && !input.readable) {\n warnings.push('The saved config key exists but is not readable in this environment. Re-enter it or override it with NEIS_API_KEY.');\n }\n\n return warnings;\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport {\n describeSecretStorage,\n getKampusConfigStatus,\n InvalidInputError,\n KAMPUS_DEVELOPER_INFO,\n KAMPUS_PROJECT_INFO,\n loadKampusConfig,\n resolveCachePolicy,\n resolveKampusCachePath,\n resolveKampusConfigPath,\n saveKampusConfig,\n setDefaultSchool,\n type SchoolRef,\n} from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printStructured } from '../output.js';\nimport { resolveSchool } from './resolve.js';\n\nconst AVAILABLE_WITHOUT_KEY = [\n 'Merged school search and school resolve across Comcigan and NEIS limited mode',\n 'Comcigan student timetable, teacher timetable, teacher info, next class, class times, export, diff',\n 'Official NEIS school search, school info, meals, and dataset queries in limited sample mode',\n];\n\nconst FULL_NEIS_FEATURES = [\n 'Complete official NEIS searches and larger result sets',\n 'Official NEIS meal month/range queries without sample truncation',\n 'Official NEIS datasets beyond the sample-mode cap',\n];\n\nexport function configCommands(program: Command): void {\n const config = program.command('config').description('Manage local Kampus configuration');\n const set = config.command('set').description('Set a config value');\n const clear = config.command('clear').description('Clear a config value');\n\n config\n .command('show')\n .description('Show the current config status')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action((opts) => {\n const format = getFormat(opts);\n const status = getKampusConfigStatus();\n const data = {\n configPath: status.configPath,\n cachePath: resolveKampusCachePath(),\n metadataReadOnly: true,\n neisApiKeyConfigured: status.neisApiKeyConfigured,\n neisApiKeyStored: status.neisApiKeyStored,\n neisApiKeyReadable: status.neisApiKeyReadable,\n neisApiKeySource: status.neisApiKeySource,\n neisApiKeyStorage: status.neisApiKeyStorage,\n neisApiKeyPreview: status.neisApiKeyPreview,\n neisApiKeyError: status.neisApiKeyError,\n neisApiKeyStatus: status.neisApiKeyStatus,\n projectInfo: KAMPUS_PROJECT_INFO,\n developerInfo: KAMPUS_DEVELOPER_INFO,\n defaultSchool: status.defaultSchool,\n recentSchools: status.recentSchools,\n activeProfile: status.activeProfile,\n profiles: status.profiles,\n cachePolicy: status.cachePolicy,\n features: {\n availableWithoutKey: AVAILABLE_WITHOUT_KEY,\n unlockedByNeisApiKey: FULL_NEIS_FEATURES,\n notes: [\n 'Without a NEIS key, official endpoints currently run in a limited sample mode and may truncate to a small number of rows.',\n 'Default school is used when --school is omitted in school-bound commands.',\n 'Recent schools are filled only from schools that you actually resolved in Kampus.',\n 'Project and developer identity shown here is embedded application metadata and cannot be changed by users.',\n ],\n },\n };\n\n if (format !== 'human') {\n printStructured(data, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold('Kampus Config')}`);\n console.log(` ${chalk.dim('-'.repeat(48))}`);\n console.log();\n console.log(` ${chalk.dim('config')} ${chalk.dim(data.configPath)}`);\n console.log(` ${chalk.dim('cache')} ${chalk.dim(data.cachePath)}`);\n console.log();\n\n console.log(` ${chalk.bold('NEIS API Key')}`);\n console.log(` ${chalk.dim('configured')} ${status.neisApiKeyConfigured ? chalk.green('yes') : chalk.yellow('no')}`);\n console.log(` ${chalk.dim('stored')} ${status.neisApiKeyStored ? 'yes' : 'no'}`);\n console.log(` ${chalk.dim('readable')} ${status.neisApiKeyReadable ? chalk.green('yes') : chalk.red('no')}`);\n if (status.neisApiKeyConfigured) {\n console.log(` ${chalk.dim('source')} ${status.neisApiKeySource}`);\n console.log(` ${chalk.dim('storage')} ${describeSecretStorage(status.neisApiKeyStorage, status.neisApiKeySource)}`);\n if (status.neisApiKeyPreview) {\n console.log(` ${chalk.dim('preview')} ${chalk.cyan(status.neisApiKeyPreview)}`);\n }\n } else if (status.neisApiKeyStored && status.neisApiKeyStorage) {\n console.log(` ${chalk.dim('storage')} ${describeSecretStorage(status.neisApiKeyStorage, status.neisApiKeySource)}`);\n }\n if (status.neisApiKeyError) {\n console.log(` ${chalk.dim('error')} ${chalk.red(status.neisApiKeyError)}`);\n }\n if (status.neisApiKeyStatus?.checkedAt) {\n console.log(` ${chalk.dim('validated')} ${status.neisApiKeyStatus.checkedAt}`);\n }\n console.log();\n\n console.log(` ${chalk.bold('Project Info')} ${chalk.dim('(read-only)')}`);\n console.log(` ${chalk.dim('name')} ${KAMPUS_PROJECT_INFO.name}`);\n console.log(` ${chalk.dim('desc')} ${KAMPUS_PROJECT_INFO.description}`);\n console.log(` ${chalk.dim('repo')} ${KAMPUS_PROJECT_INFO.repositoryUrl}`);\n console.log(` ${chalk.dim('homepage')} ${KAMPUS_PROJECT_INFO.homepageUrl}`);\n console.log();\n\n console.log(` ${chalk.bold('Developer Info')} ${chalk.dim('(read-only)')}`);\n console.log(` ${chalk.dim('name')} ${KAMPUS_DEVELOPER_INFO.name}`);\n console.log(` ${chalk.dim('email')} ${KAMPUS_DEVELOPER_INFO.email ?? chalk.dim('(not set)')}`);\n console.log(` ${chalk.dim('url')} ${KAMPUS_DEVELOPER_INFO.url ?? chalk.dim('(not set)')}`);\n console.log();\n\n console.log(` ${chalk.bold('Defaults')}`);\n console.log(` ${chalk.dim('school')} ${status.defaultSchool ? formatSchool(status.defaultSchool) : chalk.dim('(not set)')}`);\n console.log(` ${chalk.dim('profile')} ${status.activeProfile?.name ?? chalk.dim('(not set)')}`);\n console.log(` ${chalk.dim('profiles')} ${status.profiles.length}`);\n console.log(` ${chalk.dim('recent')} ${status.recentSchools.length}`);\n if (status.recentSchools.length) {\n for (const school of status.recentSchools) {\n console.log(` ${chalk.dim('-')} ${formatSchool(school)}`);\n }\n }\n console.log();\n\n console.log(` ${chalk.bold('Cache Policy')}`);\n console.log(` ${chalk.dim('dataset ttl')} ${status.cachePolicy.datasetTtlMinutes}m`);\n console.log(` ${chalk.dim('stale-if-error')} ${status.cachePolicy.staleIfErrorHours}h`);\n console.log(` ${chalk.dim('max entries')} ${status.cachePolicy.maxEntries}`);\n console.log();\n\n console.log(` ${chalk.bold('Available without key')}`);\n for (const feature of AVAILABLE_WITHOUT_KEY) {\n console.log(` ${chalk.dim('-')} ${feature}`);\n }\n console.log();\n console.log(` ${chalk.bold('Unlocked by NEIS API key')}`);\n for (const feature of FULL_NEIS_FEATURES) {\n console.log(` ${chalk.dim('-')} ${chalk.green(feature)}`);\n }\n console.log();\n for (const note of data.features.notes) {\n console.log(chalk.dim(` ${note}`));\n }\n console.log();\n });\n\n config\n .command('path')\n .description('Print the local config path')\n .action(() => {\n console.log(resolveKampusConfigPath());\n });\n\n config\n .command('cache-path')\n .description('Print the local cache path')\n .action(() => {\n console.log(resolveKampusCachePath());\n });\n\n set\n .command('neis-api-key <key>')\n .description('Save the NEIS API key to the local config')\n .action((key: string) => {\n const current = loadKampusConfig();\n const next = saveKampusConfig({\n ...current,\n neisApiKey: key,\n neisApiKeyStoredValue: undefined,\n });\n\n console.log(` ${chalk.green('[saved]')} Saved NEIS API key to ${chalk.dim(resolveKampusConfigPath())}`);\n if (next.neisApiKey) {\n console.log(` ${chalk.dim('storage')} ${describeSecretStorage(next.neisApiKeyStorage, 'config')}`);\n }\n });\n\n set\n .command('default-school <school>')\n .description('Resolve and save the default school')\n .option('--region <name>', 'Region hint to disambiguate')\n .action(async (schoolName: string, opts) => {\n const client = createClient();\n const school = await resolveSchool(client, schoolName, opts.region);\n const next = saveKampusConfig(setDefaultSchool(loadKampusConfig(), school));\n console.log(` ${chalk.green('[saved]')} Saved default school to ${chalk.dim(resolveKampusConfigPath())}`);\n if (next.defaultSchool) {\n console.log(` ${chalk.dim('school')} ${formatSchool(next.defaultSchool)}`);\n }\n });\n\n set\n .command('cache-dataset-ttl <minutes>')\n .description('Set the NEIS dataset cache TTL in minutes')\n .action((minutes: string) => {\n const parsed = parsePositiveInteger(minutes, 'Cache dataset TTL');\n const current = loadKampusConfig();\n const next = saveKampusConfig({\n ...current,\n cachePolicy: {\n ...resolveCachePolicy(current),\n datasetTtlMinutes: parsed,\n },\n });\n console.log(` ${chalk.green('[saved]')} Saved cache dataset TTL ${chalk.cyan(`${next.cachePolicy?.datasetTtlMinutes}m`)}`);\n });\n\n set\n .command('cache-stale-if-error <hours>')\n .description('Set the stale-if-error fallback window in hours')\n .action((hours: string) => {\n const parsed = parsePositiveInteger(hours, 'Cache stale-if-error window');\n const current = loadKampusConfig();\n const next = saveKampusConfig({\n ...current,\n cachePolicy: {\n ...resolveCachePolicy(current),\n staleIfErrorHours: parsed,\n },\n });\n console.log(` ${chalk.green('[saved]')} Saved stale-if-error window ${chalk.cyan(`${next.cachePolicy?.staleIfErrorHours}h`)}`);\n });\n\n set\n .command('cache-max-entries <count>')\n .description('Set the maximum number of cached dataset entries')\n .action((count: string) => {\n const parsed = parsePositiveInteger(count, 'Cache max entries');\n const current = loadKampusConfig();\n const next = saveKampusConfig({\n ...current,\n cachePolicy: {\n ...resolveCachePolicy(current),\n maxEntries: parsed,\n },\n });\n console.log(` ${chalk.green('[saved]')} Saved cache max entries ${chalk.cyan(String(next.cachePolicy?.maxEntries))}`);\n });\n\n clear\n .command('neis-api-key')\n .description('Remove the saved NEIS API key from the local config')\n .action(() => {\n const current = loadKampusConfig();\n saveKampusConfig({\n ...current,\n neisApiKey: undefined,\n neisApiKeyStoredValue: undefined,\n neisApiKeyStorage: undefined,\n neisApiKeyReadable: false,\n neisApiKeyError: undefined,\n });\n console.log(` ${chalk.green('[cleared]')} Removed saved NEIS API key.`);\n });\n\n clear\n .command('default-school')\n .description('Remove the saved default school from the local config')\n .action(() => {\n const current = loadKampusConfig();\n saveKampusConfig({\n ...current,\n defaultSchool: undefined,\n });\n console.log(` ${chalk.green('[cleared]')} Removed saved default school.`);\n });\n\n clear\n .command('cache-policy')\n .description('Reset the saved cache policy back to defaults')\n .action(() => {\n const current = loadKampusConfig();\n saveKampusConfig({\n ...current,\n cachePolicy: undefined,\n });\n console.log(` ${chalk.green('[cleared]')} Reset cache policy to defaults.`);\n });\n}\n\nfunction formatSchool(school: Pick<SchoolRef, 'name' | 'region' | 'schoolType'>): string {\n const extras = [school.region, school.schoolType].filter(Boolean).join(', ');\n return extras ? `${school.name} (${extras})` : school.name;\n}\n\nfunction parsePositiveInteger(raw: string, label: string): number {\n const parsed = Number.parseInt(raw, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new InvalidInputError(`${label} must be a non-negative integer.`);\n }\n\n return parsed;\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport {\n AmbiguousSchoolError,\n describeSecretStorage,\n InvalidInputError,\n SchoolNotFoundError,\n formatDate,\n getKampusConfigStatus,\n resolveCachePolicy,\n resolveKampusCachePath,\n resolveNeisApiKey,\n type DataStatus,\n type ProviderId,\n type SchoolRef,\n type SchoolSearchResult,\n} from '@kampus/core';\nimport { ComciganProvider } from '@kampus/provider-comcigan';\nimport { NeisProvider, type NeisDatasetName } from '@kampus/provider-neis';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printStructured, type OutputFormat } from '../output.js';\nimport { getDefaultSchool } from './resolve.js';\nimport { toCliErrorPayload } from '../errors.js';\n\nconst KNOWN_SMOKE_KEYWORD = '\\uACBD\\uAE30\\uBD81\\uACFC\\uD559\\uACE0';\nconst NEIS_DATASETS: NeisDatasetName[] = [\n 'schoolInfo',\n 'mealServiceDietInfo',\n 'classInfo',\n 'schoolMajorinfo',\n 'schulAflcoinfo',\n 'SchoolSchedule',\n 'elsTimetable',\n 'misTimetable',\n 'hisTimetable',\n 'spsTimetable',\n 'tiClrminfo',\n 'acaInsTiInfo',\n];\n\ninterface ProviderLiveCheck {\n ok: boolean;\n check: string;\n message: string;\n resultCount?: number;\n totalCount?: number;\n dataStatus?: DataStatus;\n firstResult?: unknown;\n error?: {\n code: string;\n message: string;\n };\n subchecks?: ProviderLiveSubcheck[];\n}\n\ninterface ProviderLiveSubcheck {\n name: string;\n ok: boolean;\n message: string;\n dataStatus?: DataStatus;\n error?: {\n code: string;\n message: string;\n };\n}\n\ninterface ProviderDebugReport {\n provider: ProviderId;\n configured: boolean;\n capabilities: string[];\n expectedAccessMode: 'official-full' | 'official-limited' | 'unofficial';\n notes: string[];\n live?: ProviderLiveCheck;\n}\n\ninterface DoctorReport {\n ok: true;\n checkedAt: string;\n live: boolean;\n config: ReturnType<typeof getKampusConfigStatus>;\n providers: ProviderDebugReport[];\n recommendations: string[];\n}\n\nexport function diagCommands(program: Command): void {\n program\n .command('doctor')\n .description('Inspect local Kampus configuration and provider readiness')\n .option('--live', 'Run lightweight live upstream smoke checks')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExamples:\\n kps doctor\\n kps doctor --live --json')\n .action(async (opts) => {\n const config = getKampusConfigStatus();\n const providers = await Promise.all([\n buildProviderReport('comcigan', opts.live),\n buildProviderReport('neis', opts.live),\n ]);\n\n const report: DoctorReport = {\n ok: true,\n checkedAt: new Date().toISOString(),\n live: Boolean(opts.live),\n config,\n providers,\n recommendations: buildRecommendations(config, providers),\n };\n\n printDoctorReport(report, getFormat(opts));\n });\n\n const debug = program.command('debug').description('Debug school resolution and provider state');\n\n debug\n .command('school [name]')\n .description('Inspect school search candidates and final resolution')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExamples:\\n kps debug school \"<school>\" --region \"<region>\" --json\\n kps debug school --json')\n .action(async (name: string | undefined, opts) => {\n const client = createClient();\n const defaultSchool = getDefaultSchool();\n const keyword = name?.trim() || defaultSchool?.name;\n if (!keyword) {\n throw new InvalidInputError(\n 'School name is required. Pass a name or configure a default school before using debug school.',\n );\n }\n\n const regionHint = opts.region?.trim() || (!name ? defaultSchool?.region : undefined);\n const candidates = await client.searchSchools(keyword);\n\n const report = {\n ok: true as const,\n input: {\n keyword,\n regionHint,\n usedDefaultSchool: !name,\n },\n defaultSchool,\n candidateCount: candidates.length,\n candidates,\n resolution: await resolveSchoolDebug(client, keyword, regionHint),\n };\n\n printSchoolDebugReport(report, getFormat(opts));\n });\n\n debug\n .command('provider <provider>')\n .description('Inspect provider configuration and optional live smoke result')\n .option('--live', 'Run a live smoke check for the provider')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExamples:\\n kps debug provider neis --json\\n kps debug provider comcigan --live')\n .action(async (providerName: string, opts) => {\n const provider = parseProviderId(providerName);\n const report = {\n ok: true as const,\n checkedAt: new Date().toISOString(),\n report: await buildProviderReport(provider, opts.live),\n };\n\n printProviderDebugReport(report, getFormat(opts));\n });\n\n debug\n .command('neis-dataset <dataset>')\n .description('Run a raw NEIS dataset query for troubleshooting')\n .option('--query <json>', 'Dataset query as JSON object', '{}')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps debug neis-dataset schoolInfo --query \\'{\"SCHUL_NM\":\"<school>\"}\\' --json')\n .action(async (dataset: string, opts) => {\n const serviceName = parseNeisDatasetName(dataset);\n const query = parseJsonObject(opts.query, '--query');\n const provider = new NeisProvider({\n apiKey: resolveNeisApiKey(),\n cachePath: resolveKampusCachePath(),\n cacheTtlMs: resolveCachePolicy().datasetTtlMinutes * 60 * 1000,\n staleIfErrorMs: resolveCachePolicy().staleIfErrorHours * 60 * 60 * 1000,\n cacheMaxEntries: resolveCachePolicy().maxEntries,\n });\n const result = await provider.getDatasetResult(serviceName, query);\n\n const report = {\n ok: true as const,\n dataset: serviceName,\n query,\n rowCount: result.rows.length,\n totalCount: result.totalCount,\n dataStatus: result.dataStatus,\n providerMetadata: result.providerMetadata,\n rows: result.rows,\n };\n\n printNeisDatasetDebugReport(report, getFormat(opts));\n });\n}\n\nasync function resolveSchoolDebug(\n client: ReturnType<typeof createClient>,\n keyword: string,\n regionHint?: string,\n) {\n try {\n const resolved = await client.resolveSchool(keyword, regionHint);\n return {\n status: 'resolved' as const,\n resolvedSchool: resolved,\n };\n } catch (error) {\n if (error instanceof AmbiguousSchoolError) {\n return {\n status: 'ambiguous' as const,\n matches: error.matches,\n };\n }\n\n if (error instanceof SchoolNotFoundError) {\n return {\n status: 'not_found' as const,\n };\n }\n\n throw error;\n }\n}\n\nasync function buildProviderReport(\n provider: ProviderId,\n live: boolean,\n): Promise<ProviderDebugReport> {\n if (provider === 'comcigan') {\n const instance = new ComciganProvider();\n return {\n provider,\n configured: true,\n capabilities: [...instance.capabilities],\n expectedAccessMode: 'unofficial',\n notes: [\n 'Comcigan is an unofficial upstream and can break without notice.',\n ],\n live: live ? await runComciganLiveCheck(instance) : undefined,\n };\n }\n\n const apiKey = resolveNeisApiKey();\n const cachePolicy = resolveCachePolicy();\n const instance = new NeisProvider({\n apiKey,\n cachePath: resolveKampusCachePath(),\n cacheTtlMs: cachePolicy.datasetTtlMinutes * 60 * 1000,\n staleIfErrorMs: cachePolicy.staleIfErrorHours * 60 * 60 * 1000,\n cacheMaxEntries: cachePolicy.maxEntries,\n });\n return {\n provider,\n configured: Boolean(apiKey),\n capabilities: [...instance.capabilities, 'datasets'],\n expectedAccessMode: apiKey ? 'official-full' : 'official-limited',\n notes: apiKey\n ? ['A NEIS API key is configured. Official full-mode queries are enabled.']\n : ['No NEIS API key is configured. Official queries will use limited sample mode when available.'],\n live: live ? await runNeisLiveCheck(instance) : undefined,\n };\n}\n\nasync function runComciganLiveCheck(provider: ComciganProvider): Promise<ProviderLiveCheck> {\n try {\n const schools = await provider.searchSchools(KNOWN_SMOKE_KEYWORD);\n return {\n ok: true,\n check: `searchSchools(\"${KNOWN_SMOKE_KEYWORD}\")`,\n message: `Comcigan returned ${schools.length} school result(s).`,\n resultCount: schools.length,\n firstResult: schools[0],\n };\n } catch (error) {\n const payload = toCliErrorPayload(error);\n return {\n ok: false,\n check: `searchSchools(\"${KNOWN_SMOKE_KEYWORD}\")`,\n message: payload.error.message,\n error: payload.error,\n };\n }\n}\n\nasync function runNeisLiveCheck(provider: NeisProvider): Promise<ProviderLiveCheck> {\n try {\n const result = await provider.getDatasetResult('schoolInfo', {\n SCHUL_NM: KNOWN_SMOKE_KEYWORD,\n });\n const firstRow = result.rows[0];\n const subchecks = firstRow\n ? [await runNeisTimetableSubcheck(provider, firstRow)]\n : undefined;\n\n return {\n ok: true,\n check: `schoolInfo query for \"${KNOWN_SMOKE_KEYWORD}\"`,\n message: `NEIS returned ${result.rows.length} row(s).`,\n resultCount: result.rows.length,\n totalCount: result.totalCount,\n dataStatus: result.dataStatus,\n firstResult: firstRow,\n subchecks,\n };\n } catch (error) {\n const payload = toCliErrorPayload(error);\n return {\n ok: false,\n check: `schoolInfo query for \"${KNOWN_SMOKE_KEYWORD}\"`,\n message: payload.error.message,\n error: payload.error,\n };\n }\n}\n\nasync function runNeisTimetableSubcheck(\n provider: NeisProvider,\n row: Record<string, string>,\n): Promise<ProviderLiveSubcheck> {\n const school: SchoolRef = {\n name: row.SCHUL_NM || KNOWN_SMOKE_KEYWORD,\n region: row.LCTN_SC_NM || row.ATPT_OFCDC_SC_NM,\n schoolType: row.SCHUL_KND_SC_NM,\n providerRefs: {\n neis: {\n officeCode: row.ATPT_OFCDC_SC_CODE,\n schoolCode: row.SD_SCHUL_CODE,\n },\n },\n };\n\n const today = new Date();\n const targetDate = formatDate(today);\n const targetYear = String(today.getFullYear());\n\n try {\n const result = await provider.getOfficialTimetableResult({\n school,\n year: targetYear,\n date: targetDate,\n grade: 1,\n className: '1',\n });\n\n const warningCodes = (result.dataStatus.warnings ?? []).map((warning) => warning.code);\n const warningSummary = warningCodes.length ? ` warnings=${warningCodes.join(',')}` : '';\n const message =\n result.rows.length > 0\n ? `Official timetable probe returned ${result.rows.length} row(s) for academic year ${targetYear} on ${targetDate}.`\n : `Official timetable probe returned no rows for academic year ${targetYear} on ${targetDate}.${warningSummary}`;\n\n return {\n name: 'official-timetable-probe',\n ok: true,\n message,\n dataStatus: result.dataStatus,\n };\n } catch (error) {\n const payload = toCliErrorPayload(error);\n return {\n name: 'official-timetable-probe',\n ok: false,\n message: payload.error.message,\n error: payload.error,\n };\n }\n}\n\nfunction buildRecommendations(\n config: ReturnType<typeof getKampusConfigStatus>,\n providers: ProviderDebugReport[],\n): string[] {\n const recommendations: string[] = [];\n\n if (!config.neisApiKeyConfigured) {\n recommendations.push('Configure a NEIS API key for complete official dataset coverage.');\n }\n if (!config.defaultSchool) {\n recommendations.push('Set a default school to simplify repeated CLI usage.');\n }\n if (config.neisApiKeyStored && !config.neisApiKeyReadable) {\n recommendations.push(\n 'A saved NEIS key exists but is not readable in this environment. Re-enter it with \"kps auth login\" or override it with NEIS_API_KEY.',\n );\n }\n if (config.neisApiKeySource === 'config' && config.neisApiKeyStorage === 'plain-text') {\n recommendations.push(\n process.platform === 'win32'\n ? 'The saved NEIS key is still plain text. Run \"kps auth migrate\" to upgrade it to Windows DPAPI protection.'\n : 'The saved NEIS key is stored as plain text on this platform. Prefer NEIS_API_KEY environment variables or an external secret manager for production use.',\n );\n }\n for (const provider of providers) {\n if (provider.live && !provider.live.ok) {\n recommendations.push(`Investigate ${provider.provider} provider readiness before relying on live queries.`);\n }\n for (const subcheck of provider.live?.subchecks ?? []) {\n if (!subcheck.ok) {\n recommendations.push(`Investigate ${provider.provider} ${subcheck.name} before relying on official timetable data.`);\n continue;\n }\n\n const warningCodes = (subcheck.dataStatus?.warnings ?? []).map((warning) => warning.code);\n if (warningCodes.includes('NEIS_TIMETABLE_YEAR_LAG')) {\n recommendations.push('Official NEIS timetable data appears to lag behind the current academic year for the smoke school.');\n }\n if (warningCodes.includes('NEIS_TIMETABLE_FILTER_NO_MATCH')) {\n recommendations.push('Official NEIS timetable data exists, but exact timetable filters may need to be widened when rows are empty.');\n }\n }\n }\n if (!recommendations.length) {\n recommendations.push('No immediate configuration issues detected.');\n }\n\n return recommendations;\n}\n\n/* \u2500\u2500 Human output helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction accessBadge(mode: string): string {\n switch (mode) {\n case 'official-full': return chalk.green.bold('OFFICIAL');\n case 'official-limited': return chalk.yellow.bold('LIMITED');\n case 'unofficial': return chalk.dim('UNOFFICIAL');\n default: return chalk.dim(mode);\n }\n}\n\nfunction statusIcon(ok: boolean): string {\n return ok ? chalk.green('\u2713') : chalk.red('\u2716');\n}\n\nfunction label(key: string, value: string): string {\n return ` ${chalk.dim(key)} ${value}`;\n}\n\nfunction printDoctorReport(report: DoctorReport, format: OutputFormat): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(report, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log('# Kampus Doctor');\n console.log();\n console.log(`- checkedAt: ${report.checkedAt}`);\n console.log(`- liveChecks: ${report.live ? 'enabled' : 'disabled'}`);\n console.log(`- configPath: ${report.config.configPath}`);\n console.log(`- neisApiKeyConfigured: ${report.config.neisApiKeyConfigured}`);\n console.log(`- neisApiKeyStorage: ${describeSecretStorage(report.config.neisApiKeyStorage, report.config.neisApiKeySource)}`);\n console.log(`- defaultSchool: ${report.config.defaultSchool?.name ?? '(not set)'}`);\n console.log();\n console.log('## Providers');\n console.log();\n for (const provider of report.providers) {\n printProviderSection(provider, 'markdown');\n }\n console.log('## Recommendations');\n console.log();\n for (const recommendation of report.recommendations) {\n console.log(`- ${recommendation}`);\n }\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold('Kampus Doctor')}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n console.log(label('Checked at', chalk.dim(report.checkedAt)));\n console.log(label('Live checks', report.live ? chalk.green('enabled') : chalk.dim('disabled')));\n console.log(label('Config', chalk.dim(report.config.configPath)));\n console.log(label('NEIS API key', report.config.neisApiKeyConfigured ? chalk.green('configured') : chalk.yellow('not configured')));\n console.log(label('Key storage', describeSecretStorage(report.config.neisApiKeyStorage, report.config.neisApiKeySource)));\n console.log(label('Default school', report.config.defaultSchool?.name ?? chalk.dim('(not set)')));\n console.log();\n\n console.log(` ${chalk.bold('Providers')}`);\n console.log();\n for (const provider of report.providers) {\n printProviderSection(provider, 'human');\n }\n\n console.log(` ${chalk.bold('Recommendations')}`);\n console.log();\n for (const recommendation of report.recommendations) {\n console.log(` ${chalk.dim('\u25B8')} ${recommendation}`);\n }\n console.log();\n}\n\nfunction printSchoolDebugReport(\n report: {\n ok: true;\n input: { keyword: string; regionHint?: string; usedDefaultSchool: boolean };\n defaultSchool?: SchoolSearchResult;\n candidateCount: number;\n candidates: SchoolSearchResult[];\n resolution:\n | { status: 'resolved'; resolvedSchool: SchoolSearchResult }\n | { status: 'ambiguous'; matches: Array<Pick<SchoolSearchResult, 'name' | 'region' | 'schoolType'>> }\n | { status: 'not_found' };\n },\n format: OutputFormat,\n): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(report, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log('# School Debug');\n console.log();\n console.log(`- keyword: ${report.input.keyword}`);\n console.log(`- regionHint: ${report.input.regionHint ?? '(none)'}`);\n console.log(`- usedDefaultSchool: ${report.input.usedDefaultSchool}`);\n console.log(`- candidateCount: ${report.candidateCount}`);\n console.log(`- resolution: ${report.resolution.status}`);\n console.log();\n console.log('## Candidates');\n console.log();\n for (const candidate of report.candidates) {\n console.log(`- ${formatSchool(candidate)} | refs: ${formatProviderRefs(candidate)}`);\n }\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold('School Debug')}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n console.log(label('Keyword', chalk.bold(report.input.keyword)));\n console.log(label('Region hint', report.input.regionHint ?? chalk.dim('(none)')));\n console.log(label('Used default', report.input.usedDefaultSchool ? 'yes' : 'no'));\n console.log(label('Candidates', String(report.candidateCount)));\n\n const resStatus = report.resolution.status;\n const resColor = resStatus === 'resolved' ? chalk.green : resStatus === 'ambiguous' ? chalk.yellow : chalk.red;\n console.log(label('Resolution', resColor(resStatus)));\n console.log();\n\n console.log(` ${chalk.bold('Candidates')}`);\n console.log();\n for (const candidate of report.candidates) {\n console.log(` ${chalk.bold(candidate.name)} ${chalk.dim(formatSchoolExtras(candidate))}`);\n console.log(` ${chalk.magenta(formatProviderRefs(candidate))}`);\n }\n console.log();\n}\n\nfunction printProviderDebugReport(\n report: { ok: true; checkedAt: string; report: ProviderDebugReport },\n format: OutputFormat,\n): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(report, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log('# Provider Debug');\n console.log();\n console.log(`- checkedAt: ${report.checkedAt}`);\n console.log();\n printProviderSection(report.report, 'markdown');\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold('Provider Debug')}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log(label('Checked at', chalk.dim(report.checkedAt)));\n console.log();\n printProviderSection(report.report, 'human');\n}\n\nfunction printNeisDatasetDebugReport(\n report: {\n ok: true;\n dataset: NeisDatasetName;\n query: Record<string, string | number | undefined>;\n rowCount: number;\n totalCount?: number;\n dataStatus: DataStatus;\n providerMetadata?: unknown;\n rows: Record<string, string>[];\n },\n format: OutputFormat,\n): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured(report, format);\n return;\n }\n\n const statusLines = renderDataStatusLines(report.dataStatus);\n if (format === 'markdown') {\n console.log(`# NEIS Dataset Debug: ${report.dataset}`);\n console.log();\n console.log(`- rowCount: ${report.rowCount}`);\n console.log(`- totalCount: ${report.totalCount ?? '(unknown)'}`);\n for (const line of statusLines) {\n console.log(`- ${line}`);\n }\n console.log();\n console.log('```json');\n console.log(JSON.stringify(report.rows, null, 2));\n console.log('```');\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold(`NEIS Dataset: ${report.dataset}`)}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n console.log(label('Rows', `${report.rowCount}${report.totalCount != null ? chalk.dim(` / ${report.totalCount} total`) : ''}`));\n console.log(label('Mode', accessBadge(report.dataStatus.accessMode)));\n console.log(label('Complete', report.dataStatus.complete ? chalk.green('yes') : chalk.yellow('no')));\n console.log(label('Sources', report.dataStatus.sourceProviders.join(', ')));\n for (const warning of report.dataStatus.warnings ?? []) {\n console.log(chalk.yellow(` \u26A0 ${chalk.bold(`[${warning.code}]`)} ${warning.message}`));\n }\n console.log();\n console.log(JSON.stringify(report.rows, null, 2));\n}\n\nfunction printProviderSection(provider: ProviderDebugReport, format: Exclude<OutputFormat, 'json'>): void {\n if (format === 'markdown') {\n const prefix = '- ';\n console.log(`${prefix}${provider.provider}`);\n console.log(` - configured: ${provider.configured}`);\n console.log(` - expectedAccessMode: ${provider.expectedAccessMode}`);\n console.log(` - capabilities: ${provider.capabilities.join(', ')}`);\n for (const note of provider.notes) {\n console.log(` - note: ${note}`);\n }\n if (provider.live) {\n console.log(` - live: ${provider.live.ok ? 'ok' : 'failed'}`);\n console.log(` - check: ${provider.live.check}`);\n console.log(` - message: ${provider.live.message}`);\n if (provider.live.dataStatus) {\n for (const line of renderDataStatusLines(provider.live.dataStatus)) {\n console.log(` - ${line}`);\n }\n }\n if (provider.live.error) {\n console.log(\n ` - error: ${provider.live.error.code} ${provider.live.error.message}`,\n );\n }\n for (const subcheck of provider.live.subchecks ?? []) {\n console.log(\n ` - subcheck ${subcheck.name}: ${subcheck.ok ? 'ok' : 'failed'}`,\n );\n console.log(` - message: ${subcheck.message}`);\n if (subcheck.dataStatus) {\n for (const line of renderDataStatusLines(subcheck.dataStatus)) {\n console.log(` - ${line}`);\n }\n }\n if (subcheck.error) {\n console.log(\n ` - error: ${subcheck.error.code} ${subcheck.error.message}`,\n );\n }\n }\n }\n console.log('');\n return;\n }\n\n // human\n console.log(` ${chalk.bold(provider.provider)} ${accessBadge(provider.expectedAccessMode)}`);\n console.log(` ${chalk.dim('configured')} ${provider.configured ? chalk.green('yes') : chalk.yellow('no')}`);\n console.log(` ${chalk.dim('capabilities')} ${provider.capabilities.join(', ')}`);\n for (const note of provider.notes) {\n console.log(` ${chalk.dim(note)}`);\n }\n if (provider.live) {\n console.log();\n console.log(` ${chalk.dim('live')} ${statusIcon(provider.live.ok)} ${provider.live.ok ? chalk.green('ok') : chalk.red('failed')}`);\n console.log(` ${chalk.dim('check')} ${provider.live.check}`);\n console.log(` ${chalk.dim('result')} ${provider.live.message}`);\n if (provider.live.dataStatus) {\n for (const warning of provider.live.dataStatus.warnings ?? []) {\n console.log(chalk.yellow(` \u26A0 ${chalk.bold(`[${warning.code}]`)} ${warning.message}`));\n }\n }\n if (provider.live.error) {\n console.log(` ${chalk.red(`error: ${provider.live.error.code} ${provider.live.error.message}`)}`);\n }\n for (const subcheck of provider.live.subchecks ?? []) {\n console.log();\n console.log(` ${chalk.dim(subcheck.name)} ${statusIcon(subcheck.ok)} ${subcheck.ok ? chalk.green('ok') : chalk.red('failed')}`);\n console.log(` ${chalk.dim(subcheck.message)}`);\n if (subcheck.dataStatus) {\n for (const warning of subcheck.dataStatus.warnings ?? []) {\n console.log(chalk.yellow(` \u26A0 ${chalk.bold(`[${warning.code}]`)} ${warning.message}`));\n }\n }\n if (subcheck.error) {\n console.log(` ${chalk.red(`error: ${subcheck.error.code} ${subcheck.error.message}`)}`);\n }\n }\n }\n console.log();\n}\n\nfunction renderDataStatusLines(dataStatus?: DataStatus): string[] {\n if (!dataStatus) {\n return [];\n }\n\n const lines = [\n `mode: ${dataStatus.accessMode}`,\n `complete: ${dataStatus.complete ? 'yes' : 'no'}`,\n `sources: ${dataStatus.sourceProviders.join(', ')}`,\n ];\n\n for (const warning of dataStatus.warnings ?? []) {\n lines.push(`warning: ${warning.code} - ${warning.message}`);\n }\n\n return lines;\n}\n\nfunction formatSchool(school: Pick<SchoolSearchResult, 'name' | 'region' | 'schoolType'>): string {\n const extras = [school.region, school.schoolType].filter(Boolean).join(', ');\n return extras ? `${school.name} (${extras})` : school.name;\n}\n\nfunction formatSchoolExtras(school: Pick<SchoolSearchResult, 'region' | 'schoolType'>): string {\n const extras = [school.region, school.schoolType].filter(Boolean).join(', ');\n return extras ? `(${extras})` : '';\n}\n\nfunction formatProviderRefs(school: Pick<SchoolSearchResult, 'providerRefs'>): string {\n const refs: string[] = [];\n if (school.providerRefs.comcigan) {\n refs.push(`comcigan:${school.providerRefs.comcigan.schoolCode}`);\n }\n if (school.providerRefs.neis) {\n refs.push(`neis:${school.providerRefs.neis.officeCode}/${school.providerRefs.neis.schoolCode}`);\n }\n return refs.join(', ') || '(unresolved)';\n}\n\nfunction parseProviderId(value: string): ProviderId {\n const normalized = value.trim().toLowerCase();\n if (normalized === 'comcigan' || normalized === 'neis') {\n return normalized;\n }\n throw new InvalidInputError(`Unknown provider \"${value}\". Use \"comcigan\" or \"neis\".`);\n}\n\nfunction parseNeisDatasetName(value: string): NeisDatasetName {\n const match = NEIS_DATASETS.find((dataset) => dataset.toLowerCase() === value.trim().toLowerCase());\n if (!match) {\n throw new InvalidInputError(`Unknown NEIS dataset \"${value}\".`);\n }\n return match;\n}\n\nfunction parseJsonObject(value: string, _label: string): Record<string, string | number | undefined> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch (error) {\n throw new InvalidInputError(\n `${_label} must be a valid JSON object: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new InvalidInputError(`${_label} must be a JSON object.`);\n }\n\n return Object.fromEntries(\n Object.entries(parsed as Record<string, unknown>).map(([key, entryValue]) => {\n if (\n entryValue == null ||\n typeof entryValue === 'string' ||\n typeof entryValue === 'number'\n ) {\n return [key, entryValue as string | number | undefined];\n }\n\n return [key, JSON.stringify(entryValue)];\n }),\n );\n}\n", "import chalk from 'chalk';\nimport {\n AmbiguousSchoolError,\n InvalidInputError,\n KampusError,\n MealsUnavailableError,\n NetworkError,\n ProviderUnavailableError,\n SchoolNotFoundError,\n TeacherNotFoundError,\n TimetableUnavailableError,\n UpstreamChangedError,\n} from '@kampus/core';\n\nexport type CliErrorFormat = 'human' | 'json' | 'markdown';\n\nexport interface CliErrorPayload {\n ok: false;\n error: {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n };\n}\n\ninterface CommanderLikeError {\n code?: unknown;\n message?: unknown;\n}\n\nexport function detectCliErrorFormat(argv: string[] = process.argv): CliErrorFormat {\n if (argv.includes('--json')) {\n return 'json';\n }\n if (argv.includes('--markdown')) {\n return 'markdown';\n }\n return 'human';\n}\n\nexport function exitCodeForError(error: unknown): number {\n if (error instanceof InvalidInputError || isCommanderError(error)) {\n return 2;\n }\n if (error instanceof SchoolNotFoundError) {\n return 3;\n }\n if (error instanceof AmbiguousSchoolError) {\n return 4;\n }\n if (error instanceof TeacherNotFoundError) {\n return 5;\n }\n if (error instanceof MealsUnavailableError || error instanceof TimetableUnavailableError) {\n return 6;\n }\n if (error instanceof ProviderUnavailableError) {\n return 7;\n }\n if (error instanceof NetworkError) {\n return 8;\n }\n if (error instanceof UpstreamChangedError) {\n return 9;\n }\n return 10;\n}\n\nexport function toCliErrorPayload(error: unknown): CliErrorPayload {\n if (error instanceof AmbiguousSchoolError) {\n return {\n ok: false,\n error: {\n code: error.code,\n message: error.message,\n details: {\n keyword: error.keyword,\n matches: error.matches,\n },\n },\n };\n }\n\n if (error instanceof KampusError) {\n return {\n ok: false,\n error: {\n code: error.code,\n message: error.message,\n },\n };\n }\n\n if (isCommanderError(error)) {\n return {\n ok: false,\n error: {\n code: 'CLI_PARSE_ERROR',\n message: typeof error.message === 'string' ? error.message : 'Invalid CLI input.',\n },\n };\n }\n\n return {\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: error instanceof Error ? error.message : String(error),\n },\n };\n}\n\nexport function renderCliError(error: unknown, format: CliErrorFormat): string {\n const payload = toCliErrorPayload(error);\n\n if (format === 'json') {\n return JSON.stringify(payload, null, 2);\n }\n\n if (format === 'markdown') {\n const lines = [\n '# Error',\n '',\n `- code: ${payload.error.code}`,\n `- message: ${payload.error.message}`,\n ];\n\n const matches = extractMatches(payload);\n if (matches.length) {\n lines.push('- matches:');\n for (const match of matches) {\n lines.push(` - ${match}`);\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n }\n\n const lines = [`Error [${payload.error.code}] ${payload.error.message}`];\n const matches = extractMatches(payload);\n for (const match of matches) {\n lines.push(`- ${match}`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nexport function printCliError(error: unknown, format: CliErrorFormat): void {\n const rendered = renderCliError(error, format);\n if (format === 'json') {\n console.log(rendered);\n return;\n }\n\n if (format === 'human') {\n const payload = toCliErrorPayload(error);\n const lines = [\n ` ${chalk.red('\u2716')} ${chalk.red.bold(`Error [${payload.error.code}]`)} ${payload.error.message}`,\n ];\n const matches = extractMatches(payload);\n for (const match of matches) {\n lines.push(` ${chalk.dim('\u25B8')} ${match}`);\n }\n console.error(lines.join('\\n'));\n return;\n }\n\n console.error(rendered.trimEnd());\n}\n\nfunction extractMatches(payload: CliErrorPayload): string[] {\n const rawMatches = payload.error.details?.matches;\n if (!Array.isArray(rawMatches)) {\n return [];\n }\n\n return rawMatches\n .filter((match): match is { name?: unknown; region?: unknown; schoolType?: unknown } => {\n return !!match && typeof match === 'object';\n })\n .map((match) => {\n const name = typeof match.name === 'string' ? match.name : 'Unknown school';\n const extras = [match.region, match.schoolType]\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n .join(', ');\n return extras ? `${name} (${extras})` : name;\n });\n}\n\nfunction isCommanderError(error: unknown): error is CommanderLikeError {\n if (!error || typeof error !== 'object') {\n return false;\n }\n\n const candidate = error as CommanderLikeError;\n return typeof candidate.code === 'string' && candidate.code.startsWith('commander.');\n}\n", "import type { Command } from 'commander';\nimport { InvalidInputError } from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printDailyMeals, printWeeklyMeals } from '../output.js';\nimport { resolveSchool } from './resolve.js';\n\nexport function mealsCommands(program: Command): void {\n const meals = program.command('meals').description('Meal lookup commands');\n\n meals\n .command('today')\n .description('Fetch meals for a single date')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--date <YYYY-MM-DD>', 'Date override')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps meals today --school \"<school>\" --region \"<region>\" --date 2026-03-12')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const daily = await client.getMealsToday({\n school,\n date: opts.date,\n });\n printDailyMeals(daily, getFormat(opts));\n });\n\n meals\n .command('week')\n .description('Fetch meals for a school week')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--date <YYYY-MM-DD>', 'Any date inside the target week')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps meals week --school \"<school>\" --region \"<region>\"')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const weekly = await client.getMealsWeek({\n school,\n date: opts.date,\n });\n printWeeklyMeals(weekly, getFormat(opts));\n });\n\n meals\n .command('range')\n .description('Fetch meals for a custom date range')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .requiredOption('--from <YYYY-MM-DD>', 'Start date')\n .requiredOption('--to <YYYY-MM-DD>', 'End date')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps meals range --school \"<school>\" --region \"<region>\" --from 2026-03-09 --to 2026-03-13')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const weekly = await client.getMealsRange({\n school,\n fromDate: opts.from,\n toDate: opts.to,\n });\n printWeeklyMeals(weekly, getFormat(opts));\n });\n\n meals\n .command('month')\n .description('Fetch meals for a month')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .requiredOption('--month <YYYY-MM>', 'Target month')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps meals month --school \"<school>\" --region \"<region>\" --month 2026-03')\n .action(async (opts) => {\n const month = parseMonth(opts.month);\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const weekly = await client.getMealsRange({\n school,\n fromDate: `${month}-01`,\n toDate: lastDateOfMonth(month),\n });\n printWeeklyMeals(weekly, getFormat(opts));\n });\n}\n\nfunction parseMonth(value: string): string {\n const trimmed = value.trim();\n if (!/^\\d{4}-\\d{2}$/.test(trimmed)) {\n throw new InvalidInputError('--month must be in YYYY-MM format.');\n }\n return trimmed;\n}\n\nfunction lastDateOfMonth(month: string): string {\n const [yearText, monthText] = month.split('-');\n const year = Number.parseInt(yearText, 10);\n const monthIndex = Number.parseInt(monthText, 10);\n const date = new Date(year, monthIndex, 0);\n const day = String(date.getDate()).padStart(2, '0');\n return `${month}-${day}`;\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport {\n InvalidInputError,\n KampusClient,\n resolveCachePolicy,\n resolveKampusCachePath,\n resolveNeisApiKey,\n} from '@kampus/core';\nimport {\n NeisProvider,\n type NeisAcademicScheduleRecord,\n type NeisAcademyInfoRecord,\n type NeisClassInfoRecord,\n type NeisClassroomInfoRecord,\n type NeisDatasetResult,\n type NeisMajorInfoRecord,\n type NeisOfficialTimetableRecord,\n type NeisTrackInfoRecord,\n} from '@kampus/provider-neis';\nimport { getFormat, printStructured, type OutputFormat } from '../output.js';\nimport { resolveSchool } from './resolve.js';\n\nexport function neisCommands(program: Command): void {\n const neis = program.command('neis').description('Official NEIS Open API commands');\n\n neis\n .command('classes')\n .description('Fetch official NEIS class info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--year <YYYY>', 'Academic year')\n .option('--grade <number>', 'Grade filter')\n .option('--school-course <name>', 'School course name')\n .option('--day-night <name>', 'Day/night course name')\n .option('--track <name>', 'Track name')\n .option('--department <name>', 'Department name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'classInfo',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n year: opts.year,\n grade: optionalNumber(opts.grade, '--grade'),\n schoolCourseName: opts.schoolCourse,\n dayNightCourseName: opts.dayNight,\n trackName: opts.track,\n departmentName: opts.department,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis classes', request, getFormat(opts));\n return;\n }\n const result = await provider.getClassInfoResult({\n school,\n ...request.query,\n });\n printDatasetResult('NEIS class info', result, getFormat(opts), renderClassInfoRecord);\n });\n\n neis\n .command('majors')\n .description('Fetch official NEIS school major info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--day-night <name>', 'Day/night course name')\n .option('--track <name>', 'Track name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'schoolMajorinfo',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n dayNightCourseName: opts.dayNight,\n trackName: opts.track,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis majors', request, getFormat(opts));\n return;\n }\n const result = await provider.getMajorInfoResult({\n school,\n ...request.query,\n });\n printDatasetResult('NEIS major info', result, getFormat(opts), renderMajorInfoRecord);\n });\n\n neis\n .command('tracks')\n .description('Fetch official NEIS school track info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--day-night <name>', 'Day/night course name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'schulAflcoinfo',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n dayNightCourseName: opts.dayNight,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis tracks', request, getFormat(opts));\n return;\n }\n const result = await provider.getTrackInfoResult({\n school,\n ...request.query,\n });\n printDatasetResult('NEIS track info', result, getFormat(opts), renderTrackInfoRecord);\n });\n\n neis\n .command('schedule')\n .description('Fetch official NEIS academic schedule')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--school-course <name>', 'School course name')\n .option('--day-night <name>', 'Day/night course name')\n .option('--date <YYYY-MM-DD>', 'Single date')\n .option('--from <YYYY-MM-DD>', 'Start date')\n .option('--to <YYYY-MM-DD>', 'End date')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--ics', 'Print ICS instead of text/JSON/Markdown')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'SchoolSchedule',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n schoolCourseName: opts.schoolCourse,\n dayNightCourseName: opts.dayNight,\n date: opts.date,\n fromDate: opts.from,\n toDate: opts.to,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis schedule', request, getFormat(opts));\n return;\n }\n const result = await provider.getAcademicScheduleResult({\n school,\n ...request.query,\n });\n\n if (opts.ics) {\n console.log(renderScheduleIcs(school.name, result.rows));\n return;\n }\n\n printDatasetResult('NEIS academic schedule', result, getFormat(opts), renderAcademicScheduleRecord);\n });\n\n neis\n .command('timetable')\n .description('Fetch official NEIS timetable rows')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--year <YYYY>', 'Academic year')\n .option('--semester <number>', 'Semester')\n .option('--date <YYYY-MM-DD>', 'Single date')\n .option('--from <YYYY-MM-DD>', 'Start date')\n .option('--to <YYYY-MM-DD>', 'End date')\n .option('--grade <number>', 'Grade')\n .option('--class-name <name>', 'Class name')\n .option('--period <number>', 'Period')\n .option('--school-course <name>', 'School course name')\n .option('--day-night <name>', 'Day/night course name')\n .option('--track <name>', 'Track name')\n .option('--department <name>', 'Department name')\n .option('--classroom <name>', 'Classroom name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'officialTimetable',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n year: opts.year,\n semester: opts.semester,\n date: opts.date,\n fromDate: opts.from,\n toDate: opts.to,\n grade: optionalNumber(opts.grade, '--grade'),\n className: opts.className,\n period: optionalNumber(opts.period, '--period'),\n schoolCourseName: opts.schoolCourse,\n dayNightCourseName: opts.dayNight,\n trackName: opts.track,\n departmentName: opts.department,\n classroomName: opts.classroom,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis timetable', request, getFormat(opts));\n return;\n }\n const result = await provider.getOfficialTimetableResult({\n school,\n ...request.query,\n });\n printDatasetResult('NEIS official timetable', result, getFormat(opts), renderOfficialTimetableRecord);\n });\n\n neis\n .command('classrooms')\n .description('Fetch official NEIS classroom info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--year <YYYY>', 'Academic year')\n .option('--grade <number>', 'Grade')\n .option('--semester <number>', 'Semester')\n .option('--school-course <name>', 'School course name')\n .option('--day-night <name>', 'Day/night course name')\n .option('--track <name>', 'Track name')\n .option('--department <name>', 'Department name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const school = await resolveNeisSchool(provider, opts.school, opts.region);\n const request = {\n dataset: 'tiClrminfo',\n school: {\n name: school.name,\n region: school.region,\n providerRefs: school.providerRefs,\n },\n query: {\n year: opts.year,\n grade: optionalNumber(opts.grade, '--grade'),\n semester: opts.semester,\n schoolCourseName: opts.schoolCourse,\n dayNightCourseName: opts.dayNight,\n trackName: opts.track,\n departmentName: opts.department,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis classrooms', request, getFormat(opts));\n return;\n }\n const result = await provider.getClassroomInfoResult({\n school,\n ...request.query,\n });\n printDatasetResult('NEIS classroom info', result, getFormat(opts), renderClassroomInfoRecord);\n });\n\n neis\n .command('academies')\n .description('Search official NEIS academy info')\n .option('--office-code <code>', 'Office code such as B10 or J10')\n .option('--zone <name>', 'Administrative zone name')\n .option('--number <value>', 'Academy serial number')\n .option('--name <name>', 'Academy name')\n .option('--field <name>', 'Field name')\n .option('--series <name>', 'Series name')\n .option('--course <name>', 'Course name')\n .option('--page-limit <n>', 'Maximum number of auto-fetched pages', parseInt)\n .option('--dry-run', 'Print the NEIS request plan without executing it')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .action(async (opts) => {\n const provider = createNeisProvider(opts.pageLimit);\n const request = {\n dataset: 'acaInsTiInfo',\n query: {\n officeCode: opts.officeCode,\n adminZoneName: opts.zone,\n academyNumber: opts.number,\n academyName: opts.name,\n fieldName: opts.field,\n seriesName: opts.series,\n courseName: opts.course,\n },\n pageLimit: opts.pageLimit,\n };\n if (opts.dryRun) {\n printDryRunPlan('neis academies', request, getFormat(opts));\n return;\n }\n const result = await provider.searchAcademyInfoResult(request.query);\n printDatasetResult('NEIS academy info', result, getFormat(opts), renderAcademyInfoRecord);\n });\n}\n\nfunction createNeisProvider(pageLimit?: number): NeisProvider {\n const cachePolicy = resolveCachePolicy();\n return new NeisProvider({\n apiKey: resolveNeisApiKey(),\n maxAutoPages: pageLimit,\n cachePath: resolveKampusCachePath(),\n cacheTtlMs: cachePolicy.datasetTtlMinutes * 60 * 1000,\n staleIfErrorMs: cachePolicy.staleIfErrorHours * 60 * 60 * 1000,\n cacheMaxEntries: cachePolicy.maxEntries,\n });\n}\n\nasync function resolveNeisSchool(provider: NeisProvider, name?: string, region?: string) {\n const client = new KampusClient({\n providers: [provider],\n });\n return resolveSchool(client, name, region);\n}\n\nfunction optionalNumber(value: string | undefined, _label: string): number | undefined {\n if (value == null) {\n return undefined;\n }\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed)) {\n throw new InvalidInputError(`${_label} must be an integer.`);\n }\n return parsed;\n}\n\n/* \u2500\u2500 Access badge helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction accessBadge(mode: string): string {\n switch (mode) {\n case 'official-full': return chalk.green.bold('OFFICIAL');\n case 'official-limited': return chalk.yellow.bold('LIMITED');\n case 'unofficial': return chalk.dim('UNOFFICIAL');\n default: return chalk.dim(mode);\n }\n}\n\n/* \u2500\u2500 Dataset result printer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction printDatasetResult<T>(\n title: string,\n result: NeisDatasetResult<T>,\n format: OutputFormat,\n render: (record: T) => string,\n): void {\n if (format !== 'human' && format !== 'markdown') {\n printStructured({\n totalCount: result.totalCount,\n dataStatus: result.dataStatus,\n providerMetadata: result.providerMetadata,\n rows: result.rows,\n }, format);\n return;\n }\n\n const statusLines = renderStatusLines(result);\n if (format === 'markdown') {\n console.log(`# ${title}`);\n console.log();\n for (const line of statusLines) {\n console.log(`> ${line}`);\n }\n if (!result.rows.length) {\n console.log();\n console.log('No records matched.');\n return;\n }\n console.log();\n for (const record of result.rows) {\n console.log(`- ${render(record)}`);\n }\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold(title)}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n\n const rowLabel = `${result.rows.length}${result.totalCount != null ? chalk.dim(` / ${result.totalCount} total`) : ''}`;\n console.log(` ${accessBadge(result.dataStatus.accessMode)} ${result.dataStatus.complete ? chalk.green('complete') : chalk.yellow('incomplete')} ${chalk.dim(`rows: ${rowLabel}`)}`);\n console.log(` ${chalk.dim(`via ${result.dataStatus.sourceProviders.join(', ')}`)}`);\n\n for (const warning of result.dataStatus.warnings ?? []) {\n console.log(chalk.yellow(` \u26A0 ${chalk.bold(`[${warning.code}]`)} ${warning.message}`));\n }\n\n if (!result.rows.length) {\n console.log();\n console.log(chalk.dim(' No records matched.'));\n return;\n }\n console.log();\n for (const record of result.rows) {\n console.log(` ${chalk.dim('\u25B8')} ${render(record)}`);\n }\n console.log();\n}\n\nfunction renderStatusLines<T>(result: NeisDatasetResult<T>): string[] {\n const lines = [\n `mode: ${result.dataStatus.accessMode}`,\n `complete: ${result.dataStatus.complete ? 'yes' : 'no'}`,\n `rows: ${result.rows.length}${result.totalCount != null ? ` / ${result.totalCount}` : ''}`,\n `sources: ${result.dataStatus.sourceProviders.join(', ')}`,\n ];\n\n for (const warning of result.dataStatus.warnings ?? []) {\n lines.push(`warning: [${warning.code}] ${warning.message}`);\n }\n\n return lines;\n}\n\n/* \u2500\u2500 Record renderers (unchanged data) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderClassInfoRecord(row: NeisClassInfoRecord): string {\n return [\n row.year,\n row.grade ? `${row.grade} grade` : undefined,\n row.className ? `class ${row.className}` : undefined,\n row.departmentName,\n row.trackName,\n row.dayNightCourseName,\n ]\n .filter(Boolean)\n .join(' | ');\n}\n\nfunction renderMajorInfoRecord(row: NeisMajorInfoRecord): string {\n return [row.departmentName, row.trackName, row.dayNightCourseName].filter(Boolean).join(' | ');\n}\n\nfunction renderTrackInfoRecord(row: NeisTrackInfoRecord): string {\n return [row.trackName, row.dayNightCourseName].filter(Boolean).join(' | ');\n}\n\nfunction renderAcademicScheduleRecord(row: NeisAcademicScheduleRecord): string {\n const grades = row.gradeEventYears.length ? `grades ${row.gradeEventYears.join(',')}` : undefined;\n return [row.date, row.eventName, row.eventContent, grades].filter(Boolean).join(' | ');\n}\n\nfunction renderOfficialTimetableRecord(row: NeisOfficialTimetableRecord): string {\n return [\n row.date,\n row.grade ? `${row.grade} grade` : undefined,\n row.className ? `class ${row.className}` : undefined,\n row.period ? `period ${row.period}` : undefined,\n row.content,\n row.classroomName,\n ]\n .filter(Boolean)\n .join(' | ');\n}\n\nfunction renderClassroomInfoRecord(row: NeisClassroomInfoRecord): string {\n return [\n row.year,\n row.grade ? `${row.grade} grade` : undefined,\n row.semester ? `semester ${row.semester}` : undefined,\n row.classroomName,\n row.departmentName,\n row.trackName,\n ]\n .filter(Boolean)\n .join(' | ');\n}\n\nfunction renderAcademyInfoRecord(row: NeisAcademyInfoRecord): string {\n return [\n row.academyName,\n row.adminZoneName,\n row.fieldName,\n row.seriesName,\n row.courseName,\n row.academyNumber,\n ]\n .filter(Boolean)\n .join(' | ');\n}\n\n/* \u2500\u2500 ICS renderer (unchanged) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction renderScheduleIcs(schoolName: string, rows: NeisAcademicScheduleRecord[]): string {\n const lines = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Kampus//NEIS Schedule//EN'];\n\n rows.forEach((row, index) => {\n if (!row.date || !row.eventName) {\n return;\n }\n\n const compactDate = row.date.replace(/-/g, '');\n const summary = escapeIcsText(row.eventName);\n const description = escapeIcsText(row.eventContent ?? '');\n const uidBase = summary.replace(/[^A-Za-z0-9]/g, '') || 'event';\n const uid = `${compactDate}-${uidBase}-${index + 1}@kampus`;\n\n lines.push('BEGIN:VEVENT');\n lines.push(`UID:${uid}`);\n lines.push(`DTSTAMP:${new Date().toISOString().replace(/[-:]/g, '').replace(/\\.\\d{3}Z$/, 'Z')}`);\n lines.push(`DTSTART;VALUE=DATE:${compactDate}`);\n lines.push(`SUMMARY:${summary}`);\n if (description) {\n lines.push(`DESCRIPTION:${description}`);\n }\n lines.push(`LOCATION:${escapeIcsText(schoolName)}`);\n lines.push('END:VEVENT');\n });\n\n lines.push('END:VCALENDAR');\n return `${lines.join('\\r\\n')}\\r\\n`;\n}\n\nfunction escapeIcsText(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/,/g, '\\\\,').replace(/;/g, '\\\\;');\n}\n\n/* \u2500\u2500 Dry run printer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction printDryRunPlan(command: string, payload: unknown, format: OutputFormat): void {\n const envelope = {\n ok: true,\n dryRun: true,\n command,\n payload,\n accessMode: resolveNeisApiKey() ? 'official-full' : 'official-limited',\n };\n\n if (format !== 'human' && format !== 'markdown') {\n printStructured(envelope, format);\n return;\n }\n\n if (format === 'markdown') {\n console.log(`# Dry Run: ${command}`);\n console.log();\n console.log('```json');\n console.log(JSON.stringify(envelope, null, 2));\n console.log('```');\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold(`Dry Run: ${command}`)}`);\n console.log(` ${chalk.dim('\u2500'.repeat(48))}`);\n console.log();\n console.log(JSON.stringify(envelope, null, 2));\n console.log();\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport {\n getActiveProfile,\n listProfiles,\n loadKampusConfig,\n removeProfile,\n saveKampusConfig,\n setActiveProfile,\n type KampusProfile,\n upsertProfile,\n} from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printStructured } from '../output.js';\nimport { getDefaultSchool, resolveSchool } from './resolve.js';\n\nexport function profileCommands(program: Command): void {\n const profile = program.command('profile').description('Manage reusable Kampus profiles');\n\n profile\n .command('list')\n .description('List saved profiles')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action((opts) => {\n const format = getFormat(opts);\n const config = loadKampusConfig();\n const payload = {\n activeProfile: getActiveProfile(config)?.name,\n profiles: listProfiles(config),\n };\n\n if (format !== 'human') {\n printStructured(payload, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log();\n console.log(` ${chalk.dim('active')} ${payload.activeProfile ? chalk.green(payload.activeProfile) : chalk.dim('(none)')}`);\n if (!payload.profiles.length) {\n console.log(chalk.dim(' No profiles saved.'));\n console.log();\n return;\n }\n console.log();\n for (const entry of payload.profiles) {\n const isActive = payload.activeProfile === entry.name;\n const icon = isActive ? chalk.green('\u25CF') : chalk.dim('\u25CB');\n const name = isActive ? chalk.green.bold(entry.name) : entry.name;\n console.log(` ${icon} ${name}`);\n }\n console.log();\n });\n\n profile\n .command('show [name]')\n .description('Show a saved profile or the active profile')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action((name: string | undefined, opts) => {\n const format = getFormat(opts);\n const config = loadKampusConfig();\n const entry = findProfile(config, name);\n if (format !== 'human') {\n printStructured(entry ?? null, format === 'markdown' ? 'json' : format);\n return;\n }\n if (!entry) {\n console.log(chalk.dim(' No matching profile found.'));\n return;\n }\n printProfile(entry, getActiveProfile(config)?.name === entry.name);\n });\n\n profile\n .command('save <name>')\n .description('Save or update a reusable profile')\n .option('--school <name>', 'School name')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Default grade', parseInt)\n .option('--class <n>', 'Default class number', parseInt)\n .option('--teacher <name>', 'Default teacher name')\n .option('--notes <text>', 'Optional notes')\n .option('--activate', 'Set the saved profile as active immediately')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .action(async (name: string, opts) => {\n const format = getFormat(opts);\n const client = createClient();\n const defaultSchool = getDefaultSchool();\n const school =\n opts.school || opts.region\n ? await resolveSchool(client, opts.school, opts.region)\n : defaultSchool;\n\n let nextConfig = upsertProfile(loadKampusConfig(), {\n name,\n school,\n grade: opts.grade,\n classNo: opts.class,\n teacherName: opts.teacher,\n notes: opts.notes,\n });\n\n if (opts.activate) {\n nextConfig = setActiveProfile(nextConfig, name);\n }\n\n saveKampusConfig(nextConfig);\n const entry = findProfile(nextConfig, name);\n\n if (format !== 'human') {\n printStructured({\n ok: true,\n active: opts.activate,\n profile: entry,\n }, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log(` ${chalk.green('\u2713')} Saved profile: ${chalk.bold(name)}`);\n if (opts.activate) {\n console.log(` ${chalk.green('\u25CF')} Profile is now active.`);\n }\n if (entry) {\n printProfile(entry, opts.activate);\n }\n });\n\n profile\n .command('use <name>')\n .description('Set the active profile')\n .action((name: string) => {\n const nextConfig = setActiveProfile(loadKampusConfig(), name);\n saveKampusConfig(nextConfig);\n console.log(` ${chalk.green('\u25CF')} Active profile: ${chalk.bold(findProfile(nextConfig, name)?.name ?? name)}`);\n });\n\n profile\n .command('clear-active')\n .description('Clear the active profile selection')\n .action(() => {\n saveKampusConfig(setActiveProfile(loadKampusConfig(), undefined));\n console.log(` ${chalk.green('\u2713')} Cleared the active profile.`);\n });\n\n profile\n .command('remove <name>')\n .description('Remove a saved profile')\n .action((name: string) => {\n saveKampusConfig(removeProfile(loadKampusConfig(), name));\n console.log(` ${chalk.green('\u2713')} Removed profile: ${chalk.bold(name)}`);\n });\n}\n\nfunction findProfile(config: ReturnType<typeof loadKampusConfig>, name?: string): KampusProfile | undefined {\n if (!name) {\n return getActiveProfile(config);\n }\n\n return listProfiles(config).find((entry) => entry.name.toLowerCase() === name.trim().toLowerCase());\n}\n\nfunction printProfile(profile: KampusProfile, active: boolean): void {\n console.log();\n const icon = active ? chalk.green('\u25CF') : chalk.dim('\u25CB');\n console.log(` ${icon} ${chalk.bold(profile.name)}`);\n if (profile.school) {\n const extras = [profile.school.region, profile.school.schoolType].filter(Boolean).join(', ');\n const label = extras ? `${profile.school.name} ${chalk.dim(`(${extras})`)}` : profile.school.name;\n console.log(` ${chalk.dim('school')} ${label}`);\n }\n if (profile.grade) {\n console.log(` ${chalk.dim('grade')} ${profile.grade}`);\n }\n if (profile.classNo) {\n console.log(` ${chalk.dim('class')} ${profile.classNo}`);\n }\n if (profile.teacherName) {\n console.log(` ${chalk.dim('teacher')} ${profile.teacherName}`);\n }\n if (profile.notes) {\n console.log(` ${chalk.dim('notes')} ${profile.notes}`);\n }\n console.log();\n}\n", "import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printSchoolInfo, printSchoolSearch, printStructured } from '../output.js';\nimport { resolveSchool } from './resolve.js';\n\nfunction formatResolvedRefs(school: Awaited<ReturnType<typeof resolveSchool>>): string {\n const refs: string[] = [];\n if (school.providerRefs.neis) {\n refs.push(`neis:${school.providerRefs.neis.officeCode}/${school.providerRefs.neis.schoolCode}`);\n }\n if (school.providerRefs.comcigan) {\n refs.push(`comcigan:${school.providerRefs.comcigan.schoolCode}`);\n }\n return refs.join(', ') || '(unresolved)';\n}\n\nexport function schoolCommands(program: Command): void {\n const school = program.command('school').description('Search and resolve school identities');\n\n school\n .command('search <keyword>')\n .description('Search schools by keyword')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExamples:\\n kps school search \"<keyword>\"\\n kps school search \"<keyword>\" --json')\n .action(async (keyword: string, opts) => {\n const client = createClient();\n const results = await client.searchSchools(keyword);\n printSchoolSearch(results, getFormat(opts));\n });\n\n school\n .command('info')\n .description('Fetch normalized school info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps school info --school \"<school>\" --region \"<region>\"')\n .action(async (opts) => {\n const client = createClient();\n const resolved = await resolveSchool(client, opts.school, opts.region);\n const info = await client.getSchoolInfo(resolved);\n printSchoolInfo(info, getFormat(opts));\n });\n\n school\n .command('resolve <name>')\n .description('Resolve a school into provider refs')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .addHelpText('after', '\\nExample:\\n kps school resolve \"<school>\" --region \"<region>\" --json')\n .action(async (name: string, opts) => {\n const client = createClient();\n const resolved = await resolveSchool(client, name, opts.region);\n const format = getFormat(opts);\n if (format !== 'human') {\n printStructured(resolved, format === 'markdown' ? 'json' : format);\n return;\n }\n\n console.log();\n console.log(` ${chalk.bold(resolved.name)}`);\n if (resolved.region) {\n console.log(` ${chalk.dim('region')} ${resolved.region}`);\n }\n if (resolved.schoolType) {\n console.log(` ${chalk.dim('type')} ${resolved.schoolType}`);\n }\n console.log(` ${chalk.dim('refs')} ${chalk.magenta(formatResolvedRefs(resolved))}`);\n console.log();\n });\n}\n", "import type { Command } from 'commander';\nimport { InvalidInputError } from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printTeacherInfo, printTeacherTimetable } from '../output.js';\nimport { resolveSchool, resolveTeacherDefault } from './resolve.js';\n\nexport function teacherCommands(program: Command): void {\n const teacher = program.command('teacher').description('Teacher timetable and info commands');\n\n teacher\n .command('timetable')\n .description('Fetch a teacher timetable')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--teacher <name>', 'Teacher name (falls back to active profile)')\n .option('--weekday <n>', 'Weekday (1-7)', parseInt)\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps teacher timetable --school \"<school>\" --region \"<region>\" --teacher \"<teacher>\"')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const teacherName = requireTeacherName(opts.teacher);\n const timetable = await client.getTeacherTimetable({\n school,\n teacherName,\n weekday: opts.weekday,\n });\n printTeacherTimetable(timetable, getFormat(opts));\n });\n\n teacher\n .command('info')\n .description('Fetch normalized teacher info')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--teacher <name>', 'Teacher name (falls back to active profile)')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps teacher info --school \"<school>\" --region \"<region>\" --teacher \"<teacher>\"')\n .action(async (opts) => {\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const teacherName = requireTeacherName(opts.teacher);\n const info = await client.getTeacherInfo({\n school,\n teacherName,\n });\n printTeacherInfo(info, getFormat(opts));\n });\n}\n\nfunction requireTeacherName(value?: string): string {\n const resolved = resolveTeacherDefault(value);\n if (!resolved) {\n throw new InvalidInputError(\n 'Teacher name is required. Pass --teacher or save it in the active profile.',\n );\n }\n return resolved;\n}\n", "\uFEFFimport { Box, Text, render, useApp, useInput, useStdin } from 'ink';\nimport { useEffect, useMemo, useState } from 'react';\nimport { KAMPUS_TAGLINE } from './logo.js';\nimport { Callout, FocusBanner, Footer, Header, Navigation, NoticeBanner, Panel } from './components.js';\nimport {\n DiagnosticsPage,\n EasyModeView,\n HelpPage,\n HomePage,\n MealsPage,\n SchoolsPage,\n SettingsPage,\n SplashScreen,\n TeacherPage,\n TimetablePage,\n} from './pages.js';\nimport {\n clamp,\n isTypingInput,\n pageIndexFor,\n resolvePageShortcut,\n resolveRecentSchoolShortcut,\n} from './shortcuts.js';\nimport {\n HUMAN_PAGES,\n createInitialAsyncPageStates,\n createInitialSettingsState,\n isAsyncDataPage,\n type AsyncDataPageId,\n type AsyncPageDataMap,\n type AsyncPageStateMap,\n type EasyState,\n type InteractiveMode,\n type KeyLike,\n type SearchState,\n type SettingsActionId,\n type SettingsDialog,\n type SettingsState,\n} from './types.js';\nimport {\n activateHumanProfileSelection,\n clearHumanDefaultSchoolSelection,\n clearHumanActiveProfileSelection,\n loadHumanDiagnostics,\n loadHumanHomeData,\n loadHumanSessionContext,\n loadHumanTeacherData,\n loadHumanWeekTimetable,\n loadHumanWeeklyMeals,\n removeHumanProfileSelection,\n removeHumanRecentSchoolSelection,\n saveHumanSessionProfile,\n saveEasyProfile,\n saveHumanDefaultSchoolSelection,\n searchHumanSchools,\n type HumanSessionContext,\n} from '../usecases/human.js';\nimport {\n buildSettingsActions,\n buildSettingsDialog,\n cycleSettingsSection,\n isDestructiveSettingsAction,\n moveSettingsSelection,\n} from './settings.js';\nimport { pageTone } from './theme.js';\nimport type { AccentTone } from './theme.js';\n\ninterface InteractiveOptions {\n mode: InteractiveMode;\n splash?: boolean;\n}\n\ninterface NoticeState {\n title: string;\n message: string;\n accent: AccentTone;\n}\n\ntype LineInputTarget = 'school-query' | 'easy-school-query' | 'easy-teacher-name';\n\ninterface LineInputState {\n target: LineInputTarget;\n title: string;\n description: string;\n accent: AccentTone;\n}\n\nexport function canRunInteractiveCli(\n stdinIsTty = Boolean(process.stdin.isTTY),\n stdoutIsTty = Boolean(process.stdout.isTTY),\n): boolean {\n return stdinIsTty && stdoutIsTty;\n}\n\nexport async function runInteractiveCli(options: InteractiveOptions): Promise<void> {\n if (!canRunInteractiveCli()) {\n throw new Error('Interactive human/easy mode requires an interactive TTY terminal.');\n }\n\n const app = render(<InteractiveCliApp mode={options.mode} splash={options.splash ?? true} />);\n await app.waitUntilExit();\n}\n\nfunction InteractiveCliApp({ mode, splash }: InteractiveOptions) {\n const { exit } = useApp();\n const { stdin, setRawMode, isRawModeSupported } = useStdin();\n const [effectiveMode, setEffectiveMode] = useState<InteractiveMode>(mode);\n const [showSplash, setShowSplash] = useState(Boolean(splash));\n const [session, setSession] = useState<HumanSessionContext | null>(null);\n const [sessionError, setSessionError] = useState<string | null>(null);\n const [loadingSession, setLoadingSession] = useState(true);\n const [pageIndex, setPageIndex] = useState(0);\n const [notice, setNotice] = useState<NoticeState | null>(\n mode === 'easy'\n ? {\n title: 'Easy mode ready',\n message: 'Easy mode will guide you through school and profile setup.',\n accent: 'blue',\n }\n : null,\n );\n const [lineInput, setLineInput] = useState<LineInputState | undefined>(undefined);\n const [pageStates, setPageStates] = useState<AsyncPageStateMap>(createInitialAsyncPageStates);\n const [settingsState, setSettingsState] = useState<SettingsState>(createInitialSettingsState);\n const [settingsDialog, setSettingsDialog] = useState<SettingsDialog | undefined>(undefined);\n const [searchState, setSearchState] = useState<SearchState>({\n query: '',\n dirty: false,\n loading: false,\n results: [],\n selectedIndex: 0,\n });\n const [easyState, setEasyState] = useState<EasyState>({\n step: 'welcome',\n query: '',\n dirty: false,\n loading: false,\n results: [],\n selectedIndex: 0,\n grade: 3,\n classNo: 1,\n teacherName: '',\n });\n\n const currentPage = HUMAN_PAGES[pageIndex] ?? HUMAN_PAGES[0];\n const currentAsyncPageState = isAsyncDataPage(currentPage.id)\n ? pageStates[currentPage.id]\n : undefined;\n const inputLocked =\n effectiveMode === 'easy'\n ? easyState.loading || easyState.step === 'saving'\n : loadingSession || searchState.loading || currentAsyncPageState?.loading;\n\n useEffect(() => {\n void refreshSession();\n }, []);\n\n useEffect(() => {\n if (!showSplash) {\n return undefined;\n }\n\n const timer = setTimeout(() => {\n setShowSplash(false);\n }, 1200);\n\n return () => clearTimeout(timer);\n }, [showSplash]);\n\n useEffect(() => {\n if (effectiveMode !== 'human' || showSplash || !session || !isAsyncDataPage(currentPage.id)) {\n return;\n }\n\n const pageId = currentPage.id;\n let active = true;\n setAsyncPageState(pageId, { loading: true, error: undefined });\n\n void loadAsyncPage(pageId, session)\n .then((data) => {\n if (!active) {\n return;\n }\n\n replaceAsyncPageState(pageId, {\n loading: false,\n error: undefined,\n data,\n } as AsyncPageStateMap[typeof pageId]);\n })\n .catch((error) => {\n if (!active) {\n return;\n }\n\n replaceAsyncPageState(pageId, {\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n data: undefined,\n } as AsyncPageStateMap[typeof pageId]);\n });\n\n return () => {\n active = false;\n };\n }, [currentPage.id, effectiveMode, session, showSplash]);\n\n useEffect(() => {\n if (!session) {\n return;\n }\n\n setEasyState((current) => ({\n ...current,\n grade: session.grade ?? current.grade,\n classNo: session.classNo ?? current.classNo,\n teacherName: session.teacherName ?? current.teacherName,\n }));\n\n if (!searchState.query && session.selectedSchool?.name) {\n setSearchState((current) => ({\n ...current,\n query: session.selectedSchool?.name ?? '',\n }));\n }\n\n setSettingsState((current) => alignSettingsState(current, session));\n }, [session]);\n\n useEffect(() => {\n if (currentPage.id !== 'settings' && settingsDialog) {\n setSettingsDialog(undefined);\n }\n }, [currentPage.id, settingsDialog]);\n\n useEffect(() => {\n if (!lineInput) {\n return undefined;\n }\n\n if (!isRawModeSupported) {\n setLineInput(undefined);\n setNotice({\n title: 'Input fallback',\n message: 'This terminal does not support IME-safe line capture. Continue with direct typing.',\n accent: 'yellow',\n });\n return undefined;\n }\n\n let active = true;\n let buffer = '';\n stdin.setEncoding('utf8');\n stdin.resume();\n setRawMode(false);\n\n const onData = (chunk: string | Buffer) => {\n if (!active) {\n return;\n }\n\n const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');\n if (text.includes('\\u0003')) {\n exit();\n return;\n }\n\n buffer += text;\n if (!/[\\r\\n]/u.test(text)) {\n return;\n }\n\n const value = buffer.replace(/\\r?\\n/gu, '');\n buffer = '';\n process.stdout.write('\\u001b[2K\\r');\n applyLineInputValue(lineInput.target, value);\n };\n\n stdin.on('data', onData);\n\n return () => {\n active = false;\n stdin.off('data', onData);\n setRawMode(true);\n };\n }, [exit, isRawModeSupported, lineInput, setRawMode, stdin]);\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n exit();\n return;\n }\n\n if (showSplash) {\n if (key.return || key.escape || isTypingInput(input, key)) {\n setShowSplash(false);\n }\n return;\n }\n\n if (effectiveMode === 'easy') {\n handleEasyInput(input, key);\n return;\n }\n\n handleHumanInput(input, key);\n }, { isActive: !lineInput });\n\n const headerSummary = useMemo(\n () => ({\n school: session?.selectedSchool?.name ?? 'No school selected',\n profile: session?.activeProfile?.name ?? 'No active profile',\n access: session?.configStatus.neisApiKeyConfigured ? 'official-full' : 'official-limited',\n }),\n [session],\n );\n\n const focusState = useMemo(() => {\n if (effectiveMode === 'easy') {\n return deriveEasyFocusState(easyState, lineInput);\n }\n\n return deriveHumanFocusState(currentPage.id, settingsState, settingsDialog, lineInput);\n }, [currentPage.id, easyState, effectiveMode, lineInput, settingsDialog, settingsState]);\n\n function setInfoNotice(message: string, title = 'Live notice', accent: AccentTone = 'cyan'): void {\n setNotice({\n title,\n message,\n accent,\n });\n }\n\n function setAsyncPageState<K extends AsyncDataPageId>(\n page: K,\n next: Partial<AsyncPageStateMap[K]>,\n ): void {\n setPageStates((current) => ({\n ...current,\n [page]: {\n ...current[page],\n ...next,\n },\n }));\n }\n\n function replaceAsyncPageState<K extends AsyncDataPageId>(\n page: K,\n next: AsyncPageStateMap[K],\n ): void {\n setPageStates((current) => ({\n ...current,\n [page]: next,\n }));\n }\n\n async function refreshSession(nextNotice?: string): Promise<void> {\n setLoadingSession(true);\n setSessionError(null);\n\n try {\n const nextSession = await loadHumanSessionContext();\n applyNextSession(nextSession, nextNotice);\n } catch (error) {\n setSessionError(error instanceof Error ? error.message : String(error));\n } finally {\n setLoadingSession(false);\n }\n }\n\n function applyNextSession(nextSession: HumanSessionContext, nextNotice?: string): void {\n setSession(nextSession);\n setSettingsState((current) => alignSettingsState(current, nextSession));\n setSettingsDialog(undefined);\n if (nextNotice) {\n setInfoNotice(nextNotice);\n }\n }\n\n async function runSessionMutation(\n task: () => Promise<HumanSessionContext>,\n nextNotice: string,\n ): Promise<void> {\n setLoadingSession(true);\n setSessionError(null);\n\n try {\n const nextSession = await task();\n applyNextSession(nextSession, nextNotice);\n } catch (error) {\n setSessionError(error instanceof Error ? error.message : String(error));\n } finally {\n setLoadingSession(false);\n }\n }\n\n async function refreshCurrentPage(): Promise<void> {\n if (!session || !isAsyncDataPage(currentPage.id)) {\n return;\n }\n\n const pageId = currentPage.id;\n setAsyncPageState(pageId, {\n loading: true,\n error: undefined,\n });\n\n try {\n const data = await loadAsyncPage(pageId, session);\n replaceAsyncPageState(pageId, {\n loading: false,\n error: undefined,\n data,\n } as AsyncPageStateMap[typeof pageId]);\n } catch (error) {\n replaceAsyncPageState(pageId, {\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n data: undefined,\n } as AsyncPageStateMap[typeof pageId]);\n }\n }\n\n async function runSchoolSearch(query: string): Promise<void> {\n const trimmed = query.trim();\n if (!trimmed) {\n setSearchState((current) => ({\n ...current,\n error: 'Type a school name before searching.',\n }));\n return;\n }\n\n setSearchState((current) => ({\n ...current,\n loading: true,\n error: undefined,\n }));\n\n try {\n const results = await searchHumanSchools(trimmed);\n setSearchState((current) => ({\n ...current,\n loading: false,\n dirty: false,\n results,\n selectedIndex: 0,\n }));\n setInfoNotice(\n results.length\n ? `Loaded ${results.length} school result(s).`\n : 'No schools matched that keyword.',\n 'Search results',\n results.length ? 'cyan' : 'yellow',\n );\n } catch (error) {\n setSearchState((current) => ({\n ...current,\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n }));\n }\n }\n\n async function applySchoolSelection(): Promise<void> {\n const selected = searchState.results[searchState.selectedIndex];\n if (!selected) {\n return;\n }\n\n setSearchState((current) => ({\n ...current,\n loading: true,\n error: undefined,\n }));\n\n try {\n const nextSession = await saveHumanDefaultSchoolSelection(selected);\n applyNextSession(nextSession, `Selected ${selected.name} as the current school.`);\n setSearchState((current) => ({\n ...current,\n loading: false,\n query: selected.name,\n dirty: false,\n }));\n } catch (error) {\n setSearchState((current) => ({\n ...current,\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n }));\n }\n }\n\n async function runEasySearch(query: string): Promise<void> {\n const trimmed = query.trim();\n if (!trimmed) {\n setEasyState((current) => ({\n ...current,\n error: 'Type a school name before searching.',\n }));\n return;\n }\n\n setEasyState((current) => ({\n ...current,\n loading: true,\n error: undefined,\n }));\n\n try {\n const results = await searchHumanSchools(trimmed);\n setEasyState((current) => ({\n ...current,\n loading: false,\n dirty: false,\n results,\n selectedIndex: 0,\n step: 'search',\n }));\n } catch (error) {\n setEasyState((current) => ({\n ...current,\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n }));\n }\n }\n\n async function finishEasyMode(): Promise<void> {\n const selected = easyState.results[easyState.selectedIndex];\n if (!selected) {\n setEasyState((current) => ({\n ...current,\n error: 'Select a school before saving easy mode.',\n }));\n return;\n }\n\n setEasyState((current) => ({\n ...current,\n loading: true,\n step: 'saving',\n error: undefined,\n }));\n\n try {\n const nextSession = await saveEasyProfile({\n school: selected,\n grade: easyState.grade,\n classNo: easyState.classNo,\n teacherName: easyState.teacherName || undefined,\n });\n applyNextSession(\n nextSession,\n `Easy mode saved \"easy-default\" and selected ${selected.name}.`,\n );\n setEffectiveMode('human');\n setPageIndex(0);\n } catch (error) {\n setEasyState((current) => ({\n ...current,\n loading: false,\n step: 'teacher',\n error: error instanceof Error ? error.message : String(error),\n }));\n }\n }\n\n function handleHumanInput(input: string, key: KeyLike): void {\n if (inputLocked) {\n return;\n }\n\n const shortcutPage = resolvePageShortcut(input);\n if (shortcutPage) {\n const shortcutIndex = pageIndexFor(shortcutPage);\n if (shortcutIndex >= 0) {\n setPageIndex(shortcutIndex);\n }\n return;\n }\n\n if (currentPage.id !== 'schools' && !key.meta && !key.ctrl && input === 'q') {\n exit();\n return;\n }\n\n if (currentPage.id === 'settings' && handleSettingsInput(input, key)) {\n return;\n }\n\n if (key.leftArrow) {\n setPageIndex((current) => (current - 1 + HUMAN_PAGES.length) % HUMAN_PAGES.length);\n return;\n }\n if (key.rightArrow || key.tab) {\n setPageIndex((current) => (current + 1) % HUMAN_PAGES.length);\n return;\n }\n if (input === 'r') {\n void refreshCurrentPage();\n return;\n }\n if (input === 'e') {\n setEffectiveMode('easy');\n setEasyState((current) => ({\n ...current,\n step: 'welcome',\n }));\n setInfoNotice('Switched to easy mode.', 'Mode changed', 'blue');\n return;\n }\n if (currentPage.id !== 'schools') {\n return;\n }\n handleSchoolsInput(input, key);\n }\n\n function handleSchoolsInput(input: string, key: KeyLike): void {\n if (input === 'i') {\n beginLineInput({\n target: 'school-query',\n title: 'School query capture',\n description: 'Type the school name on the terminal line below, then press Enter to search. This path is safer for Korean IME input.',\n accent: 'magenta',\n });\n return;\n }\n\n const recentIndex = resolveRecentSchoolShortcut(input);\n if (\n recentIndex != null &&\n session &&\n !searchState.query\n ) {\n const selectedRecentSchool = session.recentSchools[recentIndex];\n if (selectedRecentSchool) {\n void runSessionMutation(\n () => saveHumanDefaultSchoolSelection(selectedRecentSchool),\n `Selected ${selectedRecentSchool.name} as the current school.`,\n );\n }\n return;\n }\n\n if (key.upArrow) {\n setSearchState((current) => ({\n ...current,\n selectedIndex: Math.max(0, current.selectedIndex - 1),\n }));\n return;\n }\n if (key.downArrow) {\n setSearchState((current) => ({\n ...current,\n selectedIndex: clamp(\n current.selectedIndex + 1,\n 0,\n Math.max(0, current.results.length - 1),\n ),\n }));\n return;\n }\n if (key.return) {\n if (searchState.dirty || !searchState.results.length) {\n void runSchoolSearch(searchState.query);\n return;\n }\n void applySchoolSelection();\n return;\n }\n if (key.escape) {\n setSearchState({\n query: '',\n dirty: false,\n loading: false,\n results: [],\n selectedIndex: 0,\n });\n setInfoNotice('Cleared school search input.', 'Search cleared', 'yellow');\n return;\n }\n if (key.backspace || key.delete) {\n setSearchState((current) => applyQueryEdit(current, current.query.slice(0, -1)));\n return;\n }\n if (isTypingInput(input, key)) {\n setSearchState((current) => applyQueryEdit(current, `${current.query}${input}`));\n }\n }\n\n function handleSettingsInput(_input: string, key: KeyLike): boolean {\n if (!session) {\n return false;\n }\n\n if (settingsDialog) {\n if (key.escape) {\n setSettingsDialog(undefined);\n setInfoNotice('Cancelled the pending settings action.', 'Settings unchanged', 'yellow');\n return true;\n }\n if (key.return) {\n const actionId = settingsDialog.actionId;\n setSettingsDialog(undefined);\n executeSettingsAction(actionId);\n return true;\n }\n return true;\n }\n\n if (key.tab) {\n setSettingsState((current) => ({\n ...current,\n section: cycleSettingsSection(current.section),\n }));\n return true;\n }\n\n if (key.upArrow) {\n setSettingsState((current) => moveSettingsSelection(current, session, -1));\n return true;\n }\n\n if (key.downArrow) {\n setSettingsState((current) => moveSettingsSelection(current, session, 1));\n return true;\n }\n\n if (key.return) {\n if (settingsState.section === 'profiles') {\n const selectedProfile = session.configStatus.profiles[settingsState.profileIndex];\n if (selectedProfile) {\n void runSessionMutation(\n () => activateHumanProfileSelection(selectedProfile.name),\n `Activated profile ${selectedProfile.name}.`,\n );\n }\n } else if (settingsState.section === 'recent-schools') {\n const selectedSchool = session.recentSchools[settingsState.recentSchoolIndex];\n if (selectedSchool) {\n void runSessionMutation(\n () => saveHumanDefaultSchoolSelection(selectedSchool),\n `Selected ${selectedSchool.name} as the current school.`,\n );\n }\n } else {\n const action = buildSettingsActions(session, settingsState)[settingsState.actionIndex];\n if (!action || action.disabled) {\n return true;\n }\n\n if (isDestructiveSettingsAction(action.id)) {\n setSettingsDialog(buildSettingsDialog(action.id, session, settingsState));\n } else {\n executeSettingsAction(action.id);\n }\n }\n return true;\n }\n\n return false;\n }\n\n function executeSettingsAction(actionId: SettingsActionId): void {\n if (!session) {\n return;\n }\n\n switch (actionId) {\n case 'save-active-profile':\n if (session.activeProfile?.name) {\n void runSessionMutation(\n () => saveHumanSessionProfile(session, session.activeProfile!.name, { activate: true }),\n `Saved the current setup to ${session.activeProfile.name}.`,\n );\n }\n break;\n case 'save-shell-profile':\n void runSessionMutation(\n () => saveHumanSessionProfile(session, 'human-shell', { activate: true }),\n 'Saved the current setup to human-shell and activated it.',\n );\n break;\n case 'clear-active-profile':\n void runSessionMutation(\n () => clearHumanActiveProfileSelection(),\n 'Cleared the active profile.',\n );\n break;\n case 'clear-default-school':\n void runSessionMutation(\n () => clearHumanDefaultSchoolSelection(),\n 'Cleared the default school.',\n );\n break;\n case 'remove-selected-profile': {\n const selectedProfile = session.configStatus.profiles[settingsState.profileIndex];\n if (selectedProfile) {\n void runSessionMutation(\n () => removeHumanProfileSelection(selectedProfile.name),\n `Removed profile ${selectedProfile.name}.`,\n );\n }\n break;\n }\n case 'remove-selected-recent-school': {\n const selectedRecentSchool = session.recentSchools[settingsState.recentSchoolIndex];\n if (selectedRecentSchool) {\n void runSessionMutation(\n () => removeHumanRecentSchoolSelection(selectedRecentSchool),\n `Removed ${selectedRecentSchool.name} from recent schools.`,\n );\n }\n break;\n }\n case 'refresh-session':\n void refreshSession('Refreshed shell session.');\n break;\n }\n }\n\n function handleEasyInput(input: string, key: KeyLike): void {\n if (inputLocked) {\n return;\n }\n if (key.escape) {\n if (easyState.step === 'welcome') {\n setEffectiveMode('human');\n setInfoNotice('Returned to human mode.', 'Mode changed', 'blue');\n return;\n }\n setEasyState((current) => ({\n ...current,\n step: current.step === 'teacher' ? 'class' : 'search',\n }));\n return;\n }\n if (easyState.step === 'welcome') {\n if (key.return || isTypingInput(input, key)) {\n setEasyState((current) => ({\n ...current,\n step: 'search',\n }));\n }\n return;\n }\n if (easyState.step === 'search') {\n if (input === 'i') {\n beginLineInput({\n target: 'easy-school-query',\n title: 'School query capture',\n description: 'Type the school name on the terminal line below, then press Enter to search. This path is safer for Korean IME input.',\n accent: 'magenta',\n });\n return;\n }\n if (key.upArrow) {\n setEasyState((current) => ({\n ...current,\n selectedIndex: Math.max(0, current.selectedIndex - 1),\n }));\n return;\n }\n if (key.downArrow) {\n setEasyState((current) => ({\n ...current,\n selectedIndex: clamp(\n current.selectedIndex + 1,\n 0,\n Math.max(0, current.results.length - 1),\n ),\n }));\n return;\n }\n if (key.return) {\n if (easyState.dirty || !easyState.results.length) {\n void runEasySearch(easyState.query);\n return;\n }\n setEasyState((current) => ({\n ...current,\n step: 'class',\n error: undefined,\n }));\n return;\n }\n if (key.backspace || key.delete) {\n setEasyState((current) => applyQueryEdit(current, current.query.slice(0, -1)));\n return;\n }\n if (isTypingInput(input, key)) {\n setEasyState((current) => applyQueryEdit(current, `${current.query}${input}`));\n }\n return;\n }\n if (easyState.step === 'class') {\n if (key.upArrow) {\n setEasyState((current) => ({\n ...current,\n grade: clamp(current.grade + 1, 1, 6),\n }));\n return;\n }\n if (key.downArrow) {\n setEasyState((current) => ({\n ...current,\n grade: clamp(current.grade - 1, 1, 6),\n }));\n return;\n }\n if (key.rightArrow) {\n setEasyState((current) => ({\n ...current,\n classNo: clamp(current.classNo + 1, 1, 30),\n }));\n return;\n }\n if (key.leftArrow) {\n setEasyState((current) => ({\n ...current,\n classNo: clamp(current.classNo - 1, 1, 30),\n }));\n return;\n }\n if (key.return) {\n setEasyState((current) => ({\n ...current,\n step: 'teacher',\n }));\n }\n return;\n }\n if (easyState.step === 'teacher') {\n if (input === 'i') {\n beginLineInput({\n target: 'easy-teacher-name',\n title: 'Teacher name capture',\n description: 'Type the teacher name on the terminal line below, then press Enter to save it. This path is safer for Korean IME input.',\n accent: 'magenta',\n });\n return;\n }\n if (key.return) {\n void finishEasyMode();\n return;\n }\n if (key.backspace || key.delete) {\n setEasyState((current) => ({\n ...current,\n teacherName: current.teacherName.slice(0, -1),\n }));\n return;\n }\n if (isTypingInput(input, key)) {\n setEasyState((current) => ({\n ...current,\n teacherName: `${current.teacherName}${input}`,\n }));\n }\n }\n }\n\n function beginLineInput(next: LineInputState): void {\n setLineInput(next);\n setNotice({\n title: next.title,\n message: next.description,\n accent: next.accent,\n });\n }\n\n function applyLineInputValue(target: LineInputTarget, value: string): void {\n setLineInput(undefined);\n\n switch (target) {\n case 'school-query':\n setSearchState((current) => applyQueryEdit(current, value));\n void runSchoolSearch(value);\n return;\n case 'easy-school-query':\n setEasyState((current) => applyQueryEdit(current, value));\n void runEasySearch(value);\n return;\n case 'easy-teacher-name':\n setEasyState((current) => ({\n ...current,\n teacherName: value,\n error: undefined,\n }));\n setInfoNotice('Updated the teacher shortcut field.', 'Teacher field updated', 'green');\n return;\n }\n }\n\n if (showSplash) {\n return <SplashScreen mode={mode} />;\n }\n\n if (effectiveMode === 'easy') {\n return (\n <Box flexDirection=\"column\">\n <NoticeBanner notice={notice} />\n <FocusBanner focus={focusState} />\n {lineInput ? (\n <Callout title={lineInput.title} accent={lineInput.accent}>\n {lineInput.description}\n </Callout>\n ) : null}\n <EasyModeView\n easyState={easyState}\n session={session}\n lineInputTarget={\n lineInput?.target === 'easy-school-query' || lineInput?.target === 'easy-teacher-name'\n ? lineInput.target\n : undefined\n }\n />\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header summary={headerSummary} subtitle={KAMPUS_TAGLINE} />\n <NoticeBanner notice={notice} />\n {sessionError ? (\n <Panel title=\"Session Error\" accent=\"red\">\n <Text color=\"red\">{sessionError}</Text>\n </Panel>\n ) : null}\n <Navigation pageIndex={pageIndex} />\n <FocusBanner focus={focusState} />\n {lineInput ? (\n <Callout title={lineInput.title} accent={lineInput.accent}>\n {lineInput.description}\n </Callout>\n ) : null}\n <Panel\n title={currentPage.label}\n subtitle={currentPage.description}\n accent={pageTone(currentPage.id)}\n >\n {loadingSession || !session ? (\n <Text color=\"yellow\">Loading Kampus session...</Text>\n ) : (\n <HumanShellPage\n page={currentPage.id}\n session={session}\n searchState={searchState}\n pageStates={pageStates}\n settingsState={settingsState}\n settingsDialog={settingsDialog}\n lineInputActive={lineInput?.target === 'school-query'}\n />\n )}\n </Panel>\n <Footer page={currentPage.id} mode=\"human\" />\n </Box>\n );\n}\n\nfunction HumanShellPage({\n page,\n session,\n searchState,\n pageStates,\n settingsState,\n settingsDialog,\n lineInputActive,\n}: {\n page: (typeof HUMAN_PAGES)[number]['id'];\n session: HumanSessionContext;\n searchState: SearchState;\n pageStates: AsyncPageStateMap;\n settingsState: SettingsState;\n settingsDialog?: SettingsDialog;\n lineInputActive?: boolean;\n}) {\n switch (page) {\n case 'home':\n return pageStates.home.loading ? (\n <Text color=\"yellow\">Refreshing home...</Text>\n ) : pageStates.home.error ? (\n <Text color=\"red\">{pageStates.home.error}</Text>\n ) : (\n <HomePage session={session} data={pageStates.home.data} />\n );\n case 'schools':\n return <SchoolsPage session={session} searchState={searchState} lineInputActive={lineInputActive} />;\n case 'timetable':\n return pageStates.timetable.loading ? (\n <Text color=\"yellow\">Refreshing timetable...</Text>\n ) : pageStates.timetable.error ? (\n <Text color=\"red\">{pageStates.timetable.error}</Text>\n ) : (\n <TimetablePage data={pageStates.timetable.data} />\n );\n case 'meals':\n return pageStates.meals.loading ? (\n <Text color=\"yellow\">Refreshing meals...</Text>\n ) : pageStates.meals.error ? (\n <Text color=\"red\">{pageStates.meals.error}</Text>\n ) : (\n <MealsPage data={pageStates.meals.data} />\n );\n case 'teacher':\n return pageStates.teacher.loading ? (\n <Text color=\"yellow\">Refreshing teacher...</Text>\n ) : pageStates.teacher.error ? (\n <Text color=\"red\">{pageStates.teacher.error}</Text>\n ) : (\n <TeacherPage session={session} data={pageStates.teacher.data} />\n );\n case 'diagnostics':\n return pageStates.diagnostics.loading ? (\n <Text color=\"yellow\">Refreshing diagnostics...</Text>\n ) : pageStates.diagnostics.error ? (\n <Text color=\"red\">{pageStates.diagnostics.error}</Text>\n ) : (\n <DiagnosticsPage data={pageStates.diagnostics.data} />\n );\n case 'settings':\n return <SettingsPage session={session} settingsState={settingsState} dialog={settingsDialog} />;\n case 'help':\n return <HelpPage session={session} />;\n default:\n return <Text color=\"gray\">No page renderer.</Text>;\n }\n}\n\nasync function loadAsyncPage<K extends AsyncDataPageId>(\n page: K,\n session: HumanSessionContext,\n): Promise<AsyncPageDataMap[K]> {\n switch (page) {\n case 'home':\n return (await loadHumanHomeData(session)) as AsyncPageDataMap[K];\n case 'timetable':\n return (await loadHumanWeekTimetable(session)) as AsyncPageDataMap[K];\n case 'meals':\n return (await loadHumanWeeklyMeals(session)) as AsyncPageDataMap[K];\n case 'teacher':\n return (await loadHumanTeacherData(session)) as AsyncPageDataMap[K];\n case 'diagnostics':\n return (await loadHumanDiagnostics(session)) as AsyncPageDataMap[K];\n }\n}\n\nexport function alignSettingsState(\n current: SettingsState,\n session: HumanSessionContext,\n): SettingsState {\n const activeProfileIndex = Math.max(\n 0,\n session.configStatus.profiles.findIndex((profile) => profile.name === session.activeProfile?.name),\n );\n const currentSchoolIndex = Math.max(\n 0,\n session.recentSchools.findIndex(\n (school) =>\n school.name === session.selectedSchool?.name &&\n (school.region ?? '') === (session.selectedSchool?.region ?? ''),\n ),\n );\n\n return {\n section:\n current.section === 'recent-schools'\n ? session.recentSchools.length\n ? 'recent-schools'\n : 'profiles'\n : current.section === 'actions'\n ? 'actions'\n : 'profiles',\n profileIndex:\n session.configStatus.profiles.length === 0 ? 0 : activeProfileIndex,\n recentSchoolIndex:\n session.recentSchools.length === 0 ? 0 : currentSchoolIndex,\n actionIndex: clamp(current.actionIndex, 0, Math.max(0, buildSettingsActions(session, current).length - 1)),\n };\n}\n\ntype QueryEditState = {\n query: string;\n dirty: boolean;\n error?: string;\n results: SearchState['results'];\n selectedIndex: number;\n};\n\nexport function applyQueryEdit<T extends QueryEditState>(state: T, query: string): T {\n return {\n ...state,\n query,\n dirty: true,\n error: undefined,\n results: [],\n selectedIndex: 0,\n };\n}\n\nfunction deriveHumanFocusState(\n page: (typeof HUMAN_PAGES)[number]['id'],\n settingsState: SettingsState,\n settingsDialog?: SettingsDialog,\n lineInput?: LineInputState,\n): { title: string; description: string; accent: AccentTone } {\n if (lineInput) {\n return {\n title: lineInput.title,\n description: lineInput.description,\n accent: lineInput.accent,\n };\n }\n\n if (page === 'schools') {\n return {\n title: 'School query',\n description: 'The school query field owns text input. Press I for IME-safe line capture, Enter to search, and Enter again to apply the highlighted result.',\n accent: 'magenta',\n };\n }\n\n if (page === 'settings') {\n if (settingsDialog) {\n return {\n title: 'Settings confirmation',\n description: 'The confirmation dialog owns input. Press Enter to confirm or Esc to cancel.',\n accent: 'red',\n };\n }\n\n const sectionTitle =\n settingsState.section === 'profiles'\n ? 'Profiles pane'\n : settingsState.section === 'recent-schools'\n ? 'Recent schools pane'\n : 'Actions pane';\n return {\n title: sectionTitle,\n description: 'Use Tab to switch panes, Up and Down to move the selection, and Enter to apply the focused item.',\n accent: 'yellow',\n };\n }\n\n return {\n title: 'Page navigation',\n description: 'Use Left and Right arrows or page shortcuts to move through the command deck. Read-only pages do not capture free text input.',\n accent: pageTone(page),\n };\n}\n\nfunction deriveEasyFocusState(\n easyState: EasyState,\n lineInput?: LineInputState,\n): { title: string; description: string; accent: AccentTone } {\n if (lineInput) {\n return {\n title: lineInput.title,\n description: lineInput.description,\n accent: lineInput.accent,\n };\n }\n\n switch (easyState.step) {\n case 'welcome':\n return {\n title: 'Welcome prompt',\n description: 'Press Enter to begin guided setup or Esc to return to human mode.',\n accent: 'blue',\n };\n case 'search':\n return {\n title: 'School query',\n description: 'The school query field owns input. Press I for IME-safe line capture, Enter to search, and Enter again to accept the highlighted school.',\n accent: 'magenta',\n };\n case 'class':\n return {\n title: 'Grade and class selector',\n description: 'Use Up and Down to change grade, Left and Right to change class, then press Enter to continue.',\n accent: 'blue',\n };\n case 'teacher':\n return {\n title: 'Teacher name',\n description: 'Type a teacher name or press I for IME-safe line capture, then press Enter to save the easy-mode profile.',\n accent: 'magenta',\n };\n case 'saving':\n return {\n title: 'Saving profile',\n description: 'Easy mode is writing the selected school and class setup into the active profile.',\n accent: 'green',\n };\n }\n}\n\n", "import chalk from 'chalk';\n\nconst LOGO_LINES = [\n ' _ __ ',\n '| |/ /__ _ _ __ ___ _ __ _ _ ___',\n \"| ' // _` | '_ ` _ \\\\| '_ \\\\| | | / __|\",\n '| . \\\\ (_| | | | | | | |_) | |_| \\\\__ \\\\',\n '|_|\\\\_\\\\__,_|_| |_| |_| .__/ \\\\__,_|___/',\n ' |_| ',\n];\n\nconst LINE_GRADIENTS: Array<[string, string]> = [\n ['#2563eb', '#0ea5e9'],\n ['#2563eb', '#06b6d4'],\n ['#0ea5e9', '#22c55e'],\n ['#06b6d4', '#eab308'],\n ['#22c55e', '#f97316'],\n ['#94a3b8', '#64748b'],\n];\n\nexport function getGradientLogoLines(): string[] {\n return LOGO_LINES.map((line, index) => {\n const [startHex, endHex] = LINE_GRADIENTS[index] ?? ['#94a3b8', '#64748b'];\n return applyGradient(line, startHex, endHex);\n });\n}\n\nexport function getCompactWordmarkLines(): string[] {\n return [\n applyGradient('KAMPUS // HUMAN OPS SHELL', '#38bdf8', '#22c55e'),\n chalk.hex('#94a3b8')('Korean school data, schedules, meals, and diagnostics'),\n ];\n}\n\nexport const KAMPUS_TAGLINE = 'Human-first shell for Korean school data';\n\nfunction applyGradient(line: string, startHex: string, endHex: string): string {\n const start = hexToRgb(startHex);\n const end = hexToRgb(endHex);\n const visibleChars = [...line].filter((char) => char !== ' ').length || 1;\n let visibleIndex = 0;\n\n return [...line]\n .map((char) => {\n if (char === ' ') {\n return char;\n }\n\n const ratio = visibleChars === 1 ? 0 : visibleIndex / (visibleChars - 1);\n visibleIndex += 1;\n const red = Math.round(start.red + (end.red - start.red) * ratio);\n const green = Math.round(start.green + (end.green - start.green) * ratio);\n const blue = Math.round(start.blue + (end.blue - start.blue) * ratio);\n return chalk.rgb(red, green, blue)(char);\n })\n .join('');\n}\n\nfunction hexToRgb(hex: string): { red: number; green: number; blue: number } {\n const normalized = hex.replace('#', '');\n return {\n red: Number.parseInt(normalized.slice(0, 2), 16),\n green: Number.parseInt(normalized.slice(2, 4), 16),\n blue: Number.parseInt(normalized.slice(4, 6), 16),\n };\n}\n", "import { Box, Text } from 'ink';\nimport type { DataStatus, ProviderWarning } from '@kampus/core';\nimport type { ReactNode } from 'react';\nimport { getCompactWordmarkLines } from './logo.js';\nimport { HUMAN_PAGES, type HumanPageId, type InteractiveMode } from './types.js';\nimport {\n PAGE_SHORTCUTS,\n accentColor,\n accentGlyph,\n accessTone,\n pageTone,\n type AccentTone,\n} from './theme.js';\n\nexport function Header({\n summary,\n subtitle,\n}: {\n summary: { school: string; profile: string; access: string };\n subtitle: string;\n}) {\n return (\n <Panel title=\"Kampus Ops Deck\" subtitle={subtitle} accent=\"blue\">\n <Box flexDirection=\"column\">\n {getCompactWordmarkLines().map((line, index) => (\n <Text key={index}>{line}</Text>\n ))}\n <Text color=\"gray\">\n Enterprise-style terminal workspace for school operations, daily schedules, meals, and provider diagnostics.\n </Text>\n <Box flexWrap=\"wrap\" marginTop={1}>\n <MetricCard\n label=\"School\"\n value={summary.school}\n note=\"Current default school context\"\n accent=\"cyan\"\n width={34}\n />\n <MetricCard\n label=\"Profile\"\n value={summary.profile}\n note=\"Active saved shell profile\"\n accent=\"magenta\"\n width={32}\n />\n <MetricCard\n label=\"Access\"\n value={summary.access}\n note=\"Official provider mode\"\n accent={accessTone(summary.access)}\n width={24}\n />\n </Box>\n <Text color=\"gray\">\n Use page shortcuts to jump instantly. Raw commands and MCP behavior remain unchanged.\n </Text>\n </Box>\n </Panel>\n );\n}\n\nexport function NoticeBanner({\n notice,\n}: {\n notice?: { title: string; message: string; accent: AccentTone } | null;\n}) {\n if (!notice) {\n return null;\n }\n\n return (\n <Panel title={notice.title} subtitle=\"Latest shell event\" accent={notice.accent}>\n <Text>{notice.message}</Text>\n </Panel>\n );\n}\n\nexport function FocusBanner({\n focus,\n}: {\n focus: { title: string; description: string; accent: AccentTone };\n}) {\n return (\n <Panel title={`Input focus: ${focus.title}`} subtitle=\"Current keyboard target\" accent={focus.accent}>\n <Text>{focus.description}</Text>\n </Panel>\n );\n}\n\nexport function Navigation({ pageIndex }: { pageIndex: number }) {\n return (\n <Panel title=\"Navigation\" subtitle=\"Direct page access\" accent=\"cyan\">\n <Box flexWrap=\"wrap\">\n {HUMAN_PAGES.map((page, index) => {\n const active = index === pageIndex;\n const tone = pageTone(page.id);\n return (\n <Box key={page.id} marginRight={1} marginBottom={1}>\n <Text\n color={active ? 'black' : accentColor(tone)}\n backgroundColor={active ? accentColor(tone) : undefined}\n >\n {active\n ? ` ${PAGE_SHORTCUTS[page.id]} ${page.label} `\n : `[${PAGE_SHORTCUTS[page.id]} ${page.label}]`}\n </Text>\n </Box>\n );\n })}\n </Box>\n </Panel>\n );\n}\n\nexport function Panel({\n title,\n subtitle,\n accent,\n children,\n}: {\n title: string;\n subtitle?: string;\n accent: AccentTone;\n children: ReactNode;\n}) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={accentColor(accent)}\n paddingX={1}\n paddingY={0}\n marginBottom={1}\n >\n <Text color={accentColor(accent)}>\n {accentGlyph(accent)} {title.toUpperCase()}\n {subtitle ? <Text color=\"gray\"> {subtitle}</Text> : null}\n </Text>\n <Box marginTop={0} flexDirection=\"column\">\n {children}\n </Box>\n </Box>\n );\n}\n\nexport function MetricCard({\n label,\n value,\n note,\n accent,\n width,\n}: {\n label: string;\n value: string;\n note?: string;\n accent: AccentTone;\n width?: number;\n}) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={accentColor(accent)}\n paddingX={1}\n marginRight={1}\n marginBottom={1}\n width={width}\n >\n <Text color={accentColor(accent)}>{label.toUpperCase()}</Text>\n <Text>{value}</Text>\n {note ? <Text color=\"gray\">{note}</Text> : null}\n </Box>\n );\n}\n\nexport function Callout({\n title,\n accent,\n children,\n}: {\n title: string;\n accent: AccentTone;\n children: ReactNode;\n}) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={accentColor(accent)}\n paddingX={1}\n marginTop={1}\n >\n <Text color={accentColor(accent)}>{title}</Text>\n {typeof children === 'string' ? <Text>{children}</Text> : children}\n </Box>\n );\n}\n\nexport function InfoLine({\n label,\n value,\n tone = 'cyan',\n}: {\n label: string;\n value: string;\n tone?: AccentTone;\n}) {\n return (\n <Text>\n <Text color={accentColor(tone)}>{label.padEnd(14, ' ')}</Text>\n <Text color=\"gray\"> : </Text>\n {value}\n </Text>\n );\n}\n\nexport function ListRow({\n active,\n accent,\n primary,\n secondary,\n meta,\n leading,\n}: {\n active?: boolean;\n accent: AccentTone;\n primary: string;\n secondary?: string;\n meta?: string;\n leading?: string;\n}) {\n return (\n <Text\n color={active ? 'black' : undefined}\n backgroundColor={active ? accentColor(accent) : undefined}\n >\n {active ? '>' : ' '} {leading ? `${leading} ` : ''}{primary}\n {secondary ? <Text color={active ? 'black' : 'gray'}>{` ${secondary}`}</Text> : null}\n {meta ? <Text color={active ? 'black' : accentColor(accent)}>{` ${meta}`}</Text> : null}\n </Text>\n );\n}\n\nexport function EmptyState({\n title,\n message,\n}: {\n title: string;\n message: string;\n}) {\n return (\n <Callout title={title} accent=\"yellow\">\n <Text color=\"gray\">{message}</Text>\n </Callout>\n );\n}\n\nexport function StatusBadge({\n text,\n tone,\n}: {\n text: string;\n tone: AccentTone | 'gray';\n}) {\n const background = tone === 'gray' ? 'gray' : accentColor(tone);\n const foreground = tone === 'gray' ? 'white' : 'black';\n return (\n <Text color={foreground} backgroundColor={background}>\n {` ${text} `}\n </Text>\n );\n}\n\nexport function DataStatusSummary({\n label,\n status,\n warnings,\n}: {\n label: string;\n status?: DataStatus;\n warnings?: ProviderWarning[];\n}) {\n const mergedWarnings = mergeWarnings(status?.warnings, warnings);\n if (!status && !mergedWarnings.length) {\n return null;\n }\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n <Text color=\"cyan\">{label}</Text>\n <Text color=\"gray\"> </Text>\n {status ? (\n <>\n <StatusBadge text={status.accessMode} tone={accessTone(status.accessMode)} />\n <Text> </Text>\n <StatusBadge\n text={status.complete ? 'complete' : 'partial'}\n tone={status.complete ? 'green' : 'yellow'}\n />\n {status.sourceProviders.length ? (\n <Text color=\"gray\"> sources: {status.sourceProviders.join(', ')}</Text>\n ) : null}\n </>\n ) : (\n <StatusBadge text=\"no status metadata\" tone=\"gray\" />\n )}\n </Text>\n <WarningList warnings={mergedWarnings} />\n </Box>\n );\n}\n\nexport function IssueList({\n issues,\n title = 'Issue ledger',\n}: {\n issues?: Array<{ section: string; message: string }>;\n title?: string;\n}) {\n if (!issues?.length) {\n return null;\n }\n\n return (\n <Callout title={title} accent=\"yellow\">\n <Box flexDirection=\"column\">\n {issues.map((issue) => (\n <Text key={`${issue.section}:${issue.message}`} color=\"yellow\">\n - {issue.section}: {issue.message}\n </Text>\n ))}\n </Box>\n </Callout>\n );\n}\n\nexport function WarningList({ warnings }: { warnings?: ProviderWarning[] }) {\n if (!warnings?.length) {\n return null;\n }\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {warnings.map((warning) => (\n <Text key={`${warning.provider}:${warning.code}:${warning.message}`} color=\"yellow\">\n - {warning.provider}/{warning.code}: {warning.message}\n </Text>\n ))}\n </Box>\n );\n}\n\nexport function StepTrack({\n steps,\n current,\n}: {\n steps: string[];\n current: string;\n}) {\n const currentIndex = Math.max(0, steps.indexOf(current));\n return (\n <Box flexWrap=\"wrap\" marginBottom={1}>\n {steps.map((step, index) => {\n const state =\n index < currentIndex ? 'done' : index === currentIndex ? 'current' : 'pending';\n const tone = state === 'done' ? 'green' : state === 'current' ? 'cyan' : 'gray';\n return (\n <Box key={step} marginRight={1} marginBottom={1}>\n <StatusBadge\n text={`${index + 1} ${step}`}\n tone={tone === 'gray' ? 'gray' : tone}\n />\n </Box>\n );\n })}\n </Box>\n );\n}\n\nexport function Footer({ page, mode }: { page: HumanPageId; mode: InteractiveMode }) {\n if (mode === 'easy') {\n return (\n <KeyHintBar\n hints={[\n ['I', 'ime-safe edit'],\n ['Enter', 'confirm'],\n ['Esc', 'back'],\n ['Ctrl+C', 'exit'],\n ]}\n />\n );\n }\n\n if (page === 'schools') {\n return (\n <KeyHintBar\n hints={[\n ['Type', 'search'],\n ['I', 'ime-safe edit'],\n ['Enter', 'query/select'],\n ['Up/Down', 'move'],\n ['1-9', 'recent'],\n ['H/S/T/M/Y/G/P/?', 'jump'],\n ['Q', 'quit'],\n ]}\n />\n );\n }\n\n if (page === 'settings') {\n return (\n <KeyHintBar\n hints={[\n ['Up/Down', 'move'],\n ['Tab', 'switch pane'],\n ['Enter', 'apply'],\n ['Esc', 'cancel confirm'],\n ['H/S/T/M/Y/G/P/?', 'jump'],\n ]}\n />\n );\n }\n\n return (\n <KeyHintBar\n hints={[\n ['Left/Right', 'pages'],\n ['H/S/T/M/Y/G/P/?', 'jump'],\n ['R', 'refresh'],\n ['E', 'easy'],\n ['Q', 'quit'],\n ['Ctrl+C', 'exit'],\n ]}\n />\n );\n}\n\nfunction KeyHintBar({\n hints,\n}: {\n hints: Array<[string, string]>;\n}) {\n return (\n <Box flexWrap=\"wrap\">\n {hints.map(([key, label]) => (\n <Box key={`${key}:${label}`} marginRight={1}>\n <Text color=\"black\" backgroundColor=\"white\">\n {` ${key} `}\n </Text>\n <Text color=\"gray\"> {label}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction mergeWarnings(\n fromStatus?: ProviderWarning[],\n fromValue?: ProviderWarning[],\n): ProviderWarning[] {\n const merged = [...(fromStatus ?? []), ...(fromValue ?? [])];\n return merged.filter((warning, index, values) => {\n return (\n values.findIndex(\n (candidate) =>\n candidate.provider === warning.provider &&\n candidate.code === warning.code &&\n candidate.message === warning.message,\n ) === index\n );\n });\n}\n", "import type {\n HumanDiagnosticsData,\n HumanHomeData,\n HumanMealsData,\n HumanSessionContext,\n HumanTeacherData,\n HumanTimetableData,\n} from '../usecases/human.js';\n\nexport type {\n HumanDiagnosticsData,\n HumanHomeData,\n HumanMealsData,\n HumanSessionContext,\n HumanTeacherData,\n HumanTimetableData,\n InteractiveMode,\n} from '../usecases/human.js';\n\nexport type HumanPageId =\n | 'home'\n | 'schools'\n | 'timetable'\n | 'meals'\n | 'teacher'\n | 'diagnostics'\n | 'settings'\n | 'help';\n\nexport type AsyncDataPageId = 'home' | 'timetable' | 'meals' | 'teacher' | 'diagnostics';\n\nexport interface HumanPage {\n id: HumanPageId;\n label: string;\n description: string;\n}\n\nexport interface SearchState {\n query: string;\n dirty: boolean;\n loading: boolean;\n error?: string;\n results: HumanSessionContext['recentSchools'];\n selectedIndex: number;\n}\n\nexport interface EasyState {\n step: 'welcome' | 'search' | 'class' | 'teacher' | 'saving';\n query: string;\n dirty: boolean;\n loading: boolean;\n error?: string;\n results: HumanSessionContext['recentSchools'];\n selectedIndex: number;\n grade: number;\n classNo: number;\n teacherName: string;\n}\n\nexport interface SettingsState {\n section: SettingsSection;\n profileIndex: number;\n recentSchoolIndex: number;\n actionIndex: number;\n}\n\nexport type SettingsSection = 'profiles' | 'recent-schools' | 'actions';\n\nexport type SettingsActionId =\n | 'save-active-profile'\n | 'save-shell-profile'\n | 'clear-active-profile'\n | 'clear-default-school'\n | 'remove-selected-profile'\n | 'remove-selected-recent-school'\n | 'refresh-session';\n\nexport interface SettingsActionItem {\n id: SettingsActionId;\n label: string;\n description: string;\n disabled?: boolean;\n}\n\nexport interface SettingsDialog {\n actionId:\n | 'clear-active-profile'\n | 'clear-default-school'\n | 'remove-selected-profile'\n | 'remove-selected-recent-school';\n title: string;\n description: string;\n confirmLabel: string;\n}\n\nexport interface KeyLike {\n ctrl?: boolean;\n meta?: boolean;\n return?: boolean;\n escape?: boolean;\n backspace?: boolean;\n delete?: boolean;\n leftArrow?: boolean;\n rightArrow?: boolean;\n upArrow?: boolean;\n downArrow?: boolean;\n tab?: boolean;\n}\n\nexport interface AsyncPageDataMap {\n home: HumanHomeData;\n timetable: HumanTimetableData;\n meals: HumanMealsData;\n teacher: HumanTeacherData;\n diagnostics: HumanDiagnosticsData;\n}\n\nexport type AsyncPageState<K extends AsyncDataPageId> = {\n loading: boolean;\n error?: string;\n data?: AsyncPageDataMap[K];\n};\n\nexport type AsyncPageStateMap = {\n [K in AsyncDataPageId]: AsyncPageState<K>;\n};\n\nexport const HUMAN_PAGES: HumanPage[] = [\n { id: 'home', label: 'Home', description: 'See the current school snapshot at a glance.' },\n { id: 'schools', label: 'Schools', description: 'Search schools and choose the active default.' },\n { id: 'timetable', label: 'Timetable', description: 'Browse the weekly student timetable.' },\n { id: 'meals', label: 'Meals', description: 'Check meal summaries for the current week.' },\n { id: 'teacher', label: 'Teacher', description: 'Open teacher info and timetable summaries.' },\n { id: 'diagnostics', label: 'Diagnostics', description: 'Inspect key state and provider access modes.' },\n { id: 'settings', label: 'Settings', description: 'Review profiles, key storage, and cache policy.' },\n { id: 'help', label: 'Help', description: 'Show shortcuts and raw-command reminders.' },\n];\n\nexport function createInitialAsyncPageStates(): AsyncPageStateMap {\n return {\n home: { loading: false },\n timetable: { loading: false },\n meals: { loading: false },\n teacher: { loading: false },\n diagnostics: { loading: false },\n };\n}\n\nexport function createInitialSettingsState(): SettingsState {\n return {\n section: 'profiles',\n profileIndex: 0,\n recentSchoolIndex: 0,\n actionIndex: 0,\n };\n}\n\nexport function isAsyncDataPage(page: HumanPageId): page is AsyncDataPageId {\n return (\n page === 'home' ||\n page === 'timetable' ||\n page === 'meals' ||\n page === 'teacher' ||\n page === 'diagnostics'\n );\n}\n", "import type { HumanPageId } from './types.js';\n\nexport type AccentTone = 'cyan' | 'green' | 'yellow' | 'magenta' | 'blue' | 'red';\n\nexport const PAGE_SHORTCUTS: Record<HumanPageId, string> = {\n home: 'H',\n schools: 'S',\n timetable: 'T',\n meals: 'M',\n teacher: 'Y',\n diagnostics: 'G',\n settings: 'P',\n help: '?',\n};\n\nexport function accentColor(accent: AccentTone): string {\n switch (accent) {\n case 'blue':\n return 'blue';\n case 'green':\n return 'green';\n case 'yellow':\n return 'yellow';\n case 'magenta':\n return 'magenta';\n case 'red':\n return 'red';\n default:\n return 'cyan';\n }\n}\n\nexport function accentGlyph(accent: AccentTone): string {\n switch (accent) {\n case 'blue':\n return '::';\n case 'green':\n return '++';\n case 'yellow':\n return '!!';\n case 'magenta':\n return '##';\n case 'red':\n return 'xx';\n default:\n return '>>';\n }\n}\n\nexport function pageTone(page: HumanPageId): AccentTone {\n switch (page) {\n case 'home':\n return 'blue';\n case 'schools':\n return 'magenta';\n case 'timetable':\n return 'cyan';\n case 'meals':\n return 'green';\n case 'teacher':\n return 'magenta';\n case 'diagnostics':\n return 'yellow';\n case 'settings':\n return 'blue';\n case 'help':\n return 'cyan';\n }\n}\n\nexport function accessTone(accessMode: string): AccentTone {\n if (accessMode === 'official-full') {\n return 'green';\n }\n if (accessMode === 'official-limited') {\n return 'yellow';\n }\n return 'magenta';\n}\n", "import { Box, Newline, Text } from 'ink';\nimport {\n describeSecretStorage,\n KAMPUS_DEVELOPER_INFO,\n KAMPUS_PROJECT_INFO,\n type TeacherTimetable,\n type WeekTimetable,\n type WeeklyMeals,\n} from '@kampus/core';\nimport { KAMPUS_TAGLINE, getGradientLogoLines } from './logo.js';\nimport {\n Callout,\n DataStatusSummary,\n EmptyState,\n Footer,\n Header,\n InfoLine,\n IssueList,\n ListRow,\n MetricCard,\n Panel,\n StepTrack,\n} from './components.js';\nimport { buildSettingsActions } from './settings.js';\nimport type {\n EasyState,\n HumanDiagnosticsData,\n HumanMealsData,\n HumanSessionContext,\n HumanTeacherData,\n HumanTimetableData,\n InteractiveMode,\n SearchState,\n SettingsDialog,\n SettingsState,\n} from './types.js';\nimport type { HumanHomeData } from '../usecases/human.js';\n\nexport function SplashScreen({ mode }: { mode: InteractiveMode }) {\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Panel\n title={mode === 'easy' ? 'Easy Mode Boot' : 'Human Shell Boot'}\n subtitle=\"Interactive terminal workspace\"\n accent=\"blue\"\n >\n <Box flexDirection=\"column\">\n {getGradientLogoLines().map((line, index) => (\n <Text key={index}>{line}</Text>\n ))}\n <Newline />\n <Text color=\"cyan\">{KAMPUS_TAGLINE}</Text>\n <Text color=\"gray\">\n {mode === 'easy'\n ? 'Preparing guided setup for school, class, and teacher defaults.'\n : 'Preparing the operations deck for interactive school data work.'}\n </Text>\n <Callout title=\"Launch\" accent=\"yellow\">\n Press any key to continue immediately.\n </Callout>\n </Box>\n </Panel>\n </Box>\n );\n}\n\nexport function HomePage({\n session,\n data,\n}: {\n session: HumanSessionContext;\n data?: HumanHomeData;\n}) {\n const notes = [...session.notes, ...(data?.notes ?? [])];\n const nextClassValue = data?.nextClass\n ? `P${data.nextClass.period.period} ${data.nextClass.period.subject}`\n : 'No upcoming class';\n\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Mission Control\" subtitle=\"Live session summary\" accent=\"blue\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"School\"\n value={renderSchoolLabel(session.selectedSchool?.name, session.selectedSchool?.region)}\n note=\"Default school context\"\n accent=\"cyan\"\n width={34}\n />\n <MetricCard\n label=\"Class\"\n value={session.grade && session.classNo ? `${session.grade}-${session.classNo}` : 'Not set'}\n note=\"Student view target\"\n accent=\"blue\"\n width={20}\n />\n <MetricCard\n label=\"Teacher\"\n value={session.teacherName ?? 'Not set'}\n note=\"Teacher page target\"\n accent=\"magenta\"\n width={26}\n />\n <MetricCard\n label=\"Next class\"\n value={nextClassValue}\n note={\n data?.nextClass?.minutesUntil != null\n ? `Starts in ${data.nextClass.minutesUntil} min`\n : 'Live class countdown'\n }\n accent=\"green\"\n width={30}\n />\n </Box>\n {data?.classTimes?.length ? (\n <Callout title=\"Class-time rail\" accent=\"cyan\">\n <Text color=\"gray\">\n {data.classTimes\n .slice(0, 4)\n .map((slot) => `P${slot.period} ${slot.startTime}-${slot.endTime}`)\n .join(' ')}\n </Text>\n </Callout>\n ) : null}\n </Panel>\n\n <Panel title=\"Today timetable\" subtitle=\"Student view\" accent=\"cyan\">\n <DataStatusSummary\n label=\"Status\"\n status={data?.todayTimetable?.dataStatus}\n warnings={data?.todayTimetable?.warnings}\n />\n <Box flexDirection=\"column\" marginTop={1}>\n {data?.todayTimetable?.periods.length ? (\n data.todayTimetable.periods.slice(0, 8).map((period) => (\n <ListRow\n key={period.period}\n accent=\"cyan\"\n leading={`P${period.period}`}\n primary={period.subject}\n secondary={period.teacher ? `[${period.teacher}]` : undefined}\n />\n ))\n ) : (\n <EmptyState\n title=\"Timetable idle\"\n message=\"No student timetable is loaded for today yet.\"\n />\n )}\n </Box>\n </Panel>\n\n <Panel title=\"Today meals\" subtitle=\"Meal board\" accent=\"green\">\n <DataStatusSummary\n label=\"Status\"\n status={data?.todayMeals?.dataStatus}\n warnings={data?.todayMeals?.warnings}\n />\n <Box flexDirection=\"column\" marginTop={1}>\n {data?.todayMeals?.meals.length ? (\n data.todayMeals.meals.map((meal) => (\n <ListRow\n key={meal.type}\n accent=\"green\"\n primary={meal.type}\n secondary={meal.items.slice(0, 4).map((item) => item.name).join(', ')}\n />\n ))\n ) : (\n <EmptyState title=\"Meals idle\" message=\"No meal rows are loaded for today yet.\" />\n )}\n </Box>\n </Panel>\n\n <Panel title=\"Alerts and setup\" subtitle=\"Notes, gaps, and guidance\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {notes.length ? (\n notes.map((note) => (\n <Text key={note} color=\"gray\">\n - {note}\n </Text>\n ))\n ) : (\n <Text color=\"gray\">No setup notes right now.</Text>\n )}\n <IssueList issues={data?.issues} title=\"Provider issues\" />\n </Box>\n </Panel>\n </Box>\n );\n}\n\nexport function SchoolsPage({\n session,\n searchState,\n lineInputActive,\n}: {\n session: HumanSessionContext;\n searchState: SearchState;\n lineInputActive?: boolean;\n}) {\n const queryValue = searchState.query || 'Type a school name';\n\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Search console\" subtitle=\"Find and apply a school\" accent=\"magenta\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"Current school\"\n value={renderSchoolLabel(session.selectedSchool?.name, session.selectedSchool?.region)}\n note=\"Current shell target\"\n accent=\"cyan\"\n width={38}\n />\n <MetricCard\n label=\"Query\"\n value={lineInputActive ? `${queryValue} [line capture active]` : `${queryValue} |`}\n note=\"Enter to query, I for IME-safe editing, Enter again to apply\"\n accent=\"magenta\"\n width={38}\n />\n </Box>\n {searchState.loading ? (\n <Callout title=\"Search in progress\" accent=\"cyan\">\n Searching schools...\n </Callout>\n ) : null}\n {searchState.error ? (\n <Callout title=\"Search issue\" accent=\"red\">\n {searchState.error}\n </Callout>\n ) : (\n <Text color=\"gray\">\n Enter searches when the query changed. Enter again applies the highlighted school. Press I for IME-safe editing.\n </Text>\n )}\n </Panel>\n\n <Panel title=\"Results\" subtitle=\"Merged Comcigan + NEIS candidates\" accent=\"magenta\">\n <Box flexDirection=\"column\">\n {searchState.results.length ? (\n searchState.results.slice(0, 8).map((school, index) => {\n const active = index === searchState.selectedIndex;\n return (\n <ListRow\n key={`${school.name}-${school.region}-${index}`}\n active={active}\n accent=\"magenta\"\n leading={String(index + 1)}\n primary={school.name}\n secondary={school.region ? `(${school.region})` : undefined}\n meta={school.schoolType}\n />\n );\n })\n ) : (\n <EmptyState\n title=\"No search results\"\n message=\"Start typing a school name, then press Enter to query the merged search providers.\"\n />\n )}\n </Box>\n </Panel>\n\n <Panel title=\"Recent quick picks\" subtitle=\"Fast reuse without retyping\" accent=\"cyan\">\n <Box flexDirection=\"column\">\n {session.recentSchools.slice(0, 9).length ? (\n session.recentSchools.slice(0, 9).map((school, index) => (\n <ListRow\n key={`${school.name}-${school.region}-${index}`}\n accent=\"cyan\"\n primary={school.name}\n secondary={school.region ? `(${school.region})` : undefined}\n meta={isSameSchool(session.selectedSchool, school) ? 'current' : undefined}\n leading={`${index + 1}.`}\n />\n ))\n ) : (\n <EmptyState\n title=\"No quick picks yet\"\n message=\"Once you use schools, the recent-school rail will appear here.\"\n />\n )}\n <Text color=\"gray\">\n Press 1-9 when the search box is empty to reuse a recent school immediately.\n </Text>\n </Box>\n </Panel>\n </Box>\n );\n}\n\nexport function TimetablePage({ data }: { data?: HumanTimetableData }) {\n return (\n <Box flexDirection=\"column\">\n {data?.notes?.length ? (\n <Callout title=\"Timetable notes\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {data.notes.map((note) => (\n <Text key={note} color=\"gray\">\n - {note}\n </Text>\n ))}\n </Box>\n </Callout>\n ) : null}\n <DataStatusSummary\n label=\"Weekly timetable\"\n status={data?.week?.dataStatus}\n warnings={data?.week?.warnings}\n />\n {data?.week ? (\n <WeekTimetableView week={data.week} />\n ) : (\n <EmptyState title=\"Timetable idle\" message=\"No weekly timetable is currently loaded.\" />\n )}\n <IssueList issues={data?.issues} />\n </Box>\n );\n}\n\nexport function MealsPage({ data }: { data?: HumanMealsData }) {\n return (\n <Box flexDirection=\"column\">\n {data?.notes?.length ? (\n <Callout title=\"Meals notes\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {data.notes.map((note) => (\n <Text key={note} color=\"gray\">\n - {note}\n </Text>\n ))}\n </Box>\n </Callout>\n ) : null}\n <DataStatusSummary\n label=\"Weekly meals\"\n status={data?.week?.dataStatus}\n warnings={data?.week?.warnings}\n />\n {data?.week ? (\n <WeeklyMealsView week={data.week} />\n ) : (\n <EmptyState title=\"Meals idle\" message=\"No weekly meals are currently loaded.\" />\n )}\n <IssueList issues={data?.issues} />\n </Box>\n );\n}\n\nexport function TeacherPage({\n session,\n data,\n}: {\n session: HumanSessionContext;\n data?: HumanTeacherData;\n}) {\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Teacher focus\" subtitle=\"Current shell teacher context\" accent=\"magenta\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"Teacher\"\n value={session.teacherName ?? 'Not set'}\n note=\"Teacher page target\"\n accent=\"magenta\"\n width={30}\n />\n <MetricCard\n label=\"School\"\n value={renderSchoolLabel(session.selectedSchool?.name, session.selectedSchool?.region)}\n note=\"Current school context\"\n accent=\"cyan\"\n width={36}\n />\n </Box>\n </Panel>\n\n {data?.notes?.length ? (\n <Callout title=\"Teacher notes\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {data.notes.map((note) => (\n <Text key={note} color=\"gray\">\n - {note}\n </Text>\n ))}\n </Box>\n </Callout>\n ) : null}\n\n <Panel title=\"Teacher profile\" subtitle=\"Info card\" accent=\"green\">\n <DataStatusSummary\n label=\"Teacher info\"\n status={data?.info?.dataStatus}\n warnings={data?.info?.warnings}\n />\n {data?.info ? (\n <Box flexWrap=\"wrap\" marginTop={1}>\n <MetricCard label=\"Name\" value={data.info.name} accent=\"green\" width={28} />\n <MetricCard\n label=\"Subjects\"\n value={data.info.subjects?.join(', ') || 'No subject data'}\n accent=\"cyan\"\n width={36}\n />\n <MetricCard\n label=\"Classes\"\n value={data.info.classes?.join(', ') || 'No class data'}\n accent=\"magenta\"\n width={36}\n />\n </Box>\n ) : (\n <EmptyState title=\"Teacher info idle\" message=\"No teacher info is loaded yet.\" />\n )}\n </Panel>\n\n <Panel title=\"Teacher timetable\" subtitle=\"Weekly view\" accent=\"magenta\">\n <DataStatusSummary\n label=\"Teacher timetable\"\n status={data?.timetable?.dataStatus}\n warnings={data?.timetable?.warnings}\n />\n {data?.timetable ? (\n <TeacherTimetableView timetable={data.timetable} />\n ) : (\n <EmptyState\n title=\"Teacher timetable idle\"\n message=\"No teacher timetable is currently loaded.\"\n />\n )}\n </Panel>\n\n <IssueList issues={data?.issues} />\n </Box>\n );\n}\n\nexport function DiagnosticsPage({ data }: { data?: HumanDiagnosticsData }) {\n if (!data) {\n return <EmptyState title=\"Diagnostics idle\" message=\"No diagnostics were loaded.\" />;\n }\n\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Config posture\" subtitle=\"Auth and storage state\" accent=\"yellow\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"Key source\"\n value={data.configStatus.neisApiKeySource}\n note=\"Current auth resolution path\"\n accent=\"yellow\"\n width={24}\n />\n <MetricCard\n label=\"Key storage\"\n value={describeSecretStorage(\n data.configStatus.neisApiKeyStorage,\n data.configStatus.neisApiKeySource,\n )}\n note=\"Protected local storage mode\"\n accent=\"blue\"\n width={36}\n />\n <MetricCard\n label=\"Key preview\"\n value={data.configStatus.neisApiKeyPreview ?? 'Not configured'}\n note=\"Masked key preview\"\n accent=\"cyan\"\n width={28}\n />\n </Box>\n <InfoLine label=\"Config path\" value={data.configStatus.configPath} tone=\"yellow\" />\n </Panel>\n\n <Panel title=\"Expected provider modes\" subtitle=\"How the shell should behave\" accent=\"cyan\">\n <Box flexDirection=\"column\">\n {data.expectedModes.map((entry) => (\n <ListRow\n key={entry.provider}\n accent={entry.provider === 'neis' ? 'cyan' : 'magenta'}\n primary={entry.provider}\n secondary={entry.accessMode}\n meta={entry.note}\n />\n ))}\n </Box>\n </Panel>\n\n <Panel title=\"Warning ledger\" subtitle=\"Current operator-visible notes\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {data.warnings.length ? (\n data.warnings.map((warning) => (\n <Text key={warning} color=\"yellow\">\n - {warning}\n </Text>\n ))\n ) : (\n <Text color=\"gray\">No current warnings.</Text>\n )}\n </Box>\n </Panel>\n </Box>\n );\n}\n\nexport function SettingsPage({\n session,\n settingsState,\n dialog,\n}: {\n session: HumanSessionContext;\n settingsState: SettingsState;\n dialog?: SettingsDialog;\n}) {\n const config = session.configStatus;\n const selectedProfile = config.profiles[settingsState.profileIndex];\n const selectedRecentSchool = session.recentSchools[settingsState.recentSchoolIndex];\n const actions = buildSettingsActions(session, settingsState);\n const selectedAction = actions[settingsState.actionIndex];\n const activeProfileHasOwnSchool =\n Boolean(session.activeProfile?.school) &&\n session.activeProfile?.school?.name !== config.defaultSchool?.name;\n\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Settings overview\" subtitle=\"Profiles, defaults, and cache policy\" accent=\"blue\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"Active profile\"\n value={session.activeProfile?.name ?? 'None'}\n note=\"Current shell profile\"\n accent=\"magenta\"\n width={24}\n />\n <MetricCard\n label=\"Default school\"\n value={\n config.defaultSchool\n ? `${config.defaultSchool.name}${config.defaultSchool.region ? ` (${config.defaultSchool.region})` : ''}`\n : 'None'\n }\n note=\"Current default school\"\n accent=\"cyan\"\n width={38}\n />\n <MetricCard\n label=\"Cache policy\"\n value={`${config.cachePolicy.datasetTtlMinutes}m / ${config.cachePolicy.staleIfErrorHours}h / ${config.cachePolicy.maxEntries}`}\n note=\"TTL / stale / max entries\"\n accent=\"green\"\n width={32}\n />\n </Box>\n <InfoLine label=\"NEIS source\" value={config.neisApiKeySource} tone=\"yellow\" />\n <InfoLine\n label=\"NEIS storage\"\n value={describeSecretStorage(config.neisApiKeyStorage, config.neisApiKeySource)}\n tone=\"yellow\"\n />\n {activeProfileHasOwnSchool ? (\n <Callout title=\"Profile override\" accent=\"yellow\">\n The active profile has its own school, so it currently overrides the saved default school.\n </Callout>\n ) : null}\n </Panel>\n\n <Panel title=\"Project identity\" subtitle=\"Repository and developer metadata\" accent=\"blue\">\n <Box flexWrap=\"wrap\">\n <MetricCard\n label=\"Project\"\n value={KAMPUS_PROJECT_INFO.name}\n note={`${KAMPUS_PROJECT_INFO.description} [read-only]`}\n accent=\"blue\"\n width={38}\n />\n <MetricCard\n label=\"Developer\"\n value={KAMPUS_DEVELOPER_INFO.name}\n note={KAMPUS_DEVELOPER_INFO.email ?? 'Embedded application metadata'}\n accent=\"magenta\"\n width={34}\n />\n </Box>\n <InfoLine label=\"Repository\" value={KAMPUS_PROJECT_INFO.repositoryUrl} tone=\"cyan\" />\n <InfoLine label=\"Homepage\" value={KAMPUS_PROJECT_INFO.homepageUrl} tone=\"cyan\" />\n <InfoLine label=\"Developer URL\" value={KAMPUS_DEVELOPER_INFO.url ?? 'Not set'} tone=\"magenta\" />\n <Text color=\"gray\">This identity is embedded in the app and cannot be changed from user config.</Text>\n </Panel>\n\n <Panel\n title=\"Profiles\"\n subtitle={\n settingsState.section === 'profiles'\n ? 'Focused pane - Enter activates the selected profile'\n : 'Press Tab to focus'\n }\n accent={settingsState.section === 'profiles' ? 'yellow' : 'cyan'}\n >\n <Box flexDirection=\"column\">\n {config.profiles.length ? (\n config.profiles.map((profile, index) => {\n const focused =\n settingsState.section === 'profiles' && index === settingsState.profileIndex;\n const active = session.activeProfile?.name === profile.name;\n return (\n <ListRow\n key={profile.name}\n active={focused}\n accent=\"yellow\"\n primary={profile.name}\n secondary={profile.school?.name}\n meta={`${profile.grade && profile.classNo ? `${profile.grade}-${profile.classNo}` : 'no class'}${active ? ' active' : ''}`}\n />\n );\n })\n ) : (\n <EmptyState title=\"Profiles idle\" message=\"No saved profiles yet.\" />\n )}\n {selectedProfile ? (\n <Text color=\"gray\">\n Selected profile: {selectedProfile.name}\n {selectedProfile.teacherName ? ` teacher: ${selectedProfile.teacherName}` : ''}\n </Text>\n ) : null}\n </Box>\n </Panel>\n\n <Panel\n title=\"Recent schools\"\n subtitle={\n settingsState.section === 'recent-schools'\n ? 'Focused pane - Enter applies the selected school'\n : 'Press Tab to focus'\n }\n accent={settingsState.section === 'recent-schools' ? 'yellow' : 'cyan'}\n >\n <Box flexDirection=\"column\">\n {session.recentSchools.length ? (\n session.recentSchools.map((school, index) => {\n const focused =\n settingsState.section === 'recent-schools' &&\n index === settingsState.recentSchoolIndex;\n return (\n <ListRow\n key={`${school.name}-${school.region}-${index}`}\n active={focused}\n accent=\"yellow\"\n primary={school.name}\n secondary={school.region ? `(${school.region})` : undefined}\n meta={isSameSchool(session.selectedSchool, school) ? 'current' : school.schoolType}\n />\n );\n })\n ) : (\n <EmptyState title=\"Recent schools idle\" message=\"No recent schools are saved yet.\" />\n )}\n {selectedRecentSchool ? (\n <Text color=\"gray\">\n Selected school: {selectedRecentSchool.name}\n {selectedRecentSchool.schoolType ? ` ${selectedRecentSchool.schoolType}` : ''}\n </Text>\n ) : null}\n </Box>\n </Panel>\n\n <Panel\n title=\"Actions\"\n subtitle={\n settingsState.section === 'actions'\n ? 'Focused pane - Enter runs the selected action'\n : 'Press Tab to focus'\n }\n accent={settingsState.section === 'actions' ? 'yellow' : 'cyan'}\n >\n <Box flexDirection=\"column\">\n {actions.map((action, index) => {\n const focused = settingsState.section === 'actions' && index === settingsState.actionIndex;\n return (\n <ListRow\n key={action.id}\n active={focused}\n accent=\"yellow\"\n primary={action.label}\n meta={action.disabled ? 'disabled' : 'ready'}\n secondary={action.description}\n />\n );\n })}\n {selectedAction ? <Text color=\"gray\">{selectedAction.description}</Text> : null}\n </Box>\n </Panel>\n\n {dialog ? (\n <Panel title={dialog.title} subtitle=\"Confirmation required\" accent=\"red\">\n <Box flexDirection=\"column\">\n <Text>{dialog.description}</Text>\n <Callout title=\"Confirm\" accent=\"red\">\n {dialog.confirmLabel}\n </Callout>\n </Box>\n </Panel>\n ) : null}\n </Box>\n );\n}\n\nexport function HelpPage({}: { session?: HumanSessionContext }) {\n return (\n <Box flexDirection=\"column\">\n <Panel title=\"Workspace identity\" subtitle=\"Project and developer metadata\" accent=\"blue\">\n <Box flexDirection=\"column\">\n <InfoLine label=\"Project\" value={KAMPUS_PROJECT_INFO.name} tone=\"blue\" />\n <InfoLine label=\"Description\" value={KAMPUS_PROJECT_INFO.description} tone=\"blue\" />\n <InfoLine label=\"Repository\" value={KAMPUS_PROJECT_INFO.repositoryUrl} tone=\"cyan\" />\n <InfoLine label=\"Homepage\" value={KAMPUS_PROJECT_INFO.homepageUrl} tone=\"cyan\" />\n <InfoLine label=\"Developer\" value={KAMPUS_DEVELOPER_INFO.name} tone=\"magenta\" />\n <InfoLine label=\"Email\" value={KAMPUS_DEVELOPER_INFO.email ?? 'Not set'} tone=\"magenta\" />\n <InfoLine label=\"Developer URL\" value={KAMPUS_DEVELOPER_INFO.url ?? 'Not set'} tone=\"magenta\" />\n <Text color=\"gray\">This metadata is part of the app build and stays read-only for users.</Text>\n </Box>\n </Panel>\n <Panel title=\"Shell controls\" subtitle=\"Human shell navigation\" accent=\"cyan\">\n <Box flexDirection=\"column\">\n <Text>- Left / Right: move between pages</Text>\n <Text>- H / S / T / M / Y / G / P / ?: jump to page</Text>\n <Text>- I: open IME-safe line input on text-entry screens</Text>\n <Text>- Enter: confirm / search / select</Text>\n <Text>- R: refresh current data page</Text>\n <Text>- E: switch into easy mode</Text>\n <Text>- Q or Ctrl+C: exit</Text>\n <Text>- Settings page: Tab switches panes, Up/Down moves, Enter applies</Text>\n </Box>\n </Panel>\n <Panel title=\"Raw command reminders\" subtitle=\"Automation-safe CLI still available\" accent=\"blue\">\n <Box flexDirection=\"column\">\n <Text>- kps school search \"<school>\"</Text>\n <Text>- kps class week --school \"<school>\" --grade 3 --class 5</Text>\n <Text>- kps meals today --school \"<school>\" --date 2026-03-12</Text>\n <Text>- kps neis schedule --school \"<school>\" --from 2026-03-01 --to 2026-03-31</Text>\n <Text>- kps doctor --live --json</Text>\n </Box>\n </Panel>\n <Callout title=\"Design rule\" accent=\"yellow\">\n All raw commands remain unchanged. This shell is a human-friendly presentation layer over the same engine.\n </Callout>\n </Box>\n );\n}\n\nexport function EasyModeView({\n easyState,\n session,\n lineInputTarget,\n}: {\n easyState: EasyState;\n session: HumanSessionContext | null;\n lineInputTarget?: 'easy-school-query' | 'easy-teacher-name';\n}) {\n const selectedSchool = easyState.results[easyState.selectedIndex];\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header\n summary={{\n school: session?.selectedSchool?.name ?? 'No school selected',\n profile: session?.activeProfile?.name ?? 'No active profile',\n access: session?.configStatus.neisApiKeyConfigured ? 'official-full' : 'official-limited',\n }}\n subtitle={KAMPUS_TAGLINE}\n />\n <Panel title=\"Easy Mode\" subtitle=\"Guided setup for first-time interactive use\" accent=\"yellow\">\n <StepTrack\n steps={['welcome', 'search', 'class', 'teacher', 'saving']}\n current={easyState.step}\n />\n {selectedSchool ? (\n <Box flexWrap=\"wrap\" marginBottom={1}>\n <MetricCard\n label=\"School\"\n value={selectedSchool.name}\n note={selectedSchool.region ?? 'Region not set'}\n accent=\"cyan\"\n width={38}\n />\n <MetricCard\n label=\"Class target\"\n value={`${easyState.grade}-${easyState.classNo}`}\n note=\"Editable in class step\"\n accent=\"blue\"\n width={24}\n />\n <MetricCard\n label=\"Teacher\"\n value={easyState.teacherName || 'Optional'}\n note=\"Teacher page shortcut target\"\n accent=\"magenta\"\n width={30}\n />\n </Box>\n ) : null}\n {easyState.step === 'welcome' ? (\n <Callout title=\"Setup flow\" accent=\"cyan\">\n <Box flexDirection=\"column\">\n <Text>1. Search your school</Text>\n <Text>2. Choose grade and class</Text>\n <Text>3. Optionally save a teacher name</Text>\n <Text color=\"gray\">Press Enter to start, or Esc to return to human mode.</Text>\n </Box>\n </Callout>\n ) : null}\n\n {easyState.step === 'search' ? (\n <Box flexDirection=\"column\">\n <InfoLine\n label=\"School query\"\n value={\n lineInputTarget === 'easy-school-query'\n ? `${easyState.query || 'Type a school name'} [line capture active]`\n : `${easyState.query || 'Type a school name'} |`\n }\n tone=\"cyan\"\n />\n <Text color=\"gray\">\n Press Enter to search. Press Enter again to confirm the highlighted school. Press I for IME-safe editing.\n </Text>\n {easyState.error ? (\n <Callout title=\"Search issue\" accent=\"red\">\n {easyState.error}\n </Callout>\n ) : null}\n {easyState.loading ? (\n <Callout title=\"Search in progress\" accent=\"cyan\">\n Searching schools...\n </Callout>\n ) : null}\n <Panel title=\"Search results\" subtitle=\"Choose the highlighted school\" accent=\"yellow\">\n <Box flexDirection=\"column\">\n {easyState.results.length ? (\n easyState.results.slice(0, 8).map((school, index) => (\n <ListRow\n key={`${school.name}-${school.region}-${index}`}\n active={index === easyState.selectedIndex}\n accent=\"yellow\"\n primary={school.name}\n secondary={school.region ? `(${school.region})` : undefined}\n meta={school.schoolType}\n />\n ))\n ) : (\n <EmptyState\n title=\"No school results\"\n message=\"Run a school search to continue the guided setup.\"\n />\n )}\n </Box>\n </Panel>\n </Box>\n ) : null}\n\n {easyState.step === 'class' ? (\n <Callout title=\"Choose grade and class\" accent=\"blue\">\n <Box flexDirection=\"column\">\n <Text>School: {selectedSchool?.name ?? 'None selected'}</Text>\n <Text>Up / Down adjust grade: {easyState.grade}</Text>\n <Text>Left / Right adjust class: {easyState.classNo}</Text>\n <Text color=\"gray\">Press Enter when these values look right.</Text>\n </Box>\n </Callout>\n ) : null}\n\n {easyState.step === 'teacher' || easyState.step === 'saving' ? (\n <Callout title=\"Optional teacher shortcut\" accent=\"magenta\">\n <Box flexDirection=\"column\">\n <Text>School: {selectedSchool?.name ?? 'None selected'}</Text>\n <Text>Class: {easyState.grade}-{easyState.classNo}</Text>\n <Text>\n Teacher:{' '}\n {lineInputTarget === 'easy-teacher-name'\n ? `${easyState.teacherName || 'Leave blank to skip'} [line capture active]`\n : `${easyState.teacherName || 'Leave blank to skip'} |`}\n </Text>\n <Text color=\"gray\">\n Type a teacher name if you want teacher views ready too, then press Enter. Press I for IME-safe editing.\n </Text>\n {easyState.error ? <Text color=\"red\">{easyState.error}</Text> : null}\n {easyState.loading ? (\n <Text color=\"yellow\">Saving your easy mode profile...</Text>\n ) : null}\n </Box>\n </Callout>\n ) : null}\n </Panel>\n <Footer page=\"help\" mode=\"easy\" />\n </Box>\n );\n}\n\nfunction WeekTimetableView({ week }: { week: WeekTimetable }) {\n return (\n <Box flexDirection=\"column\">\n {week.days.map((day) => (\n <Panel\n key={`${day.weekday}-${day.date ?? day.weekdayName}`}\n title={day.weekdayName}\n subtitle={day.date}\n accent=\"cyan\"\n >\n <Box flexDirection=\"column\">\n {day.periods.length ? (\n day.periods.map((period) => (\n <ListRow\n key={`${day.weekday}-${period.period}`}\n accent=\"cyan\"\n leading={`P${period.period}`}\n primary={period.subject}\n secondary={period.teacher ? `[${period.teacher}]` : undefined}\n />\n ))\n ) : (\n <Text color=\"gray\">No periods listed.</Text>\n )}\n </Box>\n </Panel>\n ))}\n </Box>\n );\n}\n\nfunction WeeklyMealsView({ week }: { week: WeeklyMeals }) {\n return (\n <Box flexDirection=\"column\">\n {week.days.map((day) => (\n <Panel\n key={day.date}\n title={day.date}\n subtitle={day.weekdayName}\n accent=\"green\"\n >\n <Box flexDirection=\"column\">\n {(day.meals ?? []).length ? (\n (day.meals ?? []).map((meal) => (\n <ListRow\n key={`${day.date}-${meal.type}`}\n accent=\"green\"\n primary={meal.type}\n secondary={meal.items.slice(0, 4).map((item) => item.name).join(', ')}\n />\n ))\n ) : (\n <Text color=\"gray\">No meals listed.</Text>\n )}\n </Box>\n </Panel>\n ))}\n </Box>\n );\n}\n\nfunction TeacherTimetableView({ timetable }: { timetable: TeacherTimetable }) {\n return (\n <Box flexDirection=\"column\">\n {timetable.days.map((day) => (\n <Panel\n key={`${day.weekday}-${day.date ?? day.weekdayName}`}\n title={day.weekdayName}\n subtitle={day.date}\n accent=\"magenta\"\n >\n <Box flexDirection=\"column\">\n {day.periods.length ? (\n day.periods.map((period) => (\n <ListRow\n key={`${day.weekday}-${period.period}`}\n accent=\"magenta\"\n leading={`P${period.period}`}\n primary={period.subject}\n secondary={period.classLabel ? `[${period.classLabel}]` : undefined}\n />\n ))\n ) : (\n <Text color=\"gray\">No periods listed.</Text>\n )}\n </Box>\n </Panel>\n ))}\n </Box>\n );\n}\n\nfunction renderSchoolLabel(name?: string, region?: string): string {\n if (!name) {\n return 'Not set';\n }\n return region ? `${name} (${region})` : name;\n}\n\nfunction isSameSchool(\n left?: { name?: string; region?: string },\n right?: { name?: string; region?: string },\n): boolean {\n return Boolean(\n left?.name &&\n right?.name &&\n left.name === right.name &&\n (left.region ?? '') === (right.region ?? ''),\n );\n}\n\n", "import { HUMAN_PAGES, type HumanPageId, type KeyLike } from './types.js';\n\nexport function resolvePageShortcut(input: string): HumanPageId | undefined {\n switch (input) {\n case 'h':\n return 'home';\n case 's':\n return 'schools';\n case 't':\n return 'timetable';\n case 'm':\n return 'meals';\n case 'y':\n return 'teacher';\n case 'g':\n return 'diagnostics';\n case 'p':\n return 'settings';\n case '?':\n return 'help';\n default:\n return undefined;\n }\n}\n\nexport function pageIndexFor(page: HumanPageId): number {\n return HUMAN_PAGES.findIndex((entry) => entry.id === page);\n}\n\nexport function isTypingInput(input: string, key: KeyLike): boolean {\n return Boolean(\n input &&\n !key.ctrl &&\n !key.meta &&\n !key.return &&\n !key.escape &&\n !key.backspace &&\n !key.delete &&\n !key.leftArrow &&\n !key.rightArrow &&\n !key.upArrow &&\n !key.downArrow &&\n !key.tab,\n );\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function resolveRecentSchoolShortcut(input: string): number | undefined {\n if (!/^[1-9]$/.test(input)) {\n return undefined;\n }\n return Number.parseInt(input, 10) - 1;\n}\n", "import { clamp } from './shortcuts.js';\nimport type {\n HumanSessionContext,\n SettingsActionId,\n SettingsActionItem,\n SettingsDialog,\n SettingsSection,\n SettingsState,\n} from './types.js';\n\nconst SETTINGS_SECTIONS: SettingsSection[] = ['profiles', 'recent-schools', 'actions'];\n\nexport function buildSettingsActions(\n session: HumanSessionContext,\n state: SettingsState,\n): SettingsActionItem[] {\n const selectedProfile = session.configStatus.profiles[state.profileIndex];\n const selectedRecentSchool = session.recentSchools[state.recentSchoolIndex];\n const canSaveSession = Boolean(\n session.selectedSchool || session.grade || session.classNo || session.teacherName,\n );\n\n return [\n {\n id: 'save-active-profile',\n label: 'Save current setup to active profile',\n description: session.activeProfile\n ? `Overwrite \"${session.activeProfile.name}\" with the current school, class, and teacher state.`\n : 'No active profile is selected right now.',\n disabled: !session.activeProfile || !canSaveSession,\n },\n {\n id: 'save-shell-profile',\n label: 'Save current setup to human-shell',\n description: canSaveSession\n ? 'Create or update the \"human-shell\" profile from the current shell state.'\n : 'Pick a school or class setup first, then save it as a reusable profile.',\n disabled: !canSaveSession,\n },\n {\n id: 'clear-active-profile',\n label: 'Clear active profile',\n description: session.activeProfile\n ? `Stop using \"${session.activeProfile.name}\" as the active profile.`\n : 'No active profile is selected right now.',\n disabled: !session.activeProfile,\n },\n {\n id: 'clear-default-school',\n label: 'Clear default school',\n description: session.configStatus.defaultSchool\n ? `Remove \"${session.configStatus.defaultSchool.name}\" as the saved default school.`\n : 'No default school is saved right now.',\n disabled: !session.configStatus.defaultSchool,\n },\n {\n id: 'remove-selected-profile',\n label: 'Remove selected profile',\n description: selectedProfile\n ? `Delete \"${selectedProfile.name}\" from the saved profile list.`\n : 'No profile is currently selected.',\n disabled: !selectedProfile,\n },\n {\n id: 'remove-selected-recent-school',\n label: 'Remove selected recent school',\n description: selectedRecentSchool\n ? `Remove \"${selectedRecentSchool.name}\" from recent schools.`\n : 'No recent school is currently selected.',\n disabled: !selectedRecentSchool,\n },\n {\n id: 'refresh-session',\n label: 'Refresh shell session',\n description: 'Reload current config, defaults, and profile state.',\n disabled: false,\n },\n ];\n}\n\nexport function cycleSettingsSection(current: SettingsSection): SettingsSection {\n const currentIndex = SETTINGS_SECTIONS.indexOf(current);\n const nextIndex = (currentIndex + 1) % SETTINGS_SECTIONS.length;\n return SETTINGS_SECTIONS[nextIndex] ?? SETTINGS_SECTIONS[0];\n}\n\nexport function moveSettingsSelection(\n state: SettingsState,\n session: HumanSessionContext,\n delta: number,\n): SettingsState {\n switch (state.section) {\n case 'profiles':\n return {\n ...state,\n profileIndex: clamp(\n state.profileIndex + delta,\n 0,\n Math.max(0, session.configStatus.profiles.length - 1),\n ),\n };\n case 'recent-schools':\n return {\n ...state,\n recentSchoolIndex: clamp(\n state.recentSchoolIndex + delta,\n 0,\n Math.max(0, session.recentSchools.length - 1),\n ),\n };\n case 'actions':\n return {\n ...state,\n actionIndex: clamp(\n state.actionIndex + delta,\n 0,\n Math.max(0, buildSettingsActions(session, state).length - 1),\n ),\n };\n }\n}\n\nexport function buildSettingsDialog(\n actionId: SettingsActionId,\n session: HumanSessionContext,\n state: SettingsState,\n): SettingsDialog | undefined {\n switch (actionId) {\n case 'clear-active-profile':\n return session.activeProfile\n ? {\n actionId,\n title: 'Clear active profile?',\n description: `This will stop using \"${session.activeProfile.name}\" as the active profile.`,\n confirmLabel: 'Press Enter to clear it.',\n }\n : undefined;\n case 'clear-default-school':\n return session.configStatus.defaultSchool\n ? {\n actionId,\n title: 'Clear default school?',\n description: `This will remove \"${session.configStatus.defaultSchool.name}\" as the saved default school.`,\n confirmLabel: 'Press Enter to clear it.',\n }\n : undefined;\n case 'remove-selected-profile': {\n const selectedProfile = session.configStatus.profiles[state.profileIndex];\n return selectedProfile\n ? {\n actionId,\n title: 'Remove selected profile?',\n description: `This will permanently remove \"${selectedProfile.name}\" from saved profiles.`,\n confirmLabel: 'Press Enter to remove it.',\n }\n : undefined;\n }\n case 'remove-selected-recent-school': {\n const selectedRecentSchool = session.recentSchools[state.recentSchoolIndex];\n return selectedRecentSchool\n ? {\n actionId,\n title: 'Remove selected recent school?',\n description: `This will remove \"${selectedRecentSchool.name}\" from the recent-school list.`,\n confirmLabel: 'Press Enter to remove it.',\n }\n : undefined;\n }\n default:\n return undefined;\n }\n}\n\nexport function isDestructiveSettingsAction(actionId: SettingsActionId): boolean {\n return (\n actionId === 'clear-active-profile' ||\n actionId === 'clear-default-school' ||\n actionId === 'remove-selected-profile' ||\n actionId === 'remove-selected-recent-school'\n );\n}\n", "import {\n clearDefaultSchool,\n getKampusConfigStatus,\n loadKampusConfig,\n providerIdsFromRefs,\n removeProfile,\n removeRecentSchool,\n saveKampusConfig,\n setActiveProfile,\n setDefaultSchool,\n type ClassTimeSlot,\n type DailyMeals,\n type DayTimetable,\n type KampusConfigStatus,\n type KampusProfile,\n type KampusStoredSchool,\n type PeriodItem,\n type SchoolRef,\n type SchoolSearchResult,\n type TeacherInfo,\n type TeacherTimetable,\n type WeekTimetable,\n type WeeklyMeals,\n upsertProfile,\n} from '@kampus/core';\nimport { createClient } from '../client-factory.js';\n\nexport type InteractiveMode = 'human' | 'easy';\n\nexport interface HumanSessionContext {\n checkedAt: string;\n configStatus: KampusConfigStatus;\n activeProfile?: KampusProfile;\n selectedSchool?: SchoolSearchResult;\n grade?: number;\n classNo?: number;\n teacherName?: string;\n recentSchools: SchoolSearchResult[];\n notes: string[];\n}\n\nexport interface HumanIssue {\n section: string;\n message: string;\n}\n\nexport interface HumanHomeData {\n loadedAt: string;\n todayTimetable?: DayTimetable;\n todayMeals?: DailyMeals;\n classTimes?: ClassTimeSlot[];\n nextClass?: {\n period: PeriodItem;\n minutesUntil?: number;\n } | null;\n issues: HumanIssue[];\n notes: string[];\n}\n\nexport interface HumanTimetableData {\n loadedAt: string;\n week?: WeekTimetable;\n issues: HumanIssue[];\n notes: string[];\n}\n\nexport interface HumanMealsData {\n loadedAt: string;\n week?: WeeklyMeals;\n issues: HumanIssue[];\n notes: string[];\n}\n\nexport interface HumanTeacherData {\n loadedAt: string;\n info?: TeacherInfo;\n timetable?: TeacherTimetable;\n issues: HumanIssue[];\n notes: string[];\n}\n\nexport interface HumanDiagnosticsData {\n loadedAt: string;\n configStatus: KampusConfigStatus;\n expectedModes: Array<{ provider: 'comcigan' | 'neis'; accessMode: string; note: string }>;\n warnings: string[];\n}\n\nexport interface EasyProfileInput {\n school: SchoolRef;\n grade: number;\n classNo: number;\n teacherName?: string;\n profileName?: string;\n}\n\nexport async function loadHumanSessionContext(): Promise<HumanSessionContext> {\n const configStatus = getKampusConfigStatus();\n const activeProfile = configStatus.activeProfile;\n const selectedSchool = activeProfile?.school\n ? storedSchoolToSearchResult(activeProfile.school)\n : configStatus.defaultSchool\n ? storedSchoolToSearchResult(configStatus.defaultSchool)\n : undefined;\n const recentSchools = configStatus.recentSchools.map(storedSchoolToSearchResult);\n const notes = buildSessionNotes({\n selectedSchool,\n grade: activeProfile?.grade,\n classNo: activeProfile?.classNo,\n teacherName: activeProfile?.teacherName,\n neisConfigured: configStatus.neisApiKeyConfigured,\n });\n\n return {\n checkedAt: new Date().toISOString(),\n configStatus,\n activeProfile,\n selectedSchool,\n grade: activeProfile?.grade,\n classNo: activeProfile?.classNo,\n teacherName: activeProfile?.teacherName,\n recentSchools,\n notes,\n };\n}\n\nexport async function searchHumanSchools(keyword: string): Promise<SchoolSearchResult[]> {\n const client = createClient();\n return client.searchSchools(keyword);\n}\n\nexport async function saveHumanDefaultSchoolSelection(\n school: SchoolSearchResult,\n): Promise<HumanSessionContext> {\n let nextConfig = setDefaultSchool(loadKampusConfig(), school);\n const activeProfileKey = nextConfig.activeProfile;\n const activeProfile = activeProfileKey ? nextConfig.profiles?.[activeProfileKey] : undefined;\n\n if (activeProfile) {\n nextConfig = upsertProfile(nextConfig, {\n ...activeProfile,\n name: activeProfile.name,\n school,\n });\n }\n\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function activateHumanProfileSelection(\n profileName: string,\n): Promise<HumanSessionContext> {\n const nextConfig = setActiveProfile(loadKampusConfig(), profileName);\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function clearHumanActiveProfileSelection(): Promise<HumanSessionContext> {\n const nextConfig = setActiveProfile(loadKampusConfig(), undefined);\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function clearHumanDefaultSchoolSelection(): Promise<HumanSessionContext> {\n const nextConfig = clearDefaultSchool(loadKampusConfig());\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function saveHumanSessionProfile(\n session: HumanSessionContext,\n profileName: string,\n options?: { activate?: boolean },\n): Promise<HumanSessionContext> {\n let nextConfig = upsertProfile(loadKampusConfig(), {\n name: profileName,\n school: session.selectedSchool,\n grade: session.grade,\n classNo: session.classNo,\n teacherName: session.teacherName,\n notes: 'Saved from Kampus human shell.',\n });\n\n if (options?.activate) {\n nextConfig = setActiveProfile(nextConfig, profileName);\n }\n\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function removeHumanProfileSelection(\n profileName: string,\n): Promise<HumanSessionContext> {\n const nextConfig = removeProfile(loadKampusConfig(), profileName);\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function removeHumanRecentSchoolSelection(\n school: SchoolSearchResult,\n): Promise<HumanSessionContext> {\n const nextConfig = removeRecentSchool(loadKampusConfig(), school);\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function saveEasyProfile(input: EasyProfileInput): Promise<HumanSessionContext> {\n const profileName = input.profileName?.trim() || 'easy-default';\n let nextConfig = setDefaultSchool(loadKampusConfig(), input.school);\n nextConfig = upsertProfile(nextConfig, {\n name: profileName,\n school: input.school,\n grade: input.grade,\n classNo: input.classNo,\n teacherName: input.teacherName?.trim() || undefined,\n notes: 'Created from Kampus easy mode.',\n });\n nextConfig = setActiveProfile(nextConfig, profileName);\n saveKampusConfig(nextConfig);\n return loadHumanSessionContext();\n}\n\nexport async function loadHumanHomeData(context: HumanSessionContext): Promise<HumanHomeData> {\n const loadedAt = new Date().toISOString();\n const issues: HumanIssue[] = [];\n const notes: string[] = [];\n const school = context.selectedSchool;\n\n if (!school) {\n notes.push('Choose a school first to load timetable, meals, and class-time cards.');\n return { loadedAt, issues, notes };\n }\n\n const client = createClient();\n let todayTimetable: DayTimetable | undefined;\n let todayMeals: DailyMeals | undefined;\n let classTimes: ClassTimeSlot[] | undefined;\n let nextClass: { period: PeriodItem; minutesUntil?: number } | null | undefined;\n\n const tasks: Promise<void>[] = [];\n\n tasks.push(\n safeLoad('today-meals', async () => {\n todayMeals = await client.getMealsToday({ school });\n }, issues),\n );\n\n tasks.push(\n safeLoad('class-times', async () => {\n classTimes = await client.getClassTimes(school);\n }, issues),\n );\n\n if (context.grade && context.classNo) {\n tasks.push(\n safeLoad('today-timetable', async () => {\n todayTimetable = await client.getTodayTimetable({\n school,\n grade: context.grade!,\n classNo: context.classNo!,\n });\n }, issues),\n );\n\n tasks.push(\n safeLoad('next-class', async () => {\n nextClass = await client.getNextClass({\n school,\n grade: context.grade!,\n classNo: context.classNo!,\n });\n }, issues),\n );\n } else {\n notes.push('Add grade and class to unlock the today timetable and next class cards.');\n }\n\n await Promise.all(tasks);\n\n if (!context.teacherName) {\n notes.push('Add a teacher name to make the teacher page ready for direct use.');\n }\n\n return {\n loadedAt,\n todayTimetable,\n todayMeals,\n classTimes,\n nextClass: nextClass ?? null,\n issues,\n notes,\n };\n}\n\nexport async function loadHumanWeekTimetable(\n context: HumanSessionContext,\n): Promise<HumanTimetableData> {\n const loadedAt = new Date().toISOString();\n const issues: HumanIssue[] = [];\n const notes: string[] = [];\n\n if (!context.selectedSchool) {\n notes.push('Choose a school before loading the weekly timetable.');\n return { loadedAt, issues, notes };\n }\n if (!context.grade || !context.classNo) {\n notes.push('A saved grade and class are required before the weekly timetable can load.');\n return { loadedAt, issues, notes };\n }\n\n const client = createClient();\n let week: WeekTimetable | undefined;\n await safeLoad('week-timetable', async () => {\n week = await client.getWeekTimetable({\n school: context.selectedSchool!,\n grade: context.grade!,\n classNo: context.classNo!,\n });\n }, issues);\n\n return { loadedAt, week, issues, notes };\n}\n\nexport async function loadHumanWeeklyMeals(\n context: HumanSessionContext,\n): Promise<HumanMealsData> {\n const loadedAt = new Date().toISOString();\n const issues: HumanIssue[] = [];\n const notes: string[] = [];\n\n if (!context.selectedSchool) {\n notes.push('Choose a school before loading weekly meals.');\n return { loadedAt, issues, notes };\n }\n\n const client = createClient();\n let week: WeeklyMeals | undefined;\n await safeLoad('weekly-meals', async () => {\n week = await client.getMealsWeek({\n school: context.selectedSchool!,\n });\n }, issues);\n\n return { loadedAt, week, issues, notes };\n}\n\nexport async function loadHumanTeacherData(\n context: HumanSessionContext,\n): Promise<HumanTeacherData> {\n const loadedAt = new Date().toISOString();\n const issues: HumanIssue[] = [];\n const notes: string[] = [];\n\n if (!context.selectedSchool) {\n notes.push('Choose a school before opening the teacher view.');\n return { loadedAt, issues, notes };\n }\n if (!context.teacherName) {\n notes.push('Add a teacher name before loading teacher info and the teacher timetable.');\n return { loadedAt, issues, notes };\n }\n\n const client = createClient();\n let info: TeacherInfo | undefined;\n let timetable: TeacherTimetable | undefined;\n\n await Promise.all([\n safeLoad('teacher-info', async () => {\n info = await client.getTeacherInfo({\n school: context.selectedSchool!,\n teacherName: context.teacherName!,\n });\n }, issues),\n safeLoad('teacher-timetable', async () => {\n timetable = await client.getTeacherTimetable({\n school: context.selectedSchool!,\n teacherName: context.teacherName!,\n });\n }, issues),\n ]);\n\n return { loadedAt, info, timetable, issues, notes };\n}\n\nexport async function loadHumanDiagnostics(\n context?: HumanSessionContext,\n): Promise<HumanDiagnosticsData> {\n const session = context ?? (await loadHumanSessionContext());\n const warnings: string[] = [...session.notes];\n\n if (session.configStatus.neisApiKeyStored && !session.configStatus.neisApiKeyReadable) {\n warnings.push('A stored NEIS key exists, but it is not readable in this environment.');\n }\n if (!session.configStatus.neisApiKeyConfigured) {\n warnings.push('NEIS official queries are running in limited mode because no API key is configured.');\n }\n\n return {\n loadedAt: new Date().toISOString(),\n configStatus: session.configStatus,\n expectedModes: [\n {\n provider: 'comcigan',\n accessMode: 'unofficial',\n note: 'Student timetable, teacher timetable, and class times currently come from Comcigan.',\n },\n {\n provider: 'neis',\n accessMode: session.configStatus.neisApiKeyConfigured ? 'official-full' : 'official-limited',\n note: session.configStatus.neisApiKeyConfigured\n ? 'School info, meals, and official NEIS datasets are available in full mode.'\n : 'School info and meals are available, but official NEIS queries stay in limited mode.',\n },\n ],\n warnings,\n };\n}\n\nfunction storedSchoolToSearchResult(stored: KampusStoredSchool): SchoolSearchResult {\n return {\n name: stored.name,\n region: stored.region,\n schoolType: stored.schoolType,\n providerRefs: stored.providerRefs,\n sourceProviders: providerIdsFromRefs(stored.providerRefs),\n };\n}\n\nfunction buildSessionNotes(input: {\n selectedSchool?: SchoolSearchResult;\n grade?: number;\n classNo?: number;\n teacherName?: string;\n neisConfigured: boolean;\n}): string[] {\n const notes: string[] = [];\n\n if (!input.selectedSchool) {\n notes.push('No default school is saved yet. Start on the school page and choose one.');\n }\n if (!input.grade || !input.classNo) {\n notes.push('No grade/class is saved yet, so timetable cards may stay empty.');\n }\n if (!input.teacherName) {\n notes.push('Add a teacher name if you want teacher info and teacher timetable shortcuts ready.');\n }\n if (!input.neisConfigured) {\n notes.push('Without a NEIS key, official queries continue in limited mode.');\n }\n\n return notes;\n}\n\nasync function safeLoad(\n section: string,\n task: () => Promise<void>,\n issues: HumanIssue[],\n): Promise<void> {\n try {\n await task();\n } catch (error) {\n issues.push({\n section,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n}\n", "import type { Command } from 'commander';\nimport { runInteractiveCli } from '../tui/index.js';\n\nexport function interactiveCommands(program: Command): void {\n program\n .command('human')\n .description('Launch the interactive human shell')\n .option('--no-splash', 'Skip the splash/logo animation')\n .action(async (opts) => {\n await runInteractiveCli({\n mode: 'human',\n splash: opts.splash,\n });\n });\n\n program\n .command('easy')\n .description('Launch the guided easy mode')\n .option('--no-splash', 'Skip the splash/logo animation')\n .action(async (opts) => {\n await runInteractiveCli({\n mode: 'easy',\n splash: opts.splash,\n });\n });\n}\n", "import type { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { InvalidInputError, type WeekTimetable } from '@kampus/core';\nimport { createClient } from '../client-factory.js';\nimport { getFormat, printSnapshotDiff, printWeekTimetable } from '../output.js';\nimport { resolveGradeClassDefaults } from './resolve.js';\n\nexport function utilCommands(program: Command): void {\n program\n .command('diff')\n .description('Diff two serialized week timetable snapshots')\n .requiredOption('--snapshot-a <file>', 'First snapshot JSON file')\n .requiredOption('--snapshot-b <file>', 'Second snapshot JSON file')\n .option('--format <type>', 'Output format (human|json|markdown|yaml|csv|table|ndjson)')\n .option('--json', 'Print JSON')\n .option('--markdown', 'Print Markdown')\n .addHelpText('after', '\\nExample:\\n kps diff --snapshot-a week1.json --snapshot-b week2.json')\n .action(async (opts) => {\n const client = createClient();\n const snapshotA = parseWeekSnapshotFile(opts.snapshotA);\n const snapshotB = parseWeekSnapshotFile(opts.snapshotB);\n const diff = client.diffSnapshots(snapshotA, snapshotB);\n printSnapshotDiff(diff, getFormat(opts));\n });\n\n program\n .command('export')\n .description('Export a weekly timetable in JSON or Markdown')\n .option('--school <name>', 'School name (defaults to saved default school)')\n .option('--region <name>', 'Region hint to disambiguate')\n .option('--grade <n>', 'Grade (falls back to active profile)', parseInt)\n .option('--class <n>', 'Class number (falls back to active profile)', parseInt)\n .option('--format <type>', 'Output format (json|markdown)', 'json')\n .addHelpText('after', '\\nExample:\\n kps export --school \"<school>\" --region \"<region>\" --grade 3 --class 5 --format markdown')\n .action(async (opts) => {\n const { resolveSchool } = await import('./resolve.js');\n const client = createClient();\n const school = await resolveSchool(client, opts.school, opts.region);\n const { grade, classNo } = requireGradeClass(opts.grade, opts.class);\n const week = await client.getWeekTimetable({\n school,\n grade,\n classNo,\n });\n printWeekTimetable(week, opts.format === 'markdown' ? 'markdown' : 'json');\n });\n}\n\nfunction requireGradeClass(grade?: number, classNo?: number): { grade: number; classNo: number } {\n const resolved = resolveGradeClassDefaults(grade, classNo);\n if (!resolved.grade || !resolved.classNo) {\n throw new InvalidInputError(\n 'Grade and class are required. Pass --grade/--class or save them in the active profile.',\n );\n }\n return resolved;\n}\n\nexport function parseWeekSnapshotFile(path: string): WeekTimetable {\n const raw = readFileSync(path, 'utf-8').replace(/^\\uFEFF/, '');\n return JSON.parse(raw) as WeekTimetable;\n}\n", "import { createProgram } from './program.js';\nimport { detectCliErrorFormat, exitCodeForError, printCliError } from './errors.js';\nimport { canRunInteractiveCli, runInteractiveCli } from './tui/index.js';\n\nexport interface CliIoState {\n stdinIsTty: boolean;\n stdoutIsTty: boolean;\n}\n\nexport function shouldLaunchInteractiveCli(\n args: string[],\n io: CliIoState = {\n stdinIsTty: Boolean(process.stdin.isTTY),\n stdoutIsTty: Boolean(process.stdout.isTTY),\n },\n): boolean {\n return args.length === 0 && canRunInteractiveCli(io.stdinIsTty, io.stdoutIsTty);\n}\n\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n const args = argv.slice(2);\n if (shouldLaunchInteractiveCli(args)) {\n await runInteractiveCli({ mode: 'human' });\n return;\n }\n\n const program = createProgram();\n\n try {\n await program.parseAsync(argv);\n } catch (error) {\n printCliError(error, detectCliErrorFormat(argv));\n process.exit(exitCodeForError(error));\n }\n}\n", "#!/usr/bin/env node\nimport { runCli } from './runtime.js';\n\nvoid runCli();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["value", "existsSync", "mkdirSync", "readFileSync", "writeFileSync", "homedir", "dirname", "join", "KAMPUS_DIR", "UTF8_BOM", "selected", "teacher", "eta", "chalk", "chalk", "chalk", "chalk", "label", "chalk", "chalk", "lines", "matches", "instance", "accessBadge", "chalk", "formatSchool", "chalk", "accessBadge", "chalk", "render", "renderStatusLines", "compactDate", "chalk", "chalk", "label", "chalk", "chalk", "Box", "Text", "chalk", "label", "Box", "Text", "_jsx", "Box", "_jsxs", "Text", "renderSchoolLabel", "storedSchoolToSearchResult", "_jsx", "_jsxs", "Box", "Text", "readFileSync", "resolveSchool", "requireGradeClass", "readFileSync"]
|
|
7
|
+
}
|