* clean up helpers * shared in it's own top level folder * workspaces setup * build fix * disable workspaces? * run ci * rename job-flow to gradcracker * optional dependencies * formatting? * more optional modules * allow post install runs * node bump * remove post install * add optionals * add more * formatting * comments, but im unsure * run typescript DIRECTLY * better build * camoufox simplification * lint * build process doesn't exist * build fix * lockfile * type check everything, build only for client * rename steps correctly * import from package! * fix formatting * don't fetch twice * fix concern
82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
/**
|
|
* Profile service - fetches resume data from RxResume v4 API.
|
|
*
|
|
* The rxresumeBaseResumeId setting is REQUIRED for the app to function.
|
|
* There is no local file fallback.
|
|
*/
|
|
|
|
import type { ResumeProfile } from "@shared/types";
|
|
import { getSetting } from "../repositories/settings";
|
|
import { getResume, RxResumeCredentialsError } from "./rxresume-v4";
|
|
|
|
let cachedProfile: ResumeProfile | null = null;
|
|
let cachedResumeId: string | null = null;
|
|
|
|
/**
|
|
* Get the base resume profile from RxResume v4 API.
|
|
*
|
|
* Requires rxresumeBaseResumeId to be configured in settings.
|
|
* Results are cached until clearProfileCache() is called.
|
|
*
|
|
* @param forceRefresh Force reload from API.
|
|
* @throws Error if rxresumeBaseResumeId is not configured or API call fails.
|
|
*/
|
|
export async function getProfile(forceRefresh = false): Promise<ResumeProfile> {
|
|
const rxresumeBaseResumeId = await getSetting("rxresumeBaseResumeId");
|
|
|
|
if (!rxresumeBaseResumeId) {
|
|
throw new Error(
|
|
"Base resume not configured. Please select a base resume from your RxResume account in Settings.",
|
|
);
|
|
}
|
|
|
|
// Return cached profile if valid
|
|
if (
|
|
cachedProfile &&
|
|
cachedResumeId === rxresumeBaseResumeId &&
|
|
!forceRefresh
|
|
) {
|
|
return cachedProfile;
|
|
}
|
|
|
|
try {
|
|
console.log(
|
|
`📋 Fetching profile from RxResume v4 API (resume: ${rxresumeBaseResumeId})...`,
|
|
);
|
|
const resume = await getResume(rxresumeBaseResumeId);
|
|
|
|
if (!resume.data || typeof resume.data !== "object") {
|
|
throw new Error("Resume data is empty or invalid");
|
|
}
|
|
|
|
cachedProfile = resume.data as unknown as ResumeProfile;
|
|
cachedResumeId = rxresumeBaseResumeId;
|
|
console.log(`✅ Profile loaded from RxResume v4 API`);
|
|
return cachedProfile;
|
|
} catch (error) {
|
|
if (error instanceof RxResumeCredentialsError) {
|
|
throw new Error(
|
|
"RxResume credentials not configured. Set RXRESUME_EMAIL and RXRESUME_PASSWORD in settings.",
|
|
);
|
|
}
|
|
console.error(`❌ Failed to load profile from RxResume v4 API:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the person's name from the profile.
|
|
*/
|
|
export async function getPersonName(): Promise<string> {
|
|
const profile = await getProfile();
|
|
return profile?.basics?.name || "Resume";
|
|
}
|
|
|
|
/**
|
|
* Clear the profile cache.
|
|
*/
|
|
export function clearProfileCache(): void {
|
|
cachedProfile = null;
|
|
cachedResumeId = null;
|
|
}
|