The CV Service provides the main API for managing CV data in Firestore, including CRUD operations, version control, and backup management.
Overview
The service handles:
- CV data persistence to Firestore
- Version control with named snapshots
- Automatic backup creation and cleanup
- Resume list metadata with statistics
- Data validation and sanitization
Source: lib/cvService.ts:418
CV Data Operations
saveCV
Saves CV data to Firestore, creating or updating the user’s CV document.
async function saveCV(userId: string, data: CVData): Promise<void>
The unique identifier for the user
The complete CV data object to save
Behavior:
- Sanitizes data to replace undefined values (Firestore rejects undefined)
- Updates
updatedAt timestamp automatically
- Creates document with
createdAt if it doesn’t exist
- Validates data structure before saving
Example:
import { saveCV } from '@/lib/cvService';
import { CVData } from '@/lib/types';
const cvData: CVData = {
personalInfo: {
fullName: 'John Doe',
email: '[email protected]',
// ... other fields
},
experience: [],
education: [],
// ... other sections
};
await saveCV(userId, cvData);
loadCV
Loads CV data from Firestore with validation and sanitization.
async function loadCV(userId: string): Promise<CVData | null>
The unique identifier for the user
Returns validated CV data with defaults filled in, or null if document doesn’t exist or validation fails
Behavior:
- Validates loaded data using Zod schema
- Deep merges with initial values to ensure all fields are present
- Returns null if document doesn’t exist or data is invalid
- Logs warning if validation fails
Example:
const cvData = await loadCV(userId);
if (cvData) {
console.log('CV loaded:', cvData.personalInfo.fullName);
} else {
console.log('No CV found or invalid data');
}
deleteCV
Deletes a user’s CV document from Firestore.
async function deleteCV(userId: string): Promise<void>
The unique identifier for the user
Example:
await deleteCV(userId);
console.log('CV deleted successfully');
Version Control Operations
saveVersion
Saves a named version snapshot of the CV.
async function saveVersion(
userId: string,
data: CVData,
input: CVVersionInput,
isAutoSave: boolean = false
): Promise<string | null>
The unique identifier for the user
The CV data to save as a version
Version metadata including name, description, and tags
Whether this is an automatic backup version
Returns the version ID if successful, null on failure
CVVersionInput Interface:
interface CVVersionInput {
versionName: string;
description?: string;
tags?: string[];
}
Example:
const versionId = await saveVersion(
userId,
cvData,
{
versionName: 'Software Engineer Application',
description: 'Tailored for tech companies',
tags: ['tech', 'engineering']
}
);
if (versionId) {
console.log('Version saved:', versionId);
}
getVersions
Retrieves a paginated list of version metadata (without full CV data).
async function getVersions(
userId: string,
pageSize: number = 20,
lastDoc?: QueryDocumentSnapshot<DocumentData>
): Promise<{
versions: CVVersionMetadata[];
lastDoc: QueryDocumentSnapshot<DocumentData> | null;
}>
The unique identifier for the user
Number of versions to retrieve per page
Last document from previous page for pagination
Array of version metadata objects, sorted by creation date (newest first)
lastDoc
QueryDocumentSnapshot | null
Last document for pagination, null if no more pages
Example:
let lastDoc = null;
const allVersions = [];
do {
const { versions, lastDoc: nextDoc } = await getVersions(userId, 20, lastDoc);
allVersions.push(...versions);
lastDoc = nextDoc;
} while (lastDoc);
console.log(`Loaded ${allVersions.length} versions`);
getAllVersions
Retrieves all versions without pagination.
async function getAllVersions(userId: string): Promise<CVVersionMetadata[]>
The unique identifier for the user
Array of all version metadata objects
getVersion
Retrieves a specific version by ID, including full CV data.
async function getVersion(versionId: string): Promise<CVVersion | null>
The unique identifier for the version
Complete version object with full CV data, or null if not found
CVVersion Interface:
interface CVVersion {
id: string;
userId: string;
data: CVData;
versionName: string;
description?: string;
tags?: string[];
createdAt: Date;
isAutoSave: boolean;
}
Example:
const version = await getVersion(versionId);
if (version) {
console.log('Version:', version.versionName);
console.log('Created:', version.createdAt);
console.log('Data:', version.data);
}
restoreVersion
Restores CV to a specific version, creating an automatic backup first.
async function restoreVersion(userId: string, versionId: string): Promise<boolean>
The unique identifier for the user
The version ID to restore
Returns true if restore succeeded, false otherwise
Behavior:
- Fetches the version to restore
- Creates automatic backup of current CV data
- Restores the version data to main CV document
- Updates
currentVersionId field
Example:
const success = await restoreVersion(userId, versionId);
if (success) {
console.log('Version restored successfully');
} else {
console.error('Failed to restore version');
}
Error Handling:
- Returns false if version not found
- Returns false if backup creation fails
- Logs errors to console with
[cvService] prefix
deleteVersion
Deletes a specific version.
async function deleteVersion(versionId: string): Promise<boolean>
Returns true if deletion succeeded, false otherwise
Example:
const deleted = await deleteVersion(versionId);
console.log(deleted ? 'Deleted' : 'Failed');
Updates version metadata (name, description, tags) without changing the CV data.
async function updateVersionMetadata(
versionId: string,
metadata: Partial<Pick<CVVersionInput, "versionName" | "description" | "tags">>
): Promise<boolean>
metadata
Partial<CVVersionInput>
required
Partial metadata object with fields to update
Returns true if update succeeded, false otherwise
Example:
const updated = await updateVersionMetadata(versionId, {
versionName: 'Updated Version Name',
tags: ['updated', 'important']
});
searchVersions
Searches versions by name, description, or tags.
async function searchVersions(
userId: string,
searchTerm: string
): Promise<CVVersionMetadata[]>
The unique identifier for the user
Search term to match against name, description, or tags
Array of matching versions, limited to 200 results
Behavior:
- Case-insensitive search
- Matches against version name, description, and tags
- Returns up to 200 results
- Fetches all versions then filters (Firestore limitation)
Example:
const results = await searchVersions(userId, 'engineer');
console.log(`Found ${results.length} matching versions`);
Backup Operations
backupCV
Creates a backup of current CV data before overwriting.
async function backupCV(
userId: string,
reason: string = "manual_backup"
): Promise<boolean>
The unique identifier for the user
reason
string
default:"manual_backup"
Reason for creating the backup
Returns true if backup succeeded, false otherwise
Behavior:
- Creates backup with timestamp-based ID
- Automatically cleans up old backups (keeps last 5)
- Returns false if no CV data exists
- Sanitizes data before backup
Example:
const backed = await backupCV(userId, 'before_major_changes');
if (backed) {
// Safe to proceed with changes
await saveCV(userId, newData);
}
Resume List Operations
getResumeListItem
Retrieves resume metadata and statistics for display in resume lists.
async function getResumeListItem(userId: string): Promise<ResumeListItem | null>
The unique identifier for the user
Resume list item with metadata and stats, or null if not found
ResumeListItem Interface:
interface ResumeListItem {
userId: string;
createdAt: Date;
updatedAt: Date;
currentVersionId?: string;
fullName: string;
jobTitle: string;
versionCount: number;
lastVersionDate?: Date;
sectionCounts: {
experience: number;
education: number;
projects: number;
skills: number;
languages: number;
achievements: number;
};
}
Example:
const item = await getResumeListItem(userId);
if (item) {
console.log(`${item.fullName} - ${item.jobTitle}`);
console.log(`${item.versionCount} versions`);
console.log(`${item.sectionCounts.experience} experiences`);
}
Utility Functions
sanitizeCVDataForFirestore
Internal function that sanitizes CV data for Firestore by replacing undefined values.
function sanitizeCVDataForFirestore(data: CVData): CVData
Behavior:
- Replaces
undefined template with "default"
- Ensures all fields are Firestore-compatible
- Used automatically by all save operations
Constants
const MAX_BACKUPS = 5; // Maximum number of backups to keep
const VERSIONS_PAGE_SIZE = 20; // Default page size for version listing
Error Handling
All service functions include error handling:
- Errors are logged to console with
[cvService] prefix
- Functions return
null or false on failure instead of throwing
- Check return values to handle errors gracefully
Example:
try {
const data = await loadCV(userId);
if (!data) {
// Handle missing or invalid CV
console.log('No valid CV data found');
return;
}
// Process data
} catch (error) {
// Handle unexpected errors
console.error('Unexpected error:', error);
}