Skip to content

CLI-credential auth resolution + fixes (nodenext types, Bun compat, snapshot status) - #29

Merged
artemo-brd merged 6 commits into
brightdata:devfrom
karaposu:dev
Jul 30, 2026
Merged

CLI-credential auth resolution + fixes (nodenext types, Bun compat, snapshot status)#29
artemo-brd merged 6 commits into
brightdata:devfrom
karaposu:dev

Conversation

@karaposu

@karaposukaraposu commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

One feature and three fixes, all on top of the crawler work already on dev (#25).

Feature

  • feat(auth): resolve the API token from the CLI credential store + report the auth source in the User-Agent.new bdclient() now works with zero configuration on a machine where the user has run brightdata login. Resolution precedence: apiKey param → env (BRIGHTDATA_API_TOKEN / BRIGHTDATA_API_KEY) → CLI credentials store → actionable AuthenticationError. The resolved source is appended to the User-Agent as brightdata-sdk-js/<version> (auth=<param|env|cli_credentials>) so SDK onboarding is measurable. The credential path mirrors the CLI exactly (Windows homedir()/AppData/Roaming — not %APPDATA%, macOS ~/Library/Application Support, Linux ~/.config — no XDG); only credentials.json is read (never config.json), and the token is never logged or placed in the User-Agent.

Fixes

  • fix(types): author .js on relative imports so shipped .d.ts resolve under node16/nodenext (was TS2834 / silent any); adds a build-time smoke over the built ESM/CJS output.
  • fix(bun) (bdclient constructor throws under Bun runtime: 'dns is not a function' #24): capability-detect undici interceptors — Bun (omits dns) no longer crashes the Transport constructor; Node unchanged.
  • fix(polling): accept unknown snapshot statuses (e.g. starting) so the poll loop doesn't throw mid-run.

Verification

  • sanity (lint + typecheck), build + built-package smoke (all 4 entries load in ESM and CJS): clean
  • 372/372 unit tests
  • nodenext fix verified in a real consumer on both import and require; auth resolution tested across all three platform paths, precedence, empty-env fallthrough, malformed/missing credentials, the no-credentials error, and the composed User-Agent — fully isolated from the real machine's env + credential store.

SnapshotStatusResponseSchema validated the /datasets/v3/progress status
field against a fixed list (running|ready|failed|cancelled|error). The
API owns this vocabulary and emits values the SDK had not enumerated
(e.g. "starting"), so Zod validation threw and killed the polling loop —
affecting every async platform scraper.
Validate the status field by shape (a non-empty string) instead of
membership. pollUntilReady already acts only on terminal states, so
unknown lifecycle values flow through and polling continues; malformed
responses are still rejected.
Also fix an adjacent bug in the same path: "cancelled" was not treated
as terminal, so a cancelled snapshot polled until timeout instead of
stopping.
Adds regression tests for unknown/empty/non-string status and for the
cancelled terminal case.
…ta#24)
Bun's bundled undici omits the optional `dns` interceptor, so composing the dispatcher chain called `dns()` and threw "dns is not a function", crashing the Transport constructor at client init on Bun.
Detect each interceptor by capability (typeof === 'function') and compose only those the runtime provides. On Node this is unchanged (dns + retry present); on Bun `dns` is skipped (undici falls back to the platform resolver, requests still work), and it self-retires if Bun later ships dns.
…resolution
Shipped declarations used extensionless relative imports (e.g. `export { bdclient } from './client'`), which node16/nodenext resolution rejects (TS2834), silently degrading the SDK's public types to `any` for consumers on those modes. They resolved only under moduleResolution:bundler — the mode the declaration build itself used.
Author explicit `.js` on every relative specifier in src/ (551 across 184 files) so tsc emits nodenext-resolvable .d.ts under the existing build; `.js` still resolves to `.ts` under bundler and rollup, so the JS bundle and typecheck are unchanged.
Add scripts/smoke-dist.mjs (wired into `build`): it loads all four entry points in both ESM and CJS from the built dist/ and constructs the client, so a broken emitted specifier fails the build instead of shipping. scripts/add-js-extensions.mjs is the AST codemod that applied the change.
Verified in a nodenext consumer project (skipLibCheck:false): no TS2834, and real types resolve on both the import and require paths.
…user-agent
Adds a third token source so `new bdclient()` works with zero config on a machine where the user has run `brightdata login`. Resolution precedence: apiKey param → env (BRIGHTDATA_API_TOKEN / BRIGHTDATA_API_KEY) → CLI credentials store → actionable AuthenticationError.
The resolved source (param / env / cli_credentials) is appended to the User-Agent as `brightdata-sdk-js/<version> (auth=<source>)` so SDK onboarding is measurable.
src/utils/cli-credentials.ts is a read-only reader whose per-platform path mirrors the CLI exactly (bd-cli get_config_dir): Windows homedir()/AppData/Roaming (not %APPDATA%), macOS ~/Library/Application Support, Linux ~/.config (no XDG). Only credentials.json is read; config.json is never touched, and the token is never logged or put in the user-agent.
Tests: per-platform paths, precedence, empty-env fallthrough, malformed/missing/empty credentials, no-credentials error, and the composed user-agent — isolated from the real machine's env + credential store.
@karaposukaraposu changed the title Fixes: nodenext type resolution, Bun compatibility, snapshot status pollingCLI-credential auth resolution + fixes (nodenext types, Bun compat, snapshot status)Jul 29, 2026
…ring
SnapshotStatusResponseSchema validates status as a non-empty string (not an
enum) since the API can add lifecycle values without an SDK release. The
derived public type followed suit and widened to plain string, losing
editor autocomplete/exhaustiveness hints for the values we do know about.
Type it as KnownSnapshotStatus | (string & {}) instead: same runtime
behavior, but IDEs still surface running/ready/failed/cancelled/error while
still accepting any other value the API may return.
It already did its job (all relative specifiers under src/ carry explicit
.js extensions now) and isn't wired into build/test/CI, so it was dead
weight in the tree. Keeping it around risked someone re-running it against
a codebase it was never re-validated for.
If we want to keep enforcing explicit extensions on new files going
forward, that's better done with an ESLint rule (e.g. import/extensions)
than an ad-hoc script someone has to remember to run.
@artemo-brd
artemo-brd merged commit 9d019f2 into brightdata:devJul 30, 2026
3 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@karaposu@artemo-brd