Shaheer Sarfaraz 82e142a8a8
Auto-Registering Extractor System (#223)
* initial commit?

* Address PR feedback on extractor discovery and startup resilience

* Address latest PR review comments

* fix city resolution fallback when input parses empty

* address PR feedback on extractor registry and pipeline validation

* address copilot comments on manifests and registry startup

* fix extractor discovery export handling and env isolation in tests

* enforce duplicate manifest id failures in strict mode

* Fix remaining extractor registry and runtime review comments

* docs

* docs

* test all, logic remains in extractors

* Address PR review feedback on extractor registry and validation

* Revert extractor moduleResolution to bundler

* Enforce shared city filtering across all discovery sources

* Deduplicate extractor strict city post-filtering
2026-02-21 17:44:07 +00:00

128 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Express server entry point.
*/
import "./config/env";
import { logger } from "@infra/logger";
import { sanitizeUnknown } from "@infra/sanitize";
import { createApp } from "./app";
import { initializeExtractorRegistry } from "./extractors/registry";
import * as settingsRepo from "./repositories/settings";
import {
getBackupSettings,
setBackupSettings,
startBackupScheduler,
} from "./services/backup/index";
import { initializeDemoModeServices } from "./services/demo-mode";
import { applyStoredEnvOverrides } from "./services/envSettings";
import { initialize as initializeVisaSponsors } from "./services/visa-sponsors/index";
async function startServer() {
await applyStoredEnvOverrides();
try {
await initializeExtractorRegistry();
} catch (error) {
const sanitizedError = sanitizeUnknown(error);
logger.error("Failed to initialize extractor registry", {
error: sanitizedError,
});
if (process.env.NODE_ENV === "production") {
logger.error(
"Extractor registry initialization failed in production. Shutting down server.",
);
process.exit(1);
}
logger.error(
"Extractor registry initialization failed outside production. Server startup aborted.",
);
return;
}
const app = createApp();
const PORT = process.env.PORT || 3001;
// Start server
app.listen(PORT, async () => {
console.log(`
╔═══════════════════════════════════════════════════════════╗
║ ║
║ 🚀 Job Ops Orchestrator ║
║ ║
║ Server running at: http://localhost:${PORT}
║ ║
║ API: http://localhost:${PORT}/api ║
║ Health: http://localhost:${PORT}/health ║
║ PDFs: http://localhost:${PORT}/pdfs ║
║ ║
╚═══════════════════════════════════════════════════════════╝
`);
// Initialize visa sponsors service (downloads data if needed, starts scheduler)
try {
if (process.env.DEMO_MODE === "true") {
console.log(
" Demo mode enabled. Skipping visa sponsors initialization.",
);
} else {
await initializeVisaSponsors();
}
} catch (error) {
logger.warn("Failed to initialize visa sponsors service", {
error: sanitizeUnknown(error),
});
}
// Initialize backup service (load settings and start scheduler if enabled)
try {
const backupEnabled = await settingsRepo.getSetting("backupEnabled");
const backupHour = await settingsRepo.getSetting("backupHour");
const backupMaxCount = await settingsRepo.getSetting("backupMaxCount");
const parsedHour = backupHour ? parseInt(backupHour, 10) : NaN;
const parsedMaxCount = backupMaxCount
? parseInt(backupMaxCount, 10)
: NaN;
const safeHour = Number.isNaN(parsedHour)
? 2
: Math.min(23, Math.max(0, parsedHour));
const safeMaxCount = Number.isNaN(parsedMaxCount)
? 5
: Math.min(5, Math.max(1, parsedMaxCount));
setBackupSettings({
enabled: backupEnabled === "true" || backupEnabled === "1",
hour: safeHour,
maxCount: safeMaxCount,
});
startBackupScheduler();
const settings = getBackupSettings();
if (settings.enabled) {
console.log(
`✅ Backup scheduler started (hour: ${settings.hour}, max: ${settings.maxCount})`,
);
} else {
console.log(
" Backups disabled. Enable in settings to schedule automatic backups.",
);
}
} catch (error) {
logger.warn("Failed to initialize backup service", {
error: sanitizeUnknown(error),
});
}
try {
await initializeDemoModeServices();
} catch (error) {
logger.warn("Failed to initialize demo mode services", {
error: sanitizeUnknown(error),
});
}
});
}
void startServer();