Skip to content

feat: support string and file-URI attachments for React Native#78

Merged
bobbyg603 merged 4 commits into
masterfrom
feat/react-native-attachments
Apr 17, 2026
Merged

feat: support string and file-URI attachments for React Native#78
bobbyg603 merged 4 commits into
masterfrom
feat/react-native-attachments

Conversation

@bobbyg603
Copy link
Copy Markdown
Member

@bobbyg603 bobbyg603 commented Apr 17, 2026

Summary

  • Adds BugSplatFileRef ({ uri: string; type?: string }) to the BugSplatAttachment.data union so React Native consumers β€” @bugsplat/expo, bare RN β€” can upload files by URI (what expo-image-picker, react-native-view-shot, expo-screen-capture, etc. return). RN's fetch streams the file from disk at multipart-assembly time; no need to read it into JS memory.
  • Refactors the duplicated attachment loop in post() and postFeedback() into a single exported appendAttachment() helper that branches on the shape of data. No platform detection in the SDK β€” callers provide the shape their runtime expects.

Attachment data shapes

Type How it's appended
Blob body.append(filename, blob, filename) β€” multipart file part (browser)
Uint8Array Wrapped in a Blob first, then appended the same way (browser)
BugSplatFileRef ({ uri, type? }) RN's file shape β€” body.append(filename, { uri, type, name }, filename) β€” RN's fetch streams the URI

Usage

// Browser screenshot via <input type="file">
await client.postFeedback('Sidebar broken', {
  attachments: [{ filename: 'screenshot.png', data: fileFromInput }],
});

// React Native screenshot via react-native-view-shot / expo-image-picker
const uri = await captureRef(viewRef);
await client.postFeedback('Sidebar broken', {
  attachments: [{ filename: 'screenshot.png', data: { uri, type: 'image/png' } }],
});

Text attachments like a component stack are produced by the consumer in whatever shape their runtime needs (e.g. new Blob([text], { type: 'text/plain' }) on web, or a data:text/plain;base64,... URI inside a FileRef on RN). The SDK does not handle text specifically β€” see the paired change in bugsplat-react#21.

Test plan

  • npm test β€” 33 tests pass, including 4 new appendAttachment tests (Blob, Uint8Array, FileRef, FileRef without type)
  • npm run build β€” clean CJS + ESM
  • End-to-end verified via local tarball in @bugsplat/expo example app on an Android emulator (Pixel 7 API 35): `` catches a render error, client POSTs to BugSplat, server returns 200 with `crash_id`, and `componentStack.txt` shows up as a real file attachment in the BugSplat dashboard.

Ship sequence

After this merges + publishes as `9.1.0`:

  1. bugsplat-react#21 bumps `"bugsplat": "^9.1.0"` and publishes `2.1.0`.
  2. bugsplat-expo#13 bumps `"@bugsplat/react": "^2.1.0"` and publishes `0.5.0`.

πŸ€– Generated with Claude Code

Widens BugSplatAttachment.data to also accept:
- string β€” appended as-is, avoids needlessly wrapping text in a Blob
  (which React Native's FormData polyfill can't serialize).
- BugSplatFileRef ({ uri, type? }) β€” React Native's file-upload shape,
  used by expo-image-picker, react-native-view-shot, etc. Lets RN's
  fetch stream the file from disk instead of loading it into JS memory.

Refactors the duplicated attachment loop in post()/postFeedback() into
a single appendAttachment() helper that branches on the data shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 17, 2026 20:57
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the attachment API to support React Native-friendly attachment shapes and centralizes multipart attachment serialization so that post() and postFeedback() handle each runtime’s FormData capabilities correctly.

Changes:

  • Widen BugSplatAttachment.data to accept string and BugSplatFileRef ({ uri, type? }) in addition to Blob and Uint8Array.
  • Refactor attachment appending into a shared appendAttachment() helper used by both post() and postFeedback().
  • Add unit tests covering all appendAttachment() branches.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/index.ts Exports the new BugSplatFileRef type from the public entrypoint.
src/bugsplat.ts Adds appendAttachment() and replaces duplicated attachment append loops in post()/postFeedback().
src/bugsplat-options.ts Extends attachment type definitions and documents the supported attachment data shapes.
spec/bugsplat.spec.ts Adds focused tests for the new appendAttachment() helper behavior.

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/bugsplat.ts Outdated
Comment thread src/bugsplat.ts
bobbyg603 and others added 2 commits April 17, 2026 17:13
Appending a plain string to FormData with a filename arg still produces
a regular form field per spec β€” the filename is ignored and the server
never sees it as a file upload. That broke componentStack.txt: POSTs
succeeded but BugSplat didn't surface the attachment.

Wrap strings per platform so the multipart part gets a filename header:
- Browser: new Blob([data], { type: 'text/plain' }) + 3-arg append.
- React Native: encode as a base64 data URI inside the { uri, type, name }
  shape that RN's fetch uploads as a file. Avoids real Blob objects which
  RN's FormData polyfill can't serialize.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Callers that have text to upload (like bugsplat-react's componentStack)
should decide how to wrap it for their environment β€” Blob on web,
BugSplatFileRef with a data URI on React Native. Handling that inside
the SDK pulled in runtime-detection code for something only one consumer
actually cares about. Keeping the union to `Blob | Uint8Array | BugSplatFileRef`
leaves the SDK with one straight-line branch per shape and no platform
checks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds React Native–friendly attachment support by allowing attachments to be provided as file URIs, and centralizes multipart attachment appending logic in one helper.

Changes:

  • Extends BugSplatAttachment.data to support BugSplatFileRef ({ uri: string; type?: string }) for React Native file uploads.
  • Introduces appendAttachment() to handle Blob, Uint8Array, and BugSplatFileRef attachment shapes and refactors post() / postFeedback() to use it.
  • Adds unit tests covering the new attachment-appending behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/index.ts Re-exports the new BugSplatFileRef type from the public entrypoint.
src/bugsplat.ts Adds appendAttachment() helper and switches both posting methods to use it.
src/bugsplat-options.ts Defines BugSplatFileRef and widens BugSplatAttachment.data union to include it.
spec/bugsplat.spec.ts Adds tests for appendAttachment() across supported attachment shapes.

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/bugsplat.ts Outdated
Comment thread spec/bugsplat.spec.ts Outdated
Wrapping `data.buffer` uploaded the entire underlying ArrayBuffer even
when the Uint8Array was a subarray view (non-zero byteOffset or shorter
byteLength), which could corrupt the attachment or leak unrelated bytes
from the caller's buffer.

Pass the view itself to Blob so it uses the view's byteOffset and
byteLength. Adds a regression test that constructs a subarray view into
a larger buffer and asserts only the viewed bytes make it into the
uploaded Blob.

Also renames the file-ref test that said "omits type" but asserted
`type: undefined` β€” it handles a missing type, it doesn't omit the
field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bobbyg603 bobbyg603 merged commit 554ba41 into master Apr 17, 2026
7 checks passed
@bobbyg603 bobbyg603 deleted the feat/react-native-attachments branch April 17, 2026 22:16
Sign up for free to 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.

3 participants