mirror of
https://github.com/jackwener/OpenCLI.git
synced 2026-09-14 18:25:42 +08:00
69ee36f997
* fix(linkedin): surface detail_error on --details (no silent catch / no silent empty)
The previous --details enrichment path had two indistinguishable failure modes
that both produced `description: '', apply_url: ''`:
1. `if (!job.url)` early return — row had no jobId, so we couldn't navigate.
2. `} catch {}` — page.goto / page.evaluate threw (network, timeout, parse error).
Callers couldn't tell "upstream had no description" from "we failed to fetch",
and the catch swallowed every error without logging. For an enrichment that
costs one page navigation per row, silent failure is especially harmful — users
just see an empty cell with no way to debug.
Fix: replace empty strings with `null` for missing/failed rows, add a new
`detail_error` column (string|null) carrying a short typed reason:
- 'no url' — row had no jobId
- 'fetch failed: <msg>' — page.goto / page.evaluate threw
- 'missing description' — page loaded but body was empty
- null — success
Every failure is also logged to stderr with the offending URL so debugging is
possible. Per-row failures still don't abort the batch (the original intent),
but they're now visible.
Tests: 13 new contract assertions in clis/linkedin/search.test.js covering
parseCsvArg, mapFilterValues (ArgumentError on unknown values), decodeLinkedinRedirect,
and 5 enrichJobDetails paths (no-url / goto-throw / empty-description / success /
multi-row-mixed). Added `export const __test__` for testability.
Audits clean: typed-error-lint 196/196, silent-column-drop 103/103.
* fix(linkedin): fail fast on auth walls
2.1 KiB
2.1 KiB
Mode: 🔐 Browser · Domain: linkedin.com
Commands
| Command | Description |
|---|---|
opencli linkedin search |
Search LinkedIn jobs (Voyager API), with optional --details enrichment |
opencli linkedin timeline |
Read posts from your LinkedIn home feed |
Usage Examples
# Quick start
opencli linkedin search --limit 5
# Search with filters
opencli linkedin search "site reliability engineer" --location "San Francisco Bay Area" --remote remote
# Enrich with full description and apply URL (slower; 1 page navigation per row)
opencli linkedin search "data scientist" --limit 3 --details
# Read your home timeline
opencli linkedin timeline --limit 5
# JSON output
opencli linkedin search -f json
opencli linkedin timeline -f json
Output
search
Always returns: rank · title · company · location · listed · salary · url
When --details is set, each row additionally has:
| Column | Type | Notes |
|---|---|---|
description |
string | null | Full "About the job" body. null if upstream had nothing or fetch failed (see detail_error). |
apply_url |
string | null | First apply-labelled link on the page. null if upstream had nothing or fetch failed. |
detail_error |
string | null | null on success. Otherwise short reason: 'no url' (row had no jobId), 'fetch failed: <message>' (navigation/parse threw), or 'missing description' (page loaded but body was empty). |
Previously the adapter returned description: '', apply_url: '' for both the missing-url path and the silent-catch path — callers couldn't tell upstream gaps apart from fetch failures. The current shape preserves backward compatibility on success and surfaces failures with null + a typed reason on detail_error. Per-row failures still don't abort the batch.
--limit must be between 1 and 100, and --start must be a non-negative integer. LinkedIn login/auth walls abort with AuthRequiredError instead of being folded into detail_error.
Prerequisites
- Chrome running and logged into linkedin.com
- Browser Bridge extension installed