Skip to content

Commit 16c6a3b

Browse files
committed
chore(dependencies): update websocket-driver to version 0.7.5 to fix vulnerability audit
This commit updates the websocket-driver dependency to version 0.7.5 in both pnpm-lock.yaml and pnpm-workspace.yaml to address security advisories. Additionally, the README.md for attachments-storage-react-native has been enhanced to clarify the functionality of local storage and streaming transport adapters, including usage examples and API details.
1 parent 690bdac commit 16c6a3b

3 files changed

Lines changed: 162 additions & 51 deletions

File tree

packages/attachments-storage-react-native/README.md

Lines changed: 118 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
>
66
> Do not rely on this package for production use.
77
8-
React Native file system storage adapters for [PowerSync](https://powersync.com) attachments.
8+
React Native storage and transport adapters for [PowerSync](https://powersync.com) attachments.
99

10-
This package provides `LocalStorageAdapter` implementations for React Native environments, allowing you to store and retrieve attachment files on device.
10+
This package provides:
11+
12+
- **Local storage adapters** (`LocalStorageAdapter`) — persist attachment files on device.
13+
- **Streaming transport adapters** (`AttachmentTransportAdapter`) — move attachment bytes directly between the local file and remote storage using native APIs, without buffering the whole file in JS memory. Recommended for large files (recordings, videos) on lower-end devices.
1114

1215
## Installation
1316

@@ -19,7 +22,7 @@ pnpm add @powersync/attachments-storage-react-native
1922
yarn add @powersync/attachments-storage-react-native
2023
```
2124

22-
You'll also need to install one of the supported file system libraries:
25+
You'll also need to install one of the supported file system libraries. The same library powers both the local storage adapter and the native transport adapter for that platform.
2326

2427
### For Expo projects
2528

@@ -36,20 +39,23 @@ npx expo install expo-file-system
3639
npm install @dr.pogodin/react-native-fs
3740
```
3841

39-
## Usage
42+
## Local storage adapters
43+
44+
The local storage adapter handles file persistence on the device. Pass it to the queue as `localStorage`.
4045

4146
### With Expo File System
4247

4348
```typescript
4449
import { ExpoFileSystemStorageAdapter } from '@powersync/attachments-storage-react-native';
4550
import { AttachmentQueue } from '@powersync/react-native';
4651

47-
const storageAdapter = new ExpoFileSystemStorageAdapter();
52+
const localStorage = new ExpoFileSystemStorageAdapter();
4853

4954
const attachmentQueue = new AttachmentQueue({
50-
powersync: db,
51-
storage: cloudStorage,
52-
storageAdapter
55+
db,
56+
localStorage,
57+
remoteStorage, // your RemoteStorageAdapter (buffered upload/download/delete)
58+
watchAttachments
5359
});
5460
```
5561

@@ -59,43 +65,135 @@ const attachmentQueue = new AttachmentQueue({
5965
import { ReactNativeFileSystemStorageAdapter } from '@powersync/attachments-storage-react-native';
6066
import { AttachmentQueue } from '@powersync/react-native';
6167

62-
const storageAdapter = new ReactNativeFileSystemStorageAdapter();
68+
const localStorage = new ReactNativeFileSystemStorageAdapter();
6369

6470
const attachmentQueue = new AttachmentQueue({
65-
powersync: db,
66-
storage: cloudStorage,
67-
storageAdapter
71+
db,
72+
localStorage,
73+
remoteStorage,
74+
watchAttachments
6875
});
6976
```
7077

71-
### Custom Storage Directory
78+
### Custom storage directory
79+
80+
Both local adapters accept an optional `storageDirectory` parameter:
81+
82+
```typescript
83+
const localStorage = new ExpoFileSystemStorageAdapter('/custom/path/to/attachments/');
84+
```
85+
86+
## Streaming transport adapters
87+
88+
A transport adapter owns **all** remote operations (`upload` / `download` / `delete`) and transfers bytes natively — the file never enters the JS heap. When a `transportAdapter` is provided it fully replaces `remoteStorage` (which is no longer required); implement remote delete via the `deleteFile` callback.
7289

73-
Both adapters accept an optional `storageDirectory` parameter:
90+
Both transports are backend-agnostic: you supply resolver callbacks that map an attachment to a request (typically a presigned URL from your backend).
91+
92+
### With Expo File System (`uploadAsync` / `downloadAsync`)
7493

7594
```typescript
76-
const storageAdapter = new ExpoFileSystemStorageAdapter('/custom/path/to/attachments/');
95+
import {
96+
ExpoFileSystemStorageAdapter,
97+
ExpoFileSystemTransportAdapter
98+
} from '@powersync/attachments-storage-react-native';
99+
import { AttachmentQueue } from '@powersync/react-native';
100+
101+
const localStorage = new ExpoFileSystemStorageAdapter();
102+
103+
const transportAdapter = new ExpoFileSystemTransportAdapter({
104+
resolveUpload: async (attachment) => ({
105+
url: await getSignedUploadUrl(attachment.filename), // from your backend
106+
httpMethod: 'PUT',
107+
mimeType: attachment.mediaType ?? 'application/octet-stream'
108+
}),
109+
resolveDownload: async (attachment) => ({
110+
url: await getSignedDownloadUrl(attachment.filename)
111+
}),
112+
deleteFile: async (attachment) => {
113+
await deleteFromRemoteStorage(attachment.filename); // your SDK / DELETE call
114+
}
115+
});
116+
117+
const attachmentQueue = new AttachmentQueue({
118+
db,
119+
localStorage,
120+
transportAdapter, // owns upload/download/delete — no remoteStorage needed
121+
watchAttachments
122+
});
123+
```
124+
125+
### With React Native FS (`uploadFiles` / `downloadFile`)
126+
127+
Identical options shape. The upload is sent as a raw binary `PUT` (`binaryStreamOnly`), suitable for presigned S3/Supabase URLs.
128+
129+
```typescript
130+
import {
131+
ReactNativeFileSystemStorageAdapter,
132+
ReactNativeFSTransportAdapter
133+
} from '@powersync/attachments-storage-react-native';
134+
135+
const localStorage = new ReactNativeFileSystemStorageAdapter();
136+
137+
const transportAdapter = new ReactNativeFSTransportAdapter({
138+
resolveUpload: async (attachment) => ({
139+
url: await getSignedUploadUrl(attachment.filename),
140+
httpMethod: 'PUT',
141+
mimeType: attachment.mediaType ?? 'application/octet-stream'
142+
}),
143+
resolveDownload: async (attachment) => ({
144+
url: await getSignedDownloadUrl(attachment.filename)
145+
}),
146+
deleteFile: async (attachment) => {
147+
await deleteFromRemoteStorage(attachment.filename);
148+
}
149+
});
150+
```
151+
152+
## Registering an on-disk file (buffer-free)
153+
154+
For files already written to disk (recordings, camera/picker output), use `AttachmentQueue.saveFileFromUri` to register them without reading the bytes into memory — the local adapter's `moveFile` relocates the file into managed storage.
155+
156+
```typescript
157+
await attachmentQueue.saveFileFromUri({
158+
localUri, // path to the existing file
159+
fileExtension: 'm4a',
160+
mediaType: 'audio/m4a'
161+
});
77162
```
78163

79164
## API
80165

81-
Both adapters implement the `LocalStorageAdapter` interface from `@powersync/common`:
166+
### Local storage adapters
167+
168+
Implement the `LocalStorageAdapter` interface from `@powersync/common`:
82169

83170
- `initialize()` - Create the storage directory if it doesn't exist
84171
- `clear()` - Remove all files from the storage directory
85172
- `getLocalUri(filename)` - Get the full path for a filename
86173
- `saveFile(filePath, data, options?)` - Save data to a file
87174
- `readFile(filePath, options?)` - Read a file as ArrayBuffer
175+
- `moveFile(sourceUri, targetUri)` - Move a file into managed storage without buffering (enables `saveFileFromUri`)
88176
- `deleteFile(filePath)` - Delete a file
89177
- `fileExists(filePath)` - Check if a file exists
90178
- `makeDir(path)` - Create a directory
91179
- `rmDir(path)` - Remove a directory
92180

181+
### Transport adapters
182+
183+
Implement the `AttachmentTransportAdapter` interface from `@powersync/common`:
184+
185+
- `upload(attachment)` - Transfer the local file to remote storage
186+
- `download(attachment)` - Transfer the remote file into `attachment.localUri`
187+
- `delete(attachment)` - Delete the file from remote storage
188+
93189
## Supported Versions
94190

95-
| Adapter | Library | Supported Versions |
96-
| ------------------------------------- | ----------------------------- | ------------------ |
97-
| `ExpoFileSystemStorageAdapter` | `expo-file-system` | >=19.0.0 (Expo 54+)|
98-
| `ReactNativeFileSystemStorageAdapter` | `@dr.pogodin/react-native-fs` | ^2.25.0 |
191+
| Adapter | Library | Supported Versions |
192+
| ------------------------------------- | ----------------------------- | ------------------- |
193+
| `ExpoFileSystemStorageAdapter` | `expo-file-system` | >=19.0.0 (Expo 54+) |
194+
| `ExpoFileSystemTransportAdapter` | `expo-file-system` | >=19.0.0 (Expo 54+) |
195+
| `ReactNativeFileSystemStorageAdapter` | `@dr.pogodin/react-native-fs` | ^2.25.0 |
196+
| `ReactNativeFSTransportAdapter` | `@dr.pogodin/react-native-fs` | ^2.25.0 |
99197

100198
## License
101199

0 commit comments

Comments
 (0)