@chitchat/sdk-react-native 0.2.0-dev.0 → 0.2.0-dev.2
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/README.md +8 -7
- package/index.d.ts +4 -3
- package/package.json +10 -4
- package/src/index.js +29 -16
package/README.md
CHANGED
|
@@ -46,8 +46,8 @@ const tokenProvider = createBackendTokenProvider({
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
const client = createChitChatNativeClient({
|
|
49
|
-
// TLS TCP
|
|
50
|
-
endpoint: 'realtime.example.com
|
|
49
|
+
// TLS TCP hostname. Port 443 is applied when the port is omitted.
|
|
50
|
+
endpoint: 'realtime.example.com',
|
|
51
51
|
tokenProvider,
|
|
52
52
|
nativeModule,
|
|
53
53
|
storage: durableNativeOutbox
|
|
@@ -57,14 +57,15 @@ client.on('connected', () => setRealtimeState('connected'));
|
|
|
57
57
|
client.on('message', (frame) => handleChitChatFrame(frame));
|
|
58
58
|
client.on('error', (error) => reportNonSensitiveRealtimeError(error));
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
client.connect().catch(reportNonSensitiveRealtimeError);
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
On logout or account switch:
|
|
64
64
|
|
|
65
65
|
```js
|
|
66
|
-
|
|
67
|
-
tokenProvider.invalidate()
|
|
66
|
+
client.close()
|
|
67
|
+
.then(() => tokenProvider.invalidate())
|
|
68
|
+
.catch(reportNonSensitiveRealtimeError);
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
## Native bridge contract
|
|
@@ -91,7 +92,7 @@ The bridge must encode/decode the gateway’s actual generated Protobuf envelope
|
|
|
91
92
|
|
|
92
93
|
## Durable outbox
|
|
93
94
|
|
|
94
|
-
The default core outbox is memory-only. To preserve queued messages when the app is restarted, pass a durable store with
|
|
95
|
+
The default core outbox is memory-only. To preserve queued messages when the app is restarted, pass a durable store with Promise-returning `put(record)`, `remove(id)`, and `list()` methods. Use an encrypted/device-appropriate storage provider and return records sorted by `createdAt`.
|
|
95
96
|
|
|
96
97
|
## TLS requirements
|
|
97
98
|
|
|
@@ -106,7 +107,7 @@ The default core outbox is memory-only. To preserve queued messages when the app
|
|
|
106
107
|
| Problem | Fix |
|
|
107
108
|
| --- | --- |
|
|
108
109
|
| `official ChitChat native TCP module is required` | Link/provide the native bridge and rebuild the app. Expo Go is not enough. |
|
|
109
|
-
| `TLS host
|
|
110
|
+
| `TLS host endpoint is required` | Use `realtime.example.com` (defaults to 443) or an explicit `host:port`; do not pass an HTTP or WebSocket URL. |
|
|
110
111
|
| iOS SSL / certificate error | Check the hostname, SAN, trusted CA, device time, and gateway certificate chain. |
|
|
111
112
|
| Repeated reconnects | Check token issuance/expiry, gateway reachability, bridge frame codec, and `error`/`reconnectFailed` events. |
|
|
112
113
|
| Queued messages disappear after restart | Provide durable `storage`; the default is memory-only. |
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReliableRealtimeClient, ReliableRealtimeClientOptions, RealtimeFrame } from '@chitchat/sdk-core';
|
|
2
2
|
export interface ChitChatNativeConnection { onFrame(listener: (frame: RealtimeFrame) => void): void; onClose(listener: (reason?: unknown) => void): void; send(frame: RealtimeFrame): Promise<void> | void; close(): Promise<void> | void; }
|
|
3
|
-
export interface ChitChatNativeModule { connect(input: { endpoint: string; token: string; protocol: 'chitchat.protobuf.v1'; tls: true }): Promise<ChitChatNativeConnection>; }
|
|
3
|
+
export interface ChitChatNativeModule { connect(input: { endpoint: string; token: string; protocol: 'chitchat.protobuf.v1'; tls: true; minimumTlsVersion: 'TLSv1.2' | 'TLSv1.3'; pinnedPublicKeyHashes: string[] }): Promise<ChitChatNativeConnection>; }
|
|
4
4
|
export function validateNativeTlsEndpoint(endpoint: string): string;
|
|
5
|
-
export function
|
|
6
|
-
export function
|
|
5
|
+
export function validatePinnedPublicKeyHashes(value?: string[]): string[];
|
|
6
|
+
export function createNativeTcpTransportFactory(options: { nativeModule: ChitChatNativeModule; pinnedPublicKeyHashes?: string[]; minimumTlsVersion?: 'TLSv1.2' | 'TLSv1.3' }): ReliableRealtimeClientOptions['nativeTransportFactory'];
|
|
7
|
+
export function createChitChatNativeClient(options: Omit<ReliableRealtimeClientOptions, 'runtime' | 'nativeTransportFactory'> & { nativeModule: ChitChatNativeModule; pinnedPublicKeyHashes?: string[]; minimumTlsVersion?: 'TLSv1.2' | 'TLSv1.3' }): ReliableRealtimeClient;
|
package/package.json
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chitchat/sdk-react-native",
|
|
3
|
-
"version": "0.2.0-dev.
|
|
3
|
+
"version": "0.2.0-dev.2",
|
|
4
|
+
"description": "React Native TLS transport adapter for the ChitChat Developer Platform",
|
|
5
|
+
"repository": { "type": "git", "url": "git+https://github.com/07Akashh/E2E-Chat.git", "directory": "developer-web/sdk/chitchat-native" },
|
|
6
|
+
"bugs": { "url": "https://github.com/07Akashh/E2E-Chat/issues" },
|
|
7
|
+
"homepage": "https://github.com/07Akashh/E2E-Chat/tree/main/docs/developer-platform",
|
|
4
8
|
"main": "src/index.js",
|
|
5
|
-
"exports": { ".": { "types": "./index.d.ts", "require": "./src/index.js" } },
|
|
9
|
+
"exports": { ".": { "types": "./index.d.ts", "require": "./src/index.js", "import": "./src/index.js" } },
|
|
6
10
|
"types": "index.d.ts",
|
|
7
|
-
"files": ["src", "index.d.ts", "README.md"
|
|
11
|
+
"files": ["src", "index.d.ts", "README.md"],
|
|
8
12
|
"engines": { "node": ">=18" },
|
|
9
13
|
"scripts": { "test": "node test/transport.test.js" },
|
|
10
|
-
"dependencies": { "@chitchat/sdk-core": "0.2.0-dev.
|
|
14
|
+
"dependencies": { "@chitchat/sdk-core": "0.2.0-dev.2" },
|
|
15
|
+
"keywords": ["chitchat", "realtime", "react-native", "tls", "protobuf"],
|
|
16
|
+
"sideEffects": false,
|
|
11
17
|
"license": "UNLICENSED",
|
|
12
18
|
"publishConfig": { "access": "public", "tag": "development" }
|
|
13
19
|
}
|
package/src/index.js
CHANGED
|
@@ -4,12 +4,13 @@ let ReliableRealtimeClient;
|
|
|
4
4
|
try { ({ ReliableRealtimeClient } = require('@chitchat/sdk-core')); } catch (_) { ({ ReliableRealtimeClient } = require('../../chitchat-core/src')); }
|
|
5
5
|
|
|
6
6
|
const validateNativeTlsEndpoint = (endpoint) => {
|
|
7
|
-
if (typeof endpoint !== 'string' || !endpoint.trim() || /\s/.test(endpoint)) throw new Error('A TLS host
|
|
7
|
+
if (typeof endpoint !== 'string' || !endpoint.trim() || /\s/.test(endpoint)) throw new Error('A TLS host endpoint is required');
|
|
8
8
|
if (/^(https?|wss?):\/\//i.test(endpoint)) throw new Error('React Native realtime requires a TLS TCP host:port endpoint, not a HTTP/WebSocket URL');
|
|
9
9
|
let parsed;
|
|
10
|
-
try { parsed = new URL(`tls://${endpoint}`); } catch (_) { throw new Error('A valid TLS host
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
try { parsed = new URL(`tls://${endpoint}`); } catch (_) { throw new Error('A valid TLS host endpoint is required'); }
|
|
11
|
+
const port = parsed.port ? Number(parsed.port) : 443;
|
|
12
|
+
if (!parsed.hostname || port < 1 || port > 65535 || parsed.username || parsed.password || parsed.search || parsed.hash || (parsed.pathname && parsed.pathname !== '/')) throw new Error('A valid TLS host endpoint is required');
|
|
13
|
+
return `${parsed.hostname}:${port}`;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
const assertConnection = (connection) => {
|
|
@@ -17,25 +18,37 @@ const assertConnection = (connection) => {
|
|
|
17
18
|
return connection;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
|
-
const
|
|
21
|
+
const validatePinnedPublicKeyHashes = (value) => {
|
|
22
|
+
if (value === undefined) return [];
|
|
23
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > 10 || value.some((hash) => typeof hash !== 'string' || !/^sha256\/[A-Za-z0-9+/]{43}=$/.test(hash))) {
|
|
24
|
+
throw new Error('pinnedPublicKeyHashes must contain one to ten sha256/base64 SPKI hashes');
|
|
25
|
+
}
|
|
26
|
+
return [...new Set(value)];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const createNativeTcpTransportFactory = ({ nativeModule, pinnedPublicKeyHashes, minimumTlsVersion = 'TLSv1.2' }) => {
|
|
21
30
|
if (!nativeModule || typeof nativeModule.connect !== 'function') throw new Error('The official ChitChat native TCP module is required');
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
if (!['TLSv1.2', 'TLSv1.3'].includes(minimumTlsVersion)) throw new Error('minimumTlsVersion must be TLSv1.2 or TLSv1.3');
|
|
32
|
+
const pins = validatePinnedPublicKeyHashes(pinnedPublicKeyHashes);
|
|
33
|
+
return ({ endpoint, token, protocol }) => {
|
|
34
|
+
const normalizedEndpoint = validateNativeTlsEndpoint(endpoint);
|
|
24
35
|
let connection; let onMessage = () => {}; let onClose = () => {};
|
|
25
|
-
return {
|
|
36
|
+
return Promise.resolve({
|
|
26
37
|
onMessage: (listener) => { onMessage = listener; },
|
|
27
38
|
onClose: (listener) => { onClose = listener; },
|
|
28
|
-
open:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
open: () => Promise.resolve(nativeModule.connect({ endpoint: normalizedEndpoint, token, protocol, tls: true, minimumTlsVersion, pinnedPublicKeyHashes: pins }))
|
|
40
|
+
.then(assertConnection)
|
|
41
|
+
.then((openedConnection) => {
|
|
42
|
+
connection = openedConnection;
|
|
43
|
+
connection.onFrame((frame) => onMessage(frame));
|
|
44
|
+
connection.onClose((reason) => onClose(reason));
|
|
45
|
+
}),
|
|
33
46
|
send: (frame) => connection ? Promise.resolve(connection.send(frame)) : Promise.reject(new Error('Native TCP transport is not open')),
|
|
34
47
|
close: () => connection ? Promise.resolve(connection.close()) : Promise.resolve()
|
|
35
|
-
};
|
|
48
|
+
});
|
|
36
49
|
};
|
|
37
50
|
};
|
|
38
51
|
|
|
39
|
-
const createChitChatNativeClient = ({ endpoint, tokenProvider, nativeModule, ...options }) => new ReliableRealtimeClient({ endpoint, tokenProvider, runtime: 'native', nativeTransportFactory: createNativeTcpTransportFactory({ nativeModule }), ...options });
|
|
52
|
+
const createChitChatNativeClient = ({ endpoint, tokenProvider, nativeModule, pinnedPublicKeyHashes, minimumTlsVersion, ...options }) => new ReliableRealtimeClient({ endpoint, tokenProvider, runtime: 'native', nativeTransportFactory: createNativeTcpTransportFactory({ nativeModule, pinnedPublicKeyHashes, minimumTlsVersion }), ...options });
|
|
40
53
|
|
|
41
|
-
module.exports = { createChitChatNativeClient, createNativeTcpTransportFactory, validateNativeTlsEndpoint };
|
|
54
|
+
module.exports = { createChitChatNativeClient, createNativeTcpTransportFactory, validateNativeTlsEndpoint, validatePinnedPublicKeyHashes };
|