@signalapp/libsignal-client 0.67.2 → 0.67.3

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.
@@ -0,0 +1,29 @@
1
+ import type { ReadonlyDeep } from 'type-fest';
2
+ import * as Native from '../../Native';
3
+ import { TokioAsyncContext, ServiceAuth } from '../net';
4
+ export type CDSRequestOptionsType = {
5
+ e164s: Array<string>;
6
+ acisAndAccessKeys: Array<{
7
+ aci: string;
8
+ accessKey: string;
9
+ }>;
10
+ /**
11
+ * @deprecated this option is ignored by the server.
12
+ */
13
+ returnAcisWithoutUaks: boolean;
14
+ abortSignal?: AbortSignal;
15
+ useNewConnectLogic?: boolean;
16
+ };
17
+ export type CDSResponseEntryType<Aci, Pni> = {
18
+ aci: Aci | undefined;
19
+ pni: Pni | undefined;
20
+ };
21
+ export type CDSResponseEntries<Aci, Pni> = Map<string, CDSResponseEntryType<Aci, Pni>>;
22
+ export interface CDSResponseType<Aci, Pni> {
23
+ entries: CDSResponseEntries<Aci, Pni>;
24
+ debugPermitsUsed: number;
25
+ }
26
+ export declare function cdsiLookup({ asyncContext, connectionManager, }: Readonly<{
27
+ asyncContext: TokioAsyncContext;
28
+ connectionManager: Native.Wrapper<Native.ConnectionManager>;
29
+ }>, { username, password }: Readonly<ServiceAuth>, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }: ReadonlyDeep<CDSRequestOptionsType>): Promise<CDSResponseType<string, string>>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2025 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.cdsiLookup = void 0;
8
+ const Native = require("../../Native");
9
+ const Address_1 = require("../Address");
10
+ const node_buffer_1 = require("node:buffer");
11
+ const net_1 = require("../net");
12
+ async function cdsiLookup({ asyncContext, connectionManager, }, { username, password }, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }) {
13
+ const request = (0, net_1.newNativeHandle)(Native.LookupRequest_new());
14
+ e164s.forEach((e164) => {
15
+ Native.LookupRequest_addE164(request, e164);
16
+ });
17
+ acisAndAccessKeys.forEach(({ aci: aciStr, accessKey: accessKeyStr }) => {
18
+ Native.LookupRequest_addAciAndAccessKey(request, Address_1.Aci.parseFromServiceIdString(aciStr).getServiceIdFixedWidthBinary(), node_buffer_1.Buffer.from(accessKeyStr, 'base64'));
19
+ });
20
+ const startLookup = useNewConnectLogic
21
+ ? Native.CdsiLookup_new_routes
22
+ : Native.CdsiLookup_new;
23
+ const lookup = await asyncContext.makeCancellable(abortSignal, startLookup(asyncContext, connectionManager, username, password, request));
24
+ return await asyncContext.makeCancellable(abortSignal, Native.CdsiLookup_complete(asyncContext, (0, net_1.newNativeHandle)(lookup)));
25
+ }
26
+ exports.cdsiLookup = cdsiLookup;
27
+ //# sourceMappingURL=CDSI.js.map
@@ -0,0 +1,121 @@
1
+ /// <reference types="node" />
2
+ import * as Native from '../../Native';
3
+ import { LibSignalError } from '../Errors';
4
+ import { Wrapper } from '../../Native';
5
+ import { Buffer } from 'node:buffer';
6
+ import { TokioAsyncContext } from '../net';
7
+ export type ChatRequest = Readonly<{
8
+ verb: string;
9
+ path: string;
10
+ headers: ReadonlyArray<[string, string]>;
11
+ body?: Uint8Array;
12
+ timeoutMillis?: number;
13
+ }>;
14
+ type ConnectionManager = Wrapper<Native.ConnectionManager>;
15
+ export declare class ChatServerMessageAck {
16
+ readonly _nativeHandle: Native.ServerMessageAck;
17
+ constructor(_nativeHandle: Native.ServerMessageAck);
18
+ send(statusCode: number): void;
19
+ }
20
+ export interface ConnectionEventsListener {
21
+ /**
22
+ * Called when the client gets disconnected from the server.
23
+ *
24
+ * This includes both deliberate disconnects as well as unexpected socket
25
+ * closures. If the closure was not due to a deliberate disconnect, the error
26
+ * will be provided.
27
+ */
28
+ onConnectionInterrupted(cause: LibSignalError | null): void;
29
+ }
30
+ export interface ChatServiceListener extends ConnectionEventsListener {
31
+ /**
32
+ * Called when the server delivers an incoming message to the client.
33
+ *
34
+ * `timestamp` is in milliseconds.
35
+ *
36
+ * If `ack`'s `send` method is not called, the server will leave this message in the message
37
+ * queue and attempt to deliver it again in the future.
38
+ */
39
+ onIncomingMessage(envelope: Buffer, timestamp: number, ack: ChatServerMessageAck): void;
40
+ /**
41
+ * Called when the server indicates that there are no further messages in the message queue.
42
+ *
43
+ * Note that further messages may still be delivered; this merely indicates that all messages that
44
+ * were in the queue *when the connection was established* have been delivered.
45
+ */
46
+ onQueueEmpty(): void;
47
+ /**
48
+ * Called when the server has alerts for the current device.
49
+ *
50
+ * In practice this happens as part of the connecting process.
51
+ */
52
+ onReceivedAlerts?(alerts: string[]): void;
53
+ }
54
+ /**
55
+ * A connection to the Chat Service.
56
+ *
57
+ * Provides API methods to communicate with the remote service. Make sure to
58
+ * call {@link #disconnect()} when the instance is no longer needed.
59
+ */
60
+ export type ChatConnection = {
61
+ /**
62
+ * Initiates termination of the underlying connection to the Chat Service. After the service is
63
+ * disconnected, it cannot be used again.
64
+ */
65
+ disconnect(): Promise<void>;
66
+ /**
67
+ * Sends request to the Chat service.
68
+ */
69
+ fetch(chatRequest: ChatRequest, options?: {
70
+ abortSignal?: AbortSignal;
71
+ }): Promise<Native.ChatResponse>;
72
+ /**
73
+ * Information about the connection to the Chat service.
74
+ */
75
+ connectionInfo(): ConnectionInfo;
76
+ };
77
+ export interface ConnectionInfo {
78
+ localPort: number;
79
+ ipVersion: 'IPv4' | 'IPv6';
80
+ toString: () => string;
81
+ }
82
+ export declare class UnauthenticatedChatConnection implements ChatConnection {
83
+ private readonly asyncContext;
84
+ private readonly chatService;
85
+ private readonly chatListener;
86
+ static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, listener: ConnectionEventsListener, options?: {
87
+ abortSignal?: AbortSignal;
88
+ }): Promise<UnauthenticatedChatConnection>;
89
+ private constructor();
90
+ fetch(chatRequest: ChatRequest, options?: {
91
+ abortSignal?: AbortSignal;
92
+ }): Promise<Native.ChatResponse>;
93
+ disconnect(): Promise<void>;
94
+ connectionInfo(): ConnectionInfo;
95
+ }
96
+ export declare class AuthenticatedChatConnection implements ChatConnection {
97
+ private readonly asyncContext;
98
+ private readonly chatService;
99
+ private readonly chatListener;
100
+ static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, username: string, password: string, receiveStories: boolean, listener: ChatServiceListener, options?: {
101
+ abortSignal?: AbortSignal;
102
+ }): Promise<AuthenticatedChatConnection>;
103
+ /**
104
+ * Creates a chat connection backed by a fake remote end.
105
+ *
106
+ * @param asyncContext the async runtime to use
107
+ * @param listener the listener to send events to
108
+ * @param alerts alerts to send immediately upon connect
109
+ * @returns an {@link AuthenticatedChatConnection} and handle for the remote
110
+ * end of the fake connection.
111
+ */
112
+ static fakeConnect(asyncContext: TokioAsyncContext, listener: ChatServiceListener, alerts?: ReadonlyArray<string>): [AuthenticatedChatConnection, Wrapper<Native.FakeChatRemoteEnd>];
113
+ private constructor();
114
+ fetch(chatRequest: ChatRequest, options?: {
115
+ abortSignal?: AbortSignal;
116
+ }): Promise<Native.ChatResponse>;
117
+ disconnect(): Promise<void>;
118
+ connectionInfo(): ConnectionInfo;
119
+ }
120
+ export declare function buildHttpRequest(chatRequest: ChatRequest): Wrapper<Native.HttpRequest>;
121
+ export {};
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2025 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.buildHttpRequest = exports.AuthenticatedChatConnection = exports.UnauthenticatedChatConnection = exports.ChatServerMessageAck = void 0;
8
+ const Native = require("../../Native");
9
+ const node_buffer_1 = require("node:buffer");
10
+ const net_1 = require("../net");
11
+ const DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS = 5000;
12
+ class ChatServerMessageAck {
13
+ constructor(_nativeHandle) {
14
+ this._nativeHandle = _nativeHandle;
15
+ }
16
+ send(statusCode) {
17
+ Native.ServerMessageAck_SendStatus(this, statusCode);
18
+ }
19
+ }
20
+ exports.ChatServerMessageAck = ChatServerMessageAck;
21
+ class ConnectionInfoImpl {
22
+ constructor(_nativeHandle) {
23
+ this._nativeHandle = _nativeHandle;
24
+ }
25
+ get localPort() {
26
+ return Native.ChatConnectionInfo_local_port(this);
27
+ }
28
+ get ipVersion() {
29
+ const value = Native.ChatConnectionInfo_ip_version(this);
30
+ switch (value) {
31
+ case 1:
32
+ return 'IPv4';
33
+ case 2:
34
+ return 'IPv6';
35
+ default:
36
+ throw new TypeError(`ip type was unexpectedly ${value}`);
37
+ }
38
+ }
39
+ toString() {
40
+ return Native.ChatConnectionInfo_description(this);
41
+ }
42
+ }
43
+ class UnauthenticatedChatConnection {
44
+ static async connect(asyncContext, connectionManager, listener, options) {
45
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
46
+ const connect = Native.UnauthenticatedChatConnection_connect(asyncContext, connectionManager);
47
+ const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
48
+ const connection = (0, net_1.newNativeHandle)(chat);
49
+ Native.UnauthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
50
+ return new UnauthenticatedChatConnection(asyncContext, connection, nativeChatListener);
51
+ }
52
+ constructor(asyncContext, chatService,
53
+ // Unused except to keep the listener alive since the Rust code only holds a
54
+ // weak reference to the same object.
55
+ chatListener) {
56
+ this.asyncContext = asyncContext;
57
+ this.chatService = chatService;
58
+ this.chatListener = chatListener;
59
+ }
60
+ fetch(chatRequest, options) {
61
+ return this.asyncContext.makeCancellable(options?.abortSignal, Native.UnauthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
62
+ }
63
+ disconnect() {
64
+ return Native.UnauthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
65
+ }
66
+ connectionInfo() {
67
+ return new ConnectionInfoImpl(Native.UnauthenticatedChatConnection_info(this.chatService));
68
+ }
69
+ }
70
+ exports.UnauthenticatedChatConnection = UnauthenticatedChatConnection;
71
+ class AuthenticatedChatConnection {
72
+ static async connect(asyncContext, connectionManager, username, password, receiveStories, listener, options) {
73
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
74
+ const connect = Native.AuthenticatedChatConnection_connect(asyncContext, connectionManager, username, password, receiveStories);
75
+ const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
76
+ const connection = (0, net_1.newNativeHandle)(chat);
77
+ Native.AuthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
78
+ return new AuthenticatedChatConnection(asyncContext, connection, nativeChatListener);
79
+ }
80
+ /**
81
+ * Creates a chat connection backed by a fake remote end.
82
+ *
83
+ * @param asyncContext the async runtime to use
84
+ * @param listener the listener to send events to
85
+ * @param alerts alerts to send immediately upon connect
86
+ * @returns an {@link AuthenticatedChatConnection} and handle for the remote
87
+ * end of the fake connection.
88
+ */
89
+ static fakeConnect(asyncContext, listener, alerts) {
90
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
91
+ const fakeChat = (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_Create(asyncContext, new WeakListenerWrapper(nativeChatListener), alerts?.join('\n') ?? ''));
92
+ const chat = (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_TakeAuthenticatedChat(fakeChat));
93
+ return [
94
+ new AuthenticatedChatConnection(asyncContext, chat, nativeChatListener),
95
+ (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_TakeRemote(fakeChat)),
96
+ ];
97
+ }
98
+ constructor(asyncContext, chatService,
99
+ // Unused except to keep the listener alive since the Rust code only holds a
100
+ // weak reference to the same object.
101
+ chatListener) {
102
+ this.asyncContext = asyncContext;
103
+ this.chatService = chatService;
104
+ this.chatListener = chatListener;
105
+ }
106
+ fetch(chatRequest, options) {
107
+ return this.asyncContext.makeCancellable(options?.abortSignal, Native.AuthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
108
+ }
109
+ disconnect() {
110
+ return Native.AuthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
111
+ }
112
+ connectionInfo() {
113
+ return new ConnectionInfoImpl(Native.AuthenticatedChatConnection_info(this.chatService));
114
+ }
115
+ }
116
+ exports.AuthenticatedChatConnection = AuthenticatedChatConnection;
117
+ /**
118
+ * Holds a {@link Native.ChatListener} by {@link WeakRef} and delegates
119
+ * `ChatListener` calls to it.
120
+ *
121
+ * This lets us avoid passing anything across the bridge that has a normal
122
+ * (strong) reference to the app-side listener. The danger is that the passed-in
123
+ * listener might gain a reference to the JS connection object; that would
124
+ * result in a reference cycle that Node can't clean up because one of the
125
+ * references is through a Rust `Box`.
126
+ *
127
+ * When constructing a connection, calling code should wrap an app-side listener
128
+ * in this type and pass it across the bridge, then hold its own strong
129
+ * reference to the same listener as a field. This ensures that if there is a
130
+ * reference cycle between the connection and app-side listener, that cycle is
131
+ * visible to the Node runtime, while still ensuring the passed-in listener
132
+ * stays alive as long as the connection does.
133
+ */
134
+ class WeakListenerWrapper {
135
+ constructor(listener) {
136
+ this.listener = new WeakRef(listener);
137
+ }
138
+ _connection_interrupted(reason) {
139
+ this.listener.deref()?._connection_interrupted(reason);
140
+ }
141
+ _incoming_message(envelope, timestamp, ack) {
142
+ this.listener.deref()?._incoming_message(envelope, timestamp, ack);
143
+ }
144
+ _queue_empty() {
145
+ this.listener.deref()?._queue_empty();
146
+ }
147
+ _received_alerts(alerts) {
148
+ this.listener.deref()?._received_alerts(alerts);
149
+ }
150
+ }
151
+ function makeNativeChatListener(asyncContext, listener) {
152
+ if ('onQueueEmpty' in listener) {
153
+ return {
154
+ _incoming_message(envelope, timestamp, ack) {
155
+ listener.onIncomingMessage(envelope, timestamp, new ChatServerMessageAck(ack));
156
+ },
157
+ _queue_empty() {
158
+ listener.onQueueEmpty();
159
+ },
160
+ _received_alerts(alerts) {
161
+ listener.onReceivedAlerts?.(alerts);
162
+ },
163
+ _connection_interrupted(cause) {
164
+ listener.onConnectionInterrupted(cause);
165
+ },
166
+ };
167
+ }
168
+ return {
169
+ _incoming_message(_envelope, _timestamp, _ack) {
170
+ throw new Error('Event not supported on unauthenticated connection');
171
+ },
172
+ _queue_empty() {
173
+ throw new Error('Event not supported on unauthenticated connection');
174
+ },
175
+ _received_alerts(_alerts) {
176
+ throw new Error('Event not supported on unauthenticated connection');
177
+ },
178
+ _connection_interrupted(cause) {
179
+ listener.onConnectionInterrupted(cause);
180
+ },
181
+ };
182
+ }
183
+ function buildHttpRequest(chatRequest) {
184
+ const { verb, path, body, headers } = chatRequest;
185
+ const bodyBuffer = body !== undefined ? node_buffer_1.Buffer.from(body) : null;
186
+ const httpRequest = {
187
+ _nativeHandle: Native.HttpRequest_new(verb, path, bodyBuffer),
188
+ };
189
+ headers.forEach((header) => {
190
+ const [name, value] = header;
191
+ Native.HttpRequest_add_header(httpRequest, name, value);
192
+ });
193
+ return httpRequest;
194
+ }
195
+ exports.buildHttpRequest = buildHttpRequest;
196
+ //# sourceMappingURL=Chat.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalapp/libsignal-client",
3
- "version": "0.67.2",
3
+ "version": "0.67.3",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,6 +8,8 @@
8
8
  "dist/acknowledgments.md",
9
9
  "dist/*.js",
10
10
  "dist/*.d.ts",
11
+ "dist/net/**/*.js",
12
+ "dist/net/**/*.d.ts",
11
13
  "dist/zkgroup/**/*.js",
12
14
  "dist/zkgroup/**/*.d.ts",
13
15
  "Native.js",