Skip to main content
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>
userId
string
required
The unique identifier for the user
data
CVData
required
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>
userId
string
required
The unique identifier for the user
return
CVData | null
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>
userId
string
required
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>
userId
string
required
The unique identifier for the user
data
CVData
required
The CV data to save as a version
input
CVVersionInput
required
Version metadata including name, description, and tags
isAutoSave
boolean
default:"false"
Whether this is an automatic backup version
return
string | null
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;
}>
userId
string
required
The unique identifier for the user
pageSize
number
default:"20"
Number of versions to retrieve per page
lastDoc
QueryDocumentSnapshot
Last document from previous page for pagination
versions
CVVersionMetadata[]
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[]>
userId
string
required
The unique identifier for the user
return
CVVersionMetadata[]
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>
versionId
string
required
The unique identifier for the version
return
CVVersion | null
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>
userId
string
required
The unique identifier for the user
versionId
string
required
The version ID to restore
return
boolean
Returns true if restore succeeded, false otherwise
Behavior:
  1. Fetches the version to restore
  2. Creates automatic backup of current CV data
  3. Restores the version data to main CV document
  4. 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>
versionId
string
required
The version ID to delete
return
boolean
Returns true if deletion succeeded, false otherwise
Example:
const deleted = await deleteVersion(versionId);
console.log(deleted ? 'Deleted' : 'Failed');

updateVersionMetadata

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>
versionId
string
required
The version ID to update
metadata
Partial<CVVersionInput>
required
Partial metadata object with fields to update
return
boolean
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[]>
userId
string
required
The unique identifier for the user
searchTerm
string
required
Search term to match against name, description, or tags
return
CVVersionMetadata[]
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>
userId
string
required
The unique identifier for the user
reason
string
default:"manual_backup"
Reason for creating the backup
return
boolean
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>
userId
string
required
The unique identifier for the user
return
ResumeListItem | null
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);
}

Build docs developers (and LLMs) love