- Add per-listing notes (JobNotes component, notes column, auto-save) - Enforce hard score cap (≤15) when deal-breaker hits are present; add clearance/citizenship deal-breaker rules to scoring prompt - Cover letter prompt now uses full search profile (experience level, skills, work arrangement, location, salary, industries, deal-breakers) and produces longer, name-signed output - Include candidate name + location in sanitized scorer profile - Raise MAX_JOB_ACTION_BATCH_SIZE from 100 → 2500 (shared constant) - Update README with new features Made-with: Cursor
36 lines
917 B
TypeScript
36 lines
917 B
TypeScript
/**
|
|
* Database connection and initialization.
|
|
*/
|
|
|
|
import { existsSync, mkdirSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import Database from "better-sqlite3";
|
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
import { getDataDir } from "../config/dataDir";
|
|
// Apply schema migrations before any query runs (same DB path as below).
|
|
import "./migrate";
|
|
import * as schema from "./schema";
|
|
|
|
// Database path - can be overridden via env for Docker
|
|
const DB_PATH = join(getDataDir(), "jobs.db");
|
|
|
|
// Ensure data directory exists
|
|
const dataDir = dirname(DB_PATH);
|
|
if (!existsSync(dataDir)) {
|
|
mkdirSync(dataDir, { recursive: true });
|
|
}
|
|
|
|
const sqlite = new Database(DB_PATH);
|
|
sqlite.pragma("journal_mode = WAL");
|
|
let isClosed = false;
|
|
|
|
export const db = drizzle(sqlite, { schema });
|
|
|
|
export { schema };
|
|
|
|
export function closeDb() {
|
|
if (isClosed) return;
|
|
sqlite.close();
|
|
isClosed = true;
|
|
}
|