fix(jobnet-search): emit source: search-fallback on stdout for external ads (#549) (#550)

* fix(jobnet-search): emit source: search-fallback on stdout for external ads (#549)

Move the degraded search summary signal from stderr to stdout as a source: search-fallback field on DetailApiResponse. Keeps stderr quiet on success across all portal CLIs, renders the degraded signal in plain and table format outputs, documents the optional field in the CLI README, and covers the fallback execution path with tests.

* changelog: place the #550 entry under [Unreleased]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-10-20 20:59:12 +02:00
1 parent 9a53f5e05b
commit 2b4097177a
5 files changed
+324 -5

No files matched your search

@@ -17,6 +17,7 @@ export interface DetailApiResponse {
hasLogo: boolean
logoUrl: string | null
isExternal?: boolean
source?: string
employer: {
cvrNumber: string | null
pNumber: string | null
@@ -81,6 +82,7 @@ export function mapSearchAdToDetail(raw: JobAdRaw & { jobAdUrl?: string | null;
hasLogo: Boolean(raw.hasLogo),
logoUrl: raw.logoUrl ?? null,
isExternal: true,
source: "search-fallback",
employer: {
cvrNumber: raw.cvr ?? null,
pNumber: null,
@@ -184,7 +186,6 @@ export const detail = defineCommand({
})
const match = searchResult.jobAds?.find((ad) => ad.jobAdId === id)
if (match) {
process.stderr.write("note: detail endpoint returned 404; retrieved external posting summary from search endpoint\n")
data = prepareDetail(mapSearchAdToDetail(match))
}
} catch {
@@ -217,6 +218,9 @@ function outputTable(data: DetailApiResponse): void {
console.log(`ID: ${data.id}`)
console.log(`Title: ${data.title}`)
console.log(`Employer: ${data.employer.name}`)
if (data.source) {
console.log(`Source: ${data.source} (detail unavailable, synthesised from search)`)
}
console.log(`Type: ${data.job.type ?? "-"}`)
console.log(`City: ${data.job.address.city ?? "-"}`)
console.log(`Postal: ${data.job.address.postalCode ?? "-"}`)
@@ -241,6 +245,10 @@ export function formatDetailPlain(data: DetailApiResponse): string {
`Positions: ${data.application.availablePositions ?? "-"}`,
]
if (data.source) {
lines.push(`Source: ${data.source} (detail unavailable, synthesised from search)`)
}
if (data.application.url) {
lines.push(`Apply: ${data.application.url}`)
}