osra 0.2.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +319 -304
- package/build/connections/bidirectional.d.ts +53 -0
- package/build/connections/index.d.ts +20 -0
- package/build/connections/utils.d.ts +31 -0
- package/build/index.d.ts +16 -630
- package/build/index.js +918 -634
- package/build/index.js.map +1 -1
- package/build/revivables/abort-signal.d.ts +20 -0
- package/build/revivables/array-buffer.d.ts +12 -0
- package/build/revivables/bigint.d.ts +14 -0
- package/build/revivables/date.d.ts +9 -0
- package/build/revivables/error.d.ts +10 -0
- package/build/revivables/event-target.d.ts +29 -0
- package/build/revivables/function.d.ts +29 -0
- package/build/revivables/headers.d.ts +9 -0
- package/build/revivables/identity.d.ts +39 -0
- package/build/revivables/index.d.ts +39 -0
- package/build/revivables/map.d.ts +11 -0
- package/build/revivables/message-port.d.ts +83 -0
- package/build/revivables/promise.d.ts +34 -0
- package/build/revivables/readable-stream.d.ts +18 -0
- package/build/revivables/request.d.ts +23 -0
- package/build/revivables/response.d.ts +18 -0
- package/build/revivables/set.d.ts +11 -0
- package/build/revivables/transfer.d.ts +37 -0
- package/build/revivables/typed-array.d.ts +15 -0
- package/build/revivables/utils.d.ts +59 -0
- package/build/types.d.ts +45 -0
- package/build/utils/capable-check.d.ts +44 -0
- package/build/utils/event-channel.d.ts +27 -0
- package/build/utils/index.d.ts +11 -0
- package/build/utils/replace.d.ts +25 -0
- package/build/utils/transferable.d.ts +20 -0
- package/build/utils/transport.d.ts +56 -0
- package/build/utils/type-guards.d.ts +58 -0
- package/build/utils/type.d.ts +2 -0
- package/build/utils/typed-event-target.d.ts +16 -0
- package/build/utils/typed-message-channel.d.ts +19 -0
- package/package.json +60 -67
package/README.md
CHANGED
|
@@ -1,305 +1,320 @@
|
|
|
1
|
-
# Osra - Easy Communication Between Workers
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/osra)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
|
|
6
|
-
Osra is a powerful, type-safe communication library for JavaScript/TypeScript that enables seamless inter-context communication with support for complex data types that normally wouldn't be transferable.
|
|
7
|
-
|
|
8
|
-
## Features
|
|
9
|
-
|
|
10
|
-
- **Universal Communication** - Works across Workers, SharedWorkers, ServiceWorkers, Windows, MessagePorts, WebSockets, and Browser Extensions
|
|
11
|
-
- **Rich Type Support** - Seamlessly handle Promises, Functions, Streams, Dates, Errors, TypedArrays, and more
|
|
12
|
-
- **Full TypeScript Support** - Complete type safety with automatic type inference
|
|
13
|
-
- **
|
|
14
|
-
- **Zero Dependencies** - Lightweight with no external runtime dependencies
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
import {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
- **
|
|
195
|
-
- **Objects
|
|
196
|
-
- **
|
|
197
|
-
- **
|
|
198
|
-
- **
|
|
199
|
-
- **
|
|
200
|
-
- **
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
- `
|
|
212
|
-
- `
|
|
213
|
-
- `
|
|
214
|
-
- `
|
|
215
|
-
- `
|
|
216
|
-
- `
|
|
217
|
-
- `
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
##
|
|
300
|
-
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
304
|
-
-
|
|
1
|
+
# Osra - Easy Communication Between Workers
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/osra)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Osra is a powerful, type-safe communication library for JavaScript/TypeScript that enables seamless inter-context communication with support for complex data types that normally wouldn't be transferable.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Universal Communication** - Works across Workers, SharedWorkers, ServiceWorkers, Windows, MessagePorts, WebSockets, and Browser Extensions
|
|
11
|
+
- **Rich Type Support** - Seamlessly handle Promises, Functions, Streams, Dates, Errors, TypedArrays, and more
|
|
12
|
+
- **Full TypeScript Support** - Complete type safety with automatic type inference
|
|
13
|
+
- **Two Transport Modes** - Capable mode for structured-clone transports, JSON mode for string-only channels — selected from the transport itself
|
|
14
|
+
- **Zero Dependencies** - Lightweight with no external runtime dependencies
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install osra
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Basic Worker Communication
|
|
25
|
+
|
|
26
|
+
**Worker file (`worker.ts`):**
|
|
27
|
+
```typescript
|
|
28
|
+
import { expose } from 'osra'
|
|
29
|
+
|
|
30
|
+
const api = {
|
|
31
|
+
// Simple function
|
|
32
|
+
add: async (a: number, b: number) => a + b,
|
|
33
|
+
|
|
34
|
+
// Function returning complex objects
|
|
35
|
+
getUser: async (id: string) => ({
|
|
36
|
+
id,
|
|
37
|
+
name: 'John Doe',
|
|
38
|
+
createdAt: new Date(),
|
|
39
|
+
// Even functions work!
|
|
40
|
+
greet: () => `Hello, I'm user ${id}`,
|
|
41
|
+
}),
|
|
42
|
+
|
|
43
|
+
// Streaming data
|
|
44
|
+
streamData: async function* () {
|
|
45
|
+
for (let i = 0; i < 10; i++) {
|
|
46
|
+
yield i
|
|
47
|
+
await new Promise(r => setTimeout(r, 100))
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type WorkerAPI = typeof api
|
|
53
|
+
|
|
54
|
+
// Expose the API through the worker
|
|
55
|
+
expose(api, { transport: self })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Main thread (`main.ts`):**
|
|
59
|
+
```typescript
|
|
60
|
+
import { expose } from 'osra'
|
|
61
|
+
import type { WorkerAPI } from './worker'
|
|
62
|
+
|
|
63
|
+
const worker = new Worker('./worker.js', { type: 'module' })
|
|
64
|
+
|
|
65
|
+
// Connect to the worker with full type safety
|
|
66
|
+
const api = await expose<WorkerAPI>({}, { transport: worker })
|
|
67
|
+
|
|
68
|
+
// Call functions as if they were local
|
|
69
|
+
const sum = await api.add(5, 3) // 8
|
|
70
|
+
|
|
71
|
+
// Complex objects work seamlessly
|
|
72
|
+
const user = await api.getUser('123')
|
|
73
|
+
console.log(user.createdAt) // Date object, not string!
|
|
74
|
+
const greeting = await user.greet() // "Hello, I'm user 123"
|
|
75
|
+
|
|
76
|
+
// Stream data
|
|
77
|
+
for await (const value of api.streamData()) {
|
|
78
|
+
console.log(value) // 0, 1, 2, ...
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Advanced Examples
|
|
83
|
+
|
|
84
|
+
### Window to Window Communication
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Parent window
|
|
88
|
+
import { expose } from 'osra'
|
|
89
|
+
|
|
90
|
+
const childWindow = window.open('child.html')
|
|
91
|
+
|
|
92
|
+
const parentAPI = {
|
|
93
|
+
notifyParent: async (message: string) => {
|
|
94
|
+
console.log('Child says:', message)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const childAPI = await expose<ChildAPI>(parentAPI, {
|
|
99
|
+
transport: childWindow,
|
|
100
|
+
origin: 'https://child-domain.com' // Optional: restrict origin
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Child window (child.html)
|
|
104
|
+
const childAPI = {
|
|
105
|
+
initialize: async () => {
|
|
106
|
+
console.log('Child initialized!')
|
|
107
|
+
return true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
expose(childAPI, { transport: window.parent })
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### SharedWorker Communication
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Shared Worker
|
|
118
|
+
import { expose } from 'osra'
|
|
119
|
+
|
|
120
|
+
const connections = new Set<string>()
|
|
121
|
+
|
|
122
|
+
const api = {
|
|
123
|
+
connect: async (clientId: string) => {
|
|
124
|
+
connections.add(clientId)
|
|
125
|
+
return {
|
|
126
|
+
broadcast: async (message: string) => {
|
|
127
|
+
// Broadcast to all connected clients
|
|
128
|
+
console.log(`${clientId} broadcasts: ${message}`)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
self.addEventListener('connect', (event) => {
|
|
135
|
+
const port = event.ports[0]
|
|
136
|
+
expose(api, { transport: port })
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
// Client
|
|
140
|
+
const sharedWorker = new SharedWorker('./shared-worker.js')
|
|
141
|
+
const api = await expose<SharedWorkerAPI>({}, { transport: sharedWorker })
|
|
142
|
+
const connection = await api.connect('client-1')
|
|
143
|
+
await connection.broadcast('Hello everyone!')
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Browser Extension Communication
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// Background script
|
|
150
|
+
import { expose } from 'osra'
|
|
151
|
+
|
|
152
|
+
const api = {
|
|
153
|
+
fetchData: async (url: string) => {
|
|
154
|
+
const response = await fetch(url)
|
|
155
|
+
return response.json()
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
expose(api, { transport: chrome.runtime })
|
|
160
|
+
|
|
161
|
+
// Content script or popup
|
|
162
|
+
const api = await expose<BackgroundAPI>({}, { transport: chrome.runtime })
|
|
163
|
+
const data = await api.fetchData('https://api.example.com/data')
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Custom Transport
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { expose } from 'osra'
|
|
170
|
+
|
|
171
|
+
// Create custom transport for any communication channel
|
|
172
|
+
const customTransport = {
|
|
173
|
+
emit: (message: any, transferables?: Transferable[]) => {
|
|
174
|
+
// Send message through your custom channel
|
|
175
|
+
myCustomChannel.send(message, transferables)
|
|
176
|
+
},
|
|
177
|
+
receive: (listener: (message: any) => void) => {
|
|
178
|
+
// Listen for messages from your custom channel
|
|
179
|
+
myCustomChannel.on('message', listener)
|
|
180
|
+
|
|
181
|
+
// Return cleanup function
|
|
182
|
+
return () => myCustomChannel.off('message', listener)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const api = await expose<RemoteAPI>({}, { transport: customTransport })
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Supported Types
|
|
190
|
+
|
|
191
|
+
Osra automatically handles serialization/deserialization of:
|
|
192
|
+
|
|
193
|
+
- **Primitives**: `boolean`, `number`, `string`, `null`, `undefined`, `BigInt`
|
|
194
|
+
- **Objects & Arrays**: Including nested structures
|
|
195
|
+
- **Built-in Objects**: `Date`, `RegExp`, `Map`, `Set`, `Error`
|
|
196
|
+
- **Binary Data**: `ArrayBuffer`, `TypedArray`, `Blob`, `File`
|
|
197
|
+
- **Functions**: Callable across contexts with full async support
|
|
198
|
+
- **Promises**: Seamlessly await remote promises
|
|
199
|
+
- **Streams**: `ReadableStream` support (WritableStream coming soon)
|
|
200
|
+
- **Transferables**: `MessagePort`, `ImageBitmap`, `OffscreenCanvas`
|
|
201
|
+
|
|
202
|
+
## API Reference
|
|
203
|
+
|
|
204
|
+
### `expose<T>(value, options)`
|
|
205
|
+
|
|
206
|
+
The main function for establishing communication between contexts.
|
|
207
|
+
|
|
208
|
+
#### Parameters
|
|
209
|
+
|
|
210
|
+
- `value`: The object/value to expose (server-side) or an empty object (client-side)
|
|
211
|
+
- `options`: Configuration object
|
|
212
|
+
- `transport`: The transport to use (Worker, Window, MessagePort, etc.)
|
|
213
|
+
- `name?`: Optional name for this endpoint (default: random UUID)
|
|
214
|
+
- `remoteName?`: Name of the remote endpoint to connect to
|
|
215
|
+
- `key?`: Optional key for additional security
|
|
216
|
+
- `origin?`: Origin restriction for Window communication
|
|
217
|
+
- `unregisterSignal?`: AbortSignal to clean up the connection
|
|
218
|
+
|
|
219
|
+
#### Returns
|
|
220
|
+
|
|
221
|
+
Promise resolving to the remote API object with full type safety.
|
|
222
|
+
|
|
223
|
+
### Transfer Optimization
|
|
224
|
+
|
|
225
|
+
Osra copies transferables by default — your buffers stay usable on the
|
|
226
|
+
sender after an RPC. When you want to hand off ownership instead (large
|
|
227
|
+
uploads, one-shot buffers, streams you won't read locally), wrap the value
|
|
228
|
+
in `transfer()`:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { expose, transfer } from 'osra'
|
|
232
|
+
|
|
233
|
+
const buffer = new Uint8Array(largeData).buffer
|
|
234
|
+
|
|
235
|
+
// Default: copy. `buffer` is still usable after this call.
|
|
236
|
+
await remote.preview(buffer)
|
|
237
|
+
|
|
238
|
+
// Opt-in transfer: `buffer` is neutered on the sender, no copy made.
|
|
239
|
+
await remote.upload(transfer(buffer))
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`transfer()` works for `ArrayBuffer`, typed array views, `MessagePort`,
|
|
243
|
+
streams, `ImageBitmap`, and `OffscreenCanvas`. It's idempotent and a no-op
|
|
244
|
+
for primitives and plain objects. Must-transfer types (`MessagePort`,
|
|
245
|
+
streams, `OffscreenCanvas`) are always moved regardless of the wrapper —
|
|
246
|
+
structured clone can't copy them.
|
|
247
|
+
|
|
248
|
+
## Protocol Modes
|
|
249
|
+
|
|
250
|
+
### Bidirectional Mode (Default)
|
|
251
|
+
|
|
252
|
+
Both sides can expose APIs and call each other:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Side A
|
|
256
|
+
const remoteAPI = await expose<RemoteAPI>(localAPI, { transport })
|
|
257
|
+
|
|
258
|
+
// Side B
|
|
259
|
+
const remoteAPI = await expose<RemoteAPI>(localAPI, { transport })
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Unidirectional Mode
|
|
263
|
+
|
|
264
|
+
One-way communication when only one side needs to call the other:
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// Server (exposes API)
|
|
268
|
+
expose(api, { transport })
|
|
269
|
+
|
|
270
|
+
// Client (calls API)
|
|
271
|
+
const api = await expose<API>({}, { transport })
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Transport Modes
|
|
275
|
+
|
|
276
|
+
Osra picks between two modes based on the transport you hand it:
|
|
277
|
+
|
|
278
|
+
- **Capable mode** — Workers, SharedWorkers, ServiceWorkers, Windows,
|
|
279
|
+
MessagePorts, and any custom transport without `isJson: true`. Uses
|
|
280
|
+
structured clone natively and moves transferables when you opt in with
|
|
281
|
+
`transfer()`.
|
|
282
|
+
- **JSON mode** — WebSockets, browser extension runtime/port APIs, and any
|
|
283
|
+
custom transport flagged with `isJson: true`. Complex types (Functions,
|
|
284
|
+
Promises, Dates, Errors, TypedArrays, streams, …) still work: the
|
|
285
|
+
box/reviver system serializes them into JSON-safe representations and
|
|
286
|
+
revives them on the other side.
|
|
287
|
+
|
|
288
|
+
You generally don't need to configure anything — pass your transport and
|
|
289
|
+
osra does the right thing. For a custom transport that tunnels JSON (e.g.
|
|
290
|
+
over a `string`-only channel), set `isJson: true` on it.
|
|
291
|
+
|
|
292
|
+
## Performance Tips
|
|
293
|
+
|
|
294
|
+
1. **Use Transfer for Large Data**: Transfer ArrayBuffers and TypedArrays instead of cloning
|
|
295
|
+
2. **Batch Operations**: Group multiple calls when possible
|
|
296
|
+
3. **Stream Large Datasets**: Use async generators for large data sets
|
|
297
|
+
4. **Reuse Connections**: Keep connections alive for multiple operations
|
|
298
|
+
|
|
299
|
+
## Browser Compatibility
|
|
300
|
+
|
|
301
|
+
- Chrome/Edge 88+
|
|
302
|
+
- Firefox 85+
|
|
303
|
+
- Safari 15+
|
|
304
|
+
- Node.js 16+ (with Worker Threads)
|
|
305
|
+
|
|
306
|
+
## Contributing
|
|
307
|
+
|
|
308
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
309
|
+
|
|
310
|
+
## License
|
|
311
|
+
|
|
312
|
+
MIT © [Banou26](https://github.com/Banou26)
|
|
313
|
+
|
|
314
|
+
## Roadmap
|
|
315
|
+
|
|
316
|
+
- [ ] WritableStream support
|
|
317
|
+
- [ ] Custom revivable plugins for user-defined types
|
|
318
|
+
- [ ] Performance optimizations for large object graphs
|
|
319
|
+
- [ ] Better error handling and debugging tools
|
|
305
320
|
- [ ] WebRTC DataChannel transport
|