Shaheer Sarfaraz 7514aa1b28
Add RxResume v4/v5 dual support (#230)
* feat(settings): add rxresume mode and v5 api key settings

* feat(server): add mode-aware rxresume adapter with auto v5-first selection

* refactor(server): route settings profile and pdf generation through rxresume adapter

* feat(api): support rxresume v4/v5 in onboarding and settings routes with ok/meta responses

* feat(client): add rxresume mode selector and v5 api key setup flow

* docs: document rxresume auto mode with v5-first self-hosted setup

* test: verify dual-mode rxresume support and ci parity checks

* comments

* services folder

* correct types for v5

* tests and docs fix

* Fix RxResume auto fallback and route API consistency

* warning for both being set

* simpler response

* onboarding component improvements, v5 check still not working

* fix list resume endpoint...

* fix api endpoints to latest v5 docs

* don't show the entire project field on v5

* remove auto entirely

* formatting

* ci green

* v5 has a different resume schema

* remove redundant check

* remove requirement that only one must be specified

* consolidate sections

* base resume can be v4 or v5

* saving now works

* status indicator

* actually render some pills

* reason for failure

* fix apikey verification

* dedupe isValidatingMode

* reefactoor

* simplification?

* refactor?

* ci passing

* remove auto from docs

* tailoring is schema dependent

* skills object tighter

* remove redundant text

* fix lint

* mode
2026-02-25 02:26:15 +00:00

65 lines
1.8 KiB
TypeScript

import type { SettingKey } from "@server/repositories/settings";
import { getSetting } from "@server/repositories/settings";
import type { RxResumeMode } from "@shared/types";
type BaseResumeIdSettings = Partial<
Record<
| "rxresumeMode"
| "rxresumeBaseResumeId"
| "rxresumeBaseResumeIdV4"
| "rxresumeBaseResumeIdV5",
string | null
>
>;
export function normalizeRxResumeMode(
raw: string | null | undefined,
): RxResumeMode {
return raw === "v4" ? "v4" : "v5";
}
export function getRxResumeBaseResumeIdKey(
mode: RxResumeMode,
): Extract<SettingKey, "rxresumeBaseResumeIdV4" | "rxresumeBaseResumeIdV5"> {
return mode === "v4" ? "rxresumeBaseResumeIdV4" : "rxresumeBaseResumeIdV5";
}
export function resolveRxResumeBaseResumeIdForMode(
settings: BaseResumeIdSettings,
explicitMode?: RxResumeMode,
): string | null {
const mode = explicitMode ?? normalizeRxResumeMode(settings.rxresumeMode);
const modeSpecific =
mode === "v4"
? settings.rxresumeBaseResumeIdV4
: settings.rxresumeBaseResumeIdV5;
return modeSpecific?.trim() || settings.rxresumeBaseResumeId?.trim() || null;
}
export async function getConfiguredRxResumeBaseResumeId(): Promise<{
mode: RxResumeMode;
resumeId: string | null;
}> {
const [modeRaw, legacyId, v4Id, v5Id] = await Promise.all([
getSetting("rxresumeMode"),
getSetting("rxresumeBaseResumeId"),
getSetting("rxresumeBaseResumeIdV4"),
getSetting("rxresumeBaseResumeIdV5"),
]);
const mode = normalizeRxResumeMode(
modeRaw ?? process.env.RXRESUME_MODE ?? null,
);
return {
mode,
resumeId: resolveRxResumeBaseResumeIdForMode(
{
rxresumeMode: modeRaw,
rxresumeBaseResumeId: legacyId,
rxresumeBaseResumeIdV4: v4Id,
rxresumeBaseResumeIdV5: v5Id,
},
mode,
),
};
}