@droponair/sdk-js 0.22.0 → 0.22.1
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/CHANGELOG.md +16 -10
- package/README.md +2 -2
- package/dist/transport/protobuf-codec.js +31 -21
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,12 +6,20 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [0.22.1], 2026-05-31
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Message send/receive broken when attachments support is compiled in.** The protobuf reflection tree shared a single `AttachmentRef` type instance across `Envelope`, `GroupEnvelope`, and `GroupMessageNotification`. Because a protobufjs reflection object can have only one parent, adding it to a later message re-parented it and removed it from `Envelope`, so encoding any 1:1 message threw `no such Type or Enum 'AttachmentRef' in Type Envelope` before a frame was ever produced. Each message now builds its own `AttachmentRef` (and nested `DeviceWrappedKey` / `EncryptionType`) instance. Wire format is unchanged, this is purely a client-side construction fix. Also resolves the same latent failure on `GroupMessageNotification` decode.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
9
17
|
## [0.22.0], 2026-05-25
|
|
10
18
|
|
|
11
19
|
### Added
|
|
12
20
|
|
|
13
21
|
- **MessagingClient transport selection.** `initialize({ transport: 'ws' | 'sse' | 'wt' | 'auto' })` lets your app choose the signaling lane at init time. Default stays `'ws'`, so existing integrations are byte-identical. `'auto'` queries `GET /api/info.transports` and picks the best available lane from what the runtime supports. WebSocket close-code semantics (1008 JWT-expiry surfacing, 4001 JWT-refresh-on-event) are preserved on the WebSocket path; SSE/WT synthesize close events.
|
|
14
|
-
- **MQTT (IoT) broadcast lane
|
|
22
|
+
- **MQTT (IoT) broadcast lane.** Broadcasts now mirror to MQTT topic `droponair/v1/broadcast/{appId}/{channelId}` on `mqtts://mqtt.droponair.com:8883`. For IoT subscribers that consume your broadcasts without our full SDK. Subscribe-only, per-app credentials, TLS only. Visible via `GET /api/info` (`transports` includes `"mqtt"`, `features` includes `"transport_mqtt"`). No SDK API change, the lane is consumed directly by MQTT clients.
|
|
15
23
|
|
|
16
24
|
### Changed
|
|
17
25
|
|
|
@@ -23,11 +31,11 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
23
31
|
|
|
24
32
|
### Added
|
|
25
33
|
|
|
26
|
-
- **Transport auto-select helper
|
|
34
|
+
- **Transport auto-select helper.** New `selectTransport({ httpUrl })` reads `/api/info.transports`, intersects with the runtime's `WebTransport`/`WebSocket`/`EventSource` availability, and returns the best lane (preference: WebTransport -> WebSocket -> SSE; overridable via `preference`). Caller then constructs the corresponding primitive. Pluggable `fetchFn` for Node + tests.
|
|
27
35
|
|
|
28
36
|
### Notes
|
|
29
37
|
|
|
30
|
-
- Foundation for an `init({ transport: 'auto' })` shortcut once full `MessagingClient` integration lands
|
|
38
|
+
- Foundation for an `init({ transport: 'auto' })` shortcut once full `MessagingClient` integration lands in a follow-up release. Today it's a small standalone helper so existing customers can adopt the pattern without waiting.
|
|
31
39
|
|
|
32
40
|
---
|
|
33
41
|
|
|
@@ -35,12 +43,12 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
35
43
|
|
|
36
44
|
### Added
|
|
37
45
|
|
|
38
|
-
- **WebTransport (HTTP/3) transport primitive
|
|
46
|
+
- **WebTransport (HTTP/3) transport primitive.** New `WebTransportTransport` class uses the browser-native `WebTransport` API to ride the platform's `/v1/transport/wt` HTTP/3 endpoint,. Same shape as `SseTransport`: `onFrame`, `sendEnvelope`, `connect`, `close`. Caller brings own protobuf decoder. Browser-only for v1 (Chromium 97+, Firefox 125+, Safari TP-only); Node 22+ has experimental support behind flags.
|
|
39
47
|
|
|
40
48
|
### Notes
|
|
41
49
|
|
|
42
50
|
- WebTransport gives multi-stream perf wins over WebSocket on flaky cellular and similar networks. WebSocket on `/ws` remains the default; this primitive is opt-in for environments that have native WebTransport.
|
|
43
|
-
- The droponair.com endpoint only advertises `transports: ["webtransport"]` once the
|
|
51
|
+
- The droponair.com endpoint only advertises `transports: ["webtransport"]` once the HTTP/3 lane is enabled and `app.transport.webtransport-enabled` is flipped on the platform. Check `GET /api/info.transports` for the live list.
|
|
44
52
|
|
|
45
53
|
---
|
|
46
54
|
|
|
@@ -48,11 +56,11 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
48
56
|
|
|
49
57
|
### Added
|
|
50
58
|
|
|
51
|
-
- **SSE transport primitive
|
|
59
|
+
- **SSE transport primitive.** New `SseTransport` class exposes the platform's HTTP-fallback lane (`/v1/transport/stream` + `/v1/transport/send`) as a small standalone client, for environments where WebSocket upgrades are blocked by corporate firewalls but HTTPS GET/POST work. EventSource-based receive (auto-reconnects), `fetch` POST for send. Bring your own protobuf decoder (use the codec already exported from the SDK).
|
|
52
60
|
|
|
53
61
|
### Notes
|
|
54
62
|
|
|
55
|
-
- v1 is a primitive; full `init({ transport: 'sse' })` integration into `MessagingClient` lands in
|
|
63
|
+
- v1 is a primitive; full `init({ transport: 'sse' })` integration into `MessagingClient` lands in a follow-up release. Customers who need the SSE lane today can use `SseTransport` directly alongside the existing WS client.
|
|
56
64
|
- WebSocket on `/ws` remains the default for all SDK calls; this addition is purely opt-in. Older code paths and existing apps are unaffected.
|
|
57
65
|
|
|
58
66
|
---
|
|
@@ -61,7 +69,7 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
61
69
|
|
|
62
70
|
### Added
|
|
63
71
|
|
|
64
|
-
- **SFU recording
|
|
72
|
+
- **SFU recording.** Server-side recording for SFU-mode rooms with `mediaEncryption: 'SFU'`. The platform's media server records the composite of every track in the room and uploads the finalized file directly to the customer's storage bucket - the platform never holds the recorded bytes. Storage destinations (S3 / GCS / Azure) are registered once in the panel; the SDK references each by an opaque `destinationId`.
|
|
65
73
|
- Three new client methods:
|
|
66
74
|
- `startSfuRecording(roomId, destinationId)` -> `SfuRecording`
|
|
67
75
|
- `stopSfuRecording(roomId, recordingId)` -> `SfuRecording`
|
|
@@ -326,7 +334,6 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
326
334
|
- Wire-level additive: legacy 0.4.x clients ignore the new `Envelope.attachments` field (proto3 forwards-compat). Existing apps continue to work unchanged.
|
|
327
335
|
- v1 storage adapters supported by the server: S3-compatible (S3, R2, MinIO, B2, Wasabi), Google Cloud Storage, Azure Blob.
|
|
328
336
|
- Plan limits: `maxAttachmentSizeMb` per file + `maxAttachmentsPerMonth`. FREE = attachments disabled. PRO = 25 MB / 1000 per month. GROWTH = 100 MB / 10000. PAYG = 250 MB / metered. ENTERPRISE = custom.
|
|
329
|
-
- Requires sdk-be `0.5.0` server.
|
|
330
337
|
|
|
331
338
|
---
|
|
332
339
|
|
|
@@ -342,7 +349,6 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
342
349
|
### Notes
|
|
343
350
|
- Each edit and each `FOR_EVERYONE` delete counts as **one** MESSAGE usage record (subject to plan quotas + rate limits).
|
|
344
351
|
- Wire-level additive: legacy 0.3.x clients ignore unknown frame types (proto3 forwards-compat), so existing TwinFlame and CrowdSyncer apps continue to work unchanged.
|
|
345
|
-
- Requires sdk-be `0.4.0` server.
|
|
346
352
|
|
|
347
353
|
---
|
|
348
354
|
|
package/README.md
CHANGED
|
@@ -183,7 +183,7 @@ E2EE invariant: the push body is sender-supplied cleartext metadata only (e.g. "
|
|
|
183
183
|
|
|
184
184
|
### Message Edit & Delete
|
|
185
185
|
|
|
186
|
-
Available since SDK `0.4.0
|
|
186
|
+
Available since SDK `0.4.0`.
|
|
187
187
|
|
|
188
188
|
```typescript
|
|
189
189
|
// Edit an encrypted message
|
|
@@ -213,7 +213,7 @@ client.onMessageDelete((del) => {
|
|
|
213
213
|
|
|
214
214
|
### Attachments (Customer-Managed Storage)
|
|
215
215
|
|
|
216
|
-
Available since SDK `0.5.0
|
|
216
|
+
Available since SDK `0.5.0`. Configure your bucket once in the DropOnAir panel (S3-compatible, GCS, or Azure Blob). DropOnAir never holds file bytes - the SDK uploads/downloads directly against your bucket via short-lived presigned URLs.
|
|
217
217
|
|
|
218
218
|
```typescript
|
|
219
219
|
// Convenience: encrypt + upload + finalize in one call, then send with the message.
|
|
@@ -42,29 +42,38 @@ const DeviceEncryptedPayloadType = new protobuf.Type('DeviceEncryptedPayload')
|
|
|
42
42
|
.add(new protobuf.Field('deviceId', 1, 'string'))
|
|
43
43
|
.add(new protobuf.Field('encryptedPayload', 2, 'bytes'))
|
|
44
44
|
.add(new protobuf.Field('senderPublicKey', 3, 'bytes'));
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
// Reference to an out-of-band attachment in customer-managed storage, plus its
|
|
46
|
+
// nested per-device wrapped file key (PROTOCOL_VERSION 4+).
|
|
47
|
+
//
|
|
48
|
+
// A protobufjs reflection object can have only ONE parent: calling `.add(obj)`
|
|
49
|
+
// on a second message re-parents `obj` and silently removes it from the first.
|
|
50
|
+
// Envelope, GroupEnvelope and GroupMessageNotification each nest AttachmentRef,
|
|
51
|
+
// so each needs its OWN instance, built fresh here. Sharing a single instance
|
|
52
|
+
// across them re-parented it onto the last adder and orphaned it from Envelope,
|
|
53
|
+
// breaking every 1:1 send with "no such Type or Enum 'AttachmentRef' in Type
|
|
54
|
+
// Envelope". The EncryptionType enum and DeviceWrappedKey type are nested inside
|
|
55
|
+
// each AttachmentRef and so are rebuilt per call for the same reason.
|
|
56
|
+
function buildAttachmentRefType() {
|
|
57
|
+
return new protobuf.Type('AttachmentRef')
|
|
58
|
+
.add(new protobuf.Enum('EncryptionType', { E2EE: 0, CLEARTEXT: 1 }))
|
|
59
|
+
.add(new protobuf.Type('DeviceWrappedKey')
|
|
60
|
+
.add(new protobuf.Field('deviceId', 1, 'string'))
|
|
61
|
+
.add(new protobuf.Field('wrappedKey', 2, 'bytes'))
|
|
62
|
+
.add(new protobuf.Field('senderPublicKey', 3, 'bytes'))
|
|
63
|
+
.add(new protobuf.Field('nonce', 4, 'bytes')))
|
|
64
|
+
.add(new protobuf.Field('attachmentId', 1, 'string'))
|
|
65
|
+
.add(new protobuf.Field('storageHint', 2, 'string'))
|
|
66
|
+
.add(new protobuf.Field('mimeType', 3, 'string'))
|
|
67
|
+
.add(new protobuf.Field('sizeBytes', 4, 'int64'))
|
|
68
|
+
.add(new protobuf.Field('sha256', 5, 'string'))
|
|
69
|
+
.add(new protobuf.Field('encryptionType', 6, 'EncryptionType'))
|
|
70
|
+
.add(new protobuf.Field('wrappedKeys', 7, 'DeviceWrappedKey', 'repeated'))
|
|
71
|
+
.add(new protobuf.Field('thumbnailAttachmentId', 8, 'string'));
|
|
72
|
+
}
|
|
64
73
|
const EnvelopeType = new protobuf.Type('Envelope')
|
|
65
74
|
.add(EncryptionTypeEnum)
|
|
66
75
|
.add(DeviceEncryptedPayloadType) // nested type must be added first
|
|
67
|
-
.add(
|
|
76
|
+
.add(buildAttachmentRefType())
|
|
68
77
|
.add(new protobuf.Field('messageId', 1, 'string'))
|
|
69
78
|
.add(new protobuf.Field('appId', 2, 'string'))
|
|
70
79
|
.add(new protobuf.Field('fromUserId', 3, 'string'))
|
|
@@ -128,7 +137,7 @@ const GroupEnvelopeEncryptionTypeEnum = new protobuf.Enum('EncryptionType', { E2
|
|
|
128
137
|
const GroupEnvelopeType = new protobuf.Type('GroupEnvelope')
|
|
129
138
|
.add(GroupEnvelopeEncryptionTypeEnum)
|
|
130
139
|
.add(GroupMemberPayloadType)
|
|
131
|
-
.add(
|
|
140
|
+
.add(buildAttachmentRefType())
|
|
132
141
|
.add(new protobuf.Field('messageId', 1, 'string'))
|
|
133
142
|
.add(new protobuf.Field('appId', 2, 'string'))
|
|
134
143
|
.add(new protobuf.Field('groupId', 3, 'string'))
|
|
@@ -149,6 +158,7 @@ const GroupNotifDeviceType = new protobuf.Type('DeviceEncryptedPayload')
|
|
|
149
158
|
const GroupMessageNotificationType = new protobuf.Type('GroupMessageNotification')
|
|
150
159
|
.add(GroupNotifEncryptionTypeEnum)
|
|
151
160
|
.add(GroupNotifDeviceType)
|
|
161
|
+
.add(buildAttachmentRefType())
|
|
152
162
|
.add(new protobuf.Field('messageId', 1, 'string'))
|
|
153
163
|
.add(new protobuf.Field('groupId', 2, 'string'))
|
|
154
164
|
.add(new protobuf.Field('fromUserId', 3, 'string'))
|
package/dist/version.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
8
8
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
9
9
|
*/
|
|
10
|
-
export declare const SDK_VERSION = "0.22.
|
|
10
|
+
export declare const SDK_VERSION = "0.22.1";
|
|
11
11
|
/**
|
|
12
12
|
* Binary encrypted-payload format version.
|
|
13
13
|
* Included as the first byte of every encrypted payload so receivers can
|
package/dist/version.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.PROTOCOL_VERSION = exports.PAYLOAD_FORMAT_VERSION = exports.SDK_VERSION
|
|
|
10
10
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
11
11
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
12
12
|
*/
|
|
13
|
-
exports.SDK_VERSION = '0.22.
|
|
13
|
+
exports.SDK_VERSION = '0.22.1';
|
|
14
14
|
/**
|
|
15
15
|
* Binary encrypted-payload format version.
|
|
16
16
|
* Included as the first byte of every encrypted payload so receivers can
|