Skip to content

refactor(audience-core): replace Transport interface with HttpSend + structured TransportResult#2839

Merged
ImmutableJeffrey merged 2 commits into
mainfrom
feat/audience-core-transport-refactor
Apr 9, 2026
Merged

refactor(audience-core): replace Transport interface with HttpSend + structured TransportResult#2839
ImmutableJeffrey merged 2 commits into
mainfrom
feat/audience-core-transport-refactor

Conversation

@ImmutableJeffrey
Copy link
Copy Markdown
Contributor

@ImmutableJeffrey ImmutableJeffrey commented Apr 9, 2026

Summary

Replaces the Transport interface in @imtbl/audience-core with an HttpSend function type and injects it into createConsentManager, so consent and queue both use the same transport mechanism. Removes the httpTransport wrapper, the batchSize() payload-shape leak in transport.ts, and the divergent test mocking strategies (consent.test.ts no longer needs jest.mock('./transport', …)).

httpSend now returns TransportResult ({ ok, error? }) instead of Promise<boolean>, with a typed TransportError carrying { status, endpoint, body, cause }. Both MessageQueue.flushUnload and ConsentManager's consent PUT remain fire-and-forget — the new HttpSend contract documents that implementations must not reject.

TransportError and TransportResult live in a new core/src/errors.ts module so types.ts stays focused on wire shapes.

Pure refactor. No behaviour change visible to studios.

Linear

  • SDK-84 — Audience SDK: collapse Transport interface to HttpSend, inject into ConsentManager

Test plan

  • pnpm --filter @imtbl/audience-core --filter @imtbl/audience --filter @imtbl/pixel test — all pass (112 core + 52 sdk + 68 pixel)
  • pnpm --filter @imtbl/audience-core --filter @imtbl/audience --filter @imtbl/pixel typecheck — clean
  • pnpm --filter @imtbl/audience-core --filter @imtbl/audience --filter @imtbl/pixel lint — clean
  • CI green

What's next

Two follow-up PRs build on this branch (separate Linear tickets to come):

  • feat(audience-core): unified AudienceError surface in core + fix partial-success silent drop
  • feat(audience+pixel): wire onError callback end-to-end through web SDK and pixel

🤖 Generated with Claude Code

…structured TransportResult

The Transport interface had one production implementation (httpTransport)
and was being bypassed anyway: ConsentManager imported httpSend directly
instead of going through the injected transport. Tests had to mock at
two different levels (jest.fn for queue, jest.mock for consent).

Collapse the abstraction:
- Delete Transport interface and httpTransport wrapper.
- Export type HttpSend = typeof httpSend so tests can mock by injection.
- MessageQueue takes a send: HttpSend constructor parameter.
- createConsentManager takes a send: HttpSend parameter (new second arg)
  and stops importing httpSend directly. Same instance flows to both,
  so the transport layer is finally uniform.
- httpSend returns TransportResult { ok, error? } instead of boolean.
  TransportError carries { status, endpoint, body, cause } for both
  HTTP failures and network failures.
- New errors.ts module hosts TransportError + TransportResult to keep
  types.ts focused on wire shapes.
- Removes the batchSize() helper / payload-shape inspection that lived
  in transport.ts. The transport no longer cares what it's sending.

Behaviour is unchanged: queue still drops messages on result.ok, still
retries on failure, still flushes via keepalive on page unload. The
HttpSend contract is documented as never-rejects so floating promises
in flushUnload and notifyBackend are safe.

Test mocks updated to match. The old jest.mock('./transport') in
consent.test.ts is gone — fakes are passed by injection now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ImmutableJeffrey ImmutableJeffrey requested a review from a team as a code owner April 9, 2026 01:52
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Apr 9, 2026

View your CI Pipeline Execution ↗ for commit 518db0e

Command Status Duration Result
nx affected -t build,lint,test ✅ Succeeded 14s View ↗
nx run-many -p @imtbl/sdk,@imtbl/checkout-widge... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-09 03:43:42 UTC

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

✅ Pixel Bundle Size — @imtbl/pixel

Metric Size Delta vs main
Gzipped 4383 bytes (4.28 KB) +220 bytes
Raw (minified) 11790 bytes +567 bytes

Budget: 10.00 KB gzipped (warn at 8.00 KB)

Comment thread packages/audience/core/src/errors.ts Outdated
Addresses review feedback (bkbooth): stack traces were lost because
TransportError was a plain interface. Instances now carry a native
stack and integrate with devtools / Sentry / @imtbl/metrics without
custom wrapping.

- Convert TransportError from interface to class extends Error.
- Use ES2022 Error.cause via super(msg, { cause }) — the existing
  .cause field comes for free, source-compatible with consumers.
- status / endpoint / body become readonly class fields; name and
  message set so default stringification is useful.
- Two construction sites in transport.ts switch to new TransportError.
- Collapse the causeError workaround in the catch branch: the
  TransportError IS an Error, so trackError consumes it directly and
  the original error is preserved via cause chaining.

Tests: transport.test.ts uses toMatchObject + toBeInstanceOf and adds
a lock-in test for the Error contract (instanceof Error, name, stack).
queue.test.ts fail fixture constructs via new TransportError({...}).

No behaviour change visible to studios — field access on error.status /
endpoint / body / cause is identical (cause is native Error.cause,
accessed the same way).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ImmutableJeffrey ImmutableJeffrey added this pull request to the merge queue Apr 9, 2026
Merged via the queue into main with commit 01a67ef Apr 9, 2026
8 checks passed
@ImmutableJeffrey ImmutableJeffrey deleted the feat/audience-core-transport-refactor branch April 9, 2026 03:56
ImmutableJeffrey added a commit that referenced this pull request Apr 9, 2026
The squash merge of PR #2839 changed TransportError from an interface
to a class extending Error. Update test fixtures and the partial-success
detection in httpSend to use `new TransportError(...)` instead of plain
object literals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ImmutableJeffrey added a commit that referenced this pull request Apr 9, 2026
The squash merge of PR #2839 changed TransportError from an interface
to a class extending Error. Update test fixtures and the partial-success
detection in httpSend to use `new TransportError(...)` instead of plain
object literals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants