feat(extractors): expand catalog, smoke coverage, and sourcing docs
CI / Linting (Biome) (push) Failing after 40s
CI / Tests (push) Successful in 5m54s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m11s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m8s
CI / Type Check (orchestrator) (push) Successful in 1m23s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m6s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m7s
CI / Documentation (push) Successful in 1m54s
CI / Linting (Biome) (push) Failing after 40s
CI / Tests (push) Successful in 5m54s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m11s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m8s
CI / Type Check (orchestrator) (push) Successful in 1m23s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m6s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m7s
CI / Documentation (push) Successful in 1m54s
Adds Arc.dev, BC T-Net, Eluta, iCIMS tenants, QAJobsBoard, and SmartRecruiters manifests with registry/settings/UI wiring; registers full extractor list in smoke-extractors and documents supplementary board access paths. Aligns Careerjet v4 with the url query parameter and fixes strict typing in QAJobsBoard. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -503,7 +503,9 @@ async function fetchApi<T>(
|
||||
): Promise<T> {
|
||||
const method = (options?.method || "GET").toUpperCase();
|
||||
const activeCreds = getActiveBasicAuthCredentials();
|
||||
let authHeader = activeCreds ? encodeBasicAuthHeaderValue(activeCreds) : undefined;
|
||||
let authHeader = activeCreds
|
||||
? encodeBasicAuthHeaderValue(activeCreds)
|
||||
: undefined;
|
||||
let authAttempt = 0;
|
||||
let usernameHint = activeCreds?.username;
|
||||
|
||||
|
||||
@@ -210,6 +210,11 @@ export const getEnabledSources = (
|
||||
const hasGreenhouseCompanies =
|
||||
(settings.greenhouseCompanies?.value ?? []).length > 0;
|
||||
const hasWorkdayTenants = (settings.workdayTenants?.value ?? []).length > 0;
|
||||
const hasSmartrecruitersCompanies =
|
||||
(settings.smartrecruitersCompanies?.value ?? []).length > 0;
|
||||
const hasElutaRssLocations =
|
||||
(settings.elutaRssLocations?.value ?? []).length > 0;
|
||||
const hasIcimsTenants = (settings.icimsTenants?.value ?? []).length > 0;
|
||||
|
||||
for (const source of orderedSources) {
|
||||
if (source === "gradcracker") {
|
||||
@@ -272,6 +277,22 @@ export const getEnabledSources = (
|
||||
if (hasWorkdayTenants) enabled.push(source);
|
||||
continue;
|
||||
}
|
||||
if (source === "smartrecruiters") {
|
||||
if (hasSmartrecruitersCompanies) enabled.push(source);
|
||||
continue;
|
||||
}
|
||||
if (source === "icims") {
|
||||
if (hasIcimsTenants) enabled.push(source);
|
||||
continue;
|
||||
}
|
||||
if (source === "bctenet") {
|
||||
enabled.push(source);
|
||||
continue;
|
||||
}
|
||||
if (source === "eluta") {
|
||||
if (hasElutaRssLocations) enabled.push(source);
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
source === "indeed" ||
|
||||
source === "linkedin" ||
|
||||
@@ -286,7 +307,9 @@ export const getEnabledSources = (
|
||||
source === "arbeitnow" ||
|
||||
source === "himalayas" ||
|
||||
source === "weworkremotely" ||
|
||||
source === "fourdayweek"
|
||||
source === "fourdayweek" ||
|
||||
source === "qajobsboard" ||
|
||||
source === "arcdev"
|
||||
) {
|
||||
enabled.push(source);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import { asyncRoute, fail, ok } from "@infra/http";
|
||||
import { logger } from "@infra/logger";
|
||||
import { getRequestId } from "@infra/request-context";
|
||||
import { isDemoMode, sendDemoBlocked } from "@server/config/demo";
|
||||
import { getJobOwnerProfileId } from "@server/infra/request-context";
|
||||
import { DEFAULT_JOB_OWNER_PROFILE_ID } from "@server/infra/job-owner-context";
|
||||
import { parseBasicAuthUsername } from "@server/infra/basic-auth-credentials";
|
||||
import { DEFAULT_JOB_OWNER_PROFILE_ID } from "@server/infra/job-owner-context";
|
||||
import { getJobOwnerProfileId } from "@server/infra/request-context";
|
||||
import * as profilesRepo from "@server/repositories/profiles";
|
||||
import { getSetting } from "@server/repositories/settings";
|
||||
import { setBackupSettings } from "@server/services/backup/index";
|
||||
@@ -30,11 +30,11 @@ import {
|
||||
} from "@server/services/rxresume";
|
||||
import { getEffectiveSettings } from "@server/services/settings";
|
||||
import { applySettingsUpdates } from "@server/services/settings-update";
|
||||
import { jobSearchProfileSchema } from "@shared/settings-registry";
|
||||
import {
|
||||
type UpdateSettingsInput,
|
||||
updateSettingsSchema,
|
||||
} from "@shared/settings-schema";
|
||||
import { jobSearchProfileSchema } from "@shared/settings-registry";
|
||||
import { type Request, type Response, Router } from "express";
|
||||
|
||||
export const settingsRouter = Router();
|
||||
@@ -251,9 +251,12 @@ settingsRouter.patch(
|
||||
) {
|
||||
const parsed = jobSearchProfileSchema.safeParse(input.jobSearchProfile);
|
||||
if (parsed.success) {
|
||||
const username = parseBasicAuthUsername(req.headers.authorization)?.trim();
|
||||
const dataWithOwner =
|
||||
username ? { ...parsed.data, basicAuthUser: username } : parsed.data;
|
||||
const username = parseBasicAuthUsername(
|
||||
req.headers.authorization,
|
||||
)?.trim();
|
||||
const dataWithOwner = username
|
||||
? { ...parsed.data, basicAuthUser: username }
|
||||
: parsed.data;
|
||||
await profilesRepo.updateProfile(ownerId, { data: dataWithOwner });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +272,12 @@ export const DEMO_SOURCE_BASE_URLS: Record<JobSource, string> = {
|
||||
lever: "https://jobs.lever.co",
|
||||
greenhouse: "https://boards.greenhouse.io",
|
||||
workday: "https://workday.com",
|
||||
smartrecruiters: "https://www.smartrecruiters.com",
|
||||
icims: "https://www.icims.com",
|
||||
bctenet: "https://www.bctechnology.com",
|
||||
eluta: "https://www.eluta.ca",
|
||||
qajobsboard: "https://www.qajobsboard.com",
|
||||
arcdev: "https://arc.dev",
|
||||
manual: "https://example.com",
|
||||
};
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ import {
|
||||
normalizeCountryKey,
|
||||
} from "@shared/location-support.js";
|
||||
import { resolveBlockedCompanyKeywordsFromStoredString } from "@shared/resolve-blocked-company-keywords.js";
|
||||
import { jobSearchProfileSchema } from "@shared/settings-registry.js";
|
||||
import {
|
||||
inferCountryKeyFromSearchGeography,
|
||||
matchesRequestedCity,
|
||||
resolveSearchCities,
|
||||
shouldApplyStrictCityFilter,
|
||||
} from "@shared/search-cities.js";
|
||||
import { jobSearchProfileSchema } from "@shared/settings-registry.js";
|
||||
import type { CreateJobInput, PipelineConfig } from "@shared/types";
|
||||
import { type CrawlSource, progressHelpers, updateProgress } from "../progress";
|
||||
|
||||
@@ -106,19 +106,14 @@ const ROLE_TOKEN_STOPWORDS = new Set([
|
||||
]);
|
||||
|
||||
function normalizeText(value: string | null | undefined): string {
|
||||
return (value ?? "")
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
return (value ?? "").toLowerCase().replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
function buildRoleMatchers(phrases: string[]): {
|
||||
phraseMatchers: string[];
|
||||
tokenMatchers: string[];
|
||||
} {
|
||||
const phraseMatchers = phrases
|
||||
.map((p) => normalizeText(p))
|
||||
.filter(Boolean);
|
||||
const phraseMatchers = phrases.map((p) => normalizeText(p)).filter(Boolean);
|
||||
|
||||
const tokenSet = new Set<string>();
|
||||
for (const phrase of phraseMatchers) {
|
||||
@@ -164,7 +159,10 @@ function filterJobsBySearchProfile(args: {
|
||||
const body = normalizeText(job.jobDescription);
|
||||
const haystack = `${title}\n${body}`;
|
||||
|
||||
if (dealBreakersLower.length > 0 && matchesAny(haystack, dealBreakersLower)) {
|
||||
if (
|
||||
dealBreakersLower.length > 0 &&
|
||||
matchesAny(haystack, dealBreakersLower)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user