@basmilius/apple-common 0.9.19 → 0.10.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/dist/index.d.mts +767 -14
- package/dist/index.mjs +1051 -106
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { RemoteInfo } from "node:dgram";
|
|
2
3
|
import { EventEmitter } from "node:events";
|
|
3
4
|
|
|
4
5
|
//#region ../../node_modules/.bun/uuid@13.0.0/node_modules/uuid/dist/types.d.ts
|
|
@@ -12,6 +13,7 @@ declare function v4(options?: Version4Options, buf?: undefined, offset?: number)
|
|
|
12
13
|
declare function v4<TBuf extends Uint8Array = Uint8Array>(options: Version4Options | undefined, buf: TBuf, offset?: number): TBuf;
|
|
13
14
|
//#endregion
|
|
14
15
|
//#region src/airplayFeatures.d.ts
|
|
16
|
+
/** Type definition for the AirPlay feature flags bitmask object. */
|
|
15
17
|
type AirPlayFeatureFlagsType = {
|
|
16
18
|
readonly SupportsAirPlayVideoV1: bigint;
|
|
17
19
|
readonly SupportsAirPlayPhoto: bigint;
|
|
@@ -58,54 +60,225 @@ type AirPlayFeatureFlagsType = {
|
|
|
58
60
|
readonly SupportsAudioMetadataControl: bigint;
|
|
59
61
|
readonly SupportsRFC2198Redundancy: bigint;
|
|
60
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* AirPlay feature flags as a bitmask of bigint values. Each flag corresponds to a specific
|
|
65
|
+
* capability advertised by an AirPlay device in its mDNS TXT record "features" field.
|
|
66
|
+
* The bit positions match Apple's internal AirPlayFeatureFlags enum.
|
|
67
|
+
*/
|
|
61
68
|
declare const AirPlayFeatureFlags: AirPlayFeatureFlagsType;
|
|
69
|
+
/** String union of all known AirPlay feature flag names. */
|
|
62
70
|
type AirPlayFeatureFlagName = keyof typeof AirPlayFeatureFlags;
|
|
71
|
+
/** The type of pairing required to connect to an AirPlay device. */
|
|
63
72
|
type PairingRequirement = 'none' | 'pin' | 'transient' | 'homekit';
|
|
73
|
+
/**
|
|
74
|
+
* Parses an AirPlay features string into a single bigint bitmask.
|
|
75
|
+
* Features are advertised as either a single hex value or two comma-separated
|
|
76
|
+
* 32-bit hex values (low,high) which are combined into a 64-bit bitmask.
|
|
77
|
+
*
|
|
78
|
+
* @param features - The features string from the mDNS TXT record.
|
|
79
|
+
* @returns The combined feature flags as a bigint.
|
|
80
|
+
* @throws If the features string has an unexpected format.
|
|
81
|
+
*/
|
|
64
82
|
declare function parseFeatures(features: string): bigint;
|
|
83
|
+
/**
|
|
84
|
+
* Checks whether a specific feature flag is set in a features bitmask.
|
|
85
|
+
*
|
|
86
|
+
* @param features - The combined feature flags bitmask.
|
|
87
|
+
* @param flag - The specific flag to check for.
|
|
88
|
+
* @returns True if the flag is set.
|
|
89
|
+
*/
|
|
65
90
|
declare function hasFeatureFlag(features: bigint, flag: bigint): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Returns the names of all feature flags that are set in the given bitmask.
|
|
93
|
+
* Useful for debugging and diagnostics output.
|
|
94
|
+
*
|
|
95
|
+
* @param features - The combined feature flags bitmask.
|
|
96
|
+
* @returns An array of feature flag names that are active.
|
|
97
|
+
*/
|
|
66
98
|
declare function describeFlags(features: bigint): AirPlayFeatureFlagName[];
|
|
99
|
+
/**
|
|
100
|
+
* Determines the AirPlay protocol version supported by a device based on its
|
|
101
|
+
* mDNS TXT record properties. AirPlay 2 is indicated by the presence of
|
|
102
|
+
* SupportsUnifiedMediaControl or SupportsCoreUtilsPairingAndEncryption flags.
|
|
103
|
+
*
|
|
104
|
+
* @param txt - The key-value properties from the device's mDNS TXT record.
|
|
105
|
+
* @returns 1 for legacy AirPlay, 2 for AirPlay 2.
|
|
106
|
+
*/
|
|
67
107
|
declare function getProtocolVersion(txt: Record<string, string>): 1 | 2;
|
|
108
|
+
/**
|
|
109
|
+
* Determines the pairing requirement for an AirPlay device based on its
|
|
110
|
+
* feature flags and status flags. The hierarchy is:
|
|
111
|
+
* HomeKit pairing > PIN required > Transient (system) pairing > Legacy PIN > None.
|
|
112
|
+
*
|
|
113
|
+
* @param txt - The key-value properties from the device's mDNS TXT record.
|
|
114
|
+
* @returns The pairing requirement type.
|
|
115
|
+
*/
|
|
68
116
|
declare function getPairingRequirement(txt: Record<string, string>): PairingRequirement;
|
|
117
|
+
/**
|
|
118
|
+
* Checks whether the AirPlay device requires a password to connect.
|
|
119
|
+
* Determined by the "pw" TXT field or the password bit in the "sf" status flags.
|
|
120
|
+
*
|
|
121
|
+
* @param txt - The key-value properties from the device's mDNS TXT record.
|
|
122
|
+
* @returns True if a password is required.
|
|
123
|
+
*/
|
|
69
124
|
declare function isPasswordRequired(txt: Record<string, string>): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Checks whether the AirPlay device supports remote control (Hangdog protocol).
|
|
127
|
+
* Only devices with the SupportsHangdogRemoteControl flag can receive HID events.
|
|
128
|
+
*
|
|
129
|
+
* @param txt - The key-value properties from the device's mDNS TXT record.
|
|
130
|
+
* @returns True if remote control is supported (typically Apple TV only).
|
|
131
|
+
*/
|
|
70
132
|
declare function isRemoteControlSupported(txt: Record<string, string>): boolean;
|
|
71
133
|
//#endregion
|
|
72
134
|
//#region src/reporter.d.ts
|
|
135
|
+
/**
|
|
136
|
+
* Available debug output groups. Each group can be independently enabled
|
|
137
|
+
* or disabled via the global {@link Reporter} singleton.
|
|
138
|
+
*/
|
|
73
139
|
type DebugGroup = 'debug' | 'error' | 'info' | 'net' | 'raw' | 'warn';
|
|
140
|
+
/**
|
|
141
|
+
* Scoped logger instance tagged with a device or component identifier.
|
|
142
|
+
* All log output is gated by the global {@link reporter} singleton — messages
|
|
143
|
+
* are only printed when the corresponding debug group is enabled.
|
|
144
|
+
*/
|
|
74
145
|
declare class Logger {
|
|
75
146
|
#private;
|
|
147
|
+
/** The identifier this logger is scoped to. */
|
|
76
148
|
get id(): string;
|
|
149
|
+
/** ANSI-colored label prefix used in log output. */
|
|
77
150
|
get label(): string;
|
|
151
|
+
/**
|
|
152
|
+
* @param id - Identifier used as a prefix in log output (typically a device ID or component name).
|
|
153
|
+
*/
|
|
78
154
|
constructor(id: string);
|
|
155
|
+
/**
|
|
156
|
+
* Logs a debug-level message (cyan). Only printed when the 'debug' group is enabled.
|
|
157
|
+
*
|
|
158
|
+
* @param data - Values to log.
|
|
159
|
+
*/
|
|
79
160
|
debug(...data: any[]): void;
|
|
161
|
+
/**
|
|
162
|
+
* Logs an error-level message (red). Only printed when the 'error' group is enabled.
|
|
163
|
+
*
|
|
164
|
+
* @param data - Values to log.
|
|
165
|
+
*/
|
|
80
166
|
error(...data: any[]): void;
|
|
167
|
+
/**
|
|
168
|
+
* Logs an info-level message (green). Only printed when the 'info' group is enabled.
|
|
169
|
+
*
|
|
170
|
+
* @param data - Values to log.
|
|
171
|
+
*/
|
|
81
172
|
info(...data: any[]): void;
|
|
173
|
+
/**
|
|
174
|
+
* Logs a network-level message (yellow). Only printed when the 'net' group is enabled.
|
|
175
|
+
*
|
|
176
|
+
* @param data - Values to log.
|
|
177
|
+
*/
|
|
82
178
|
net(...data: any[]): void;
|
|
179
|
+
/**
|
|
180
|
+
* Logs a raw data message (blue). Only printed when the 'raw' group is enabled.
|
|
181
|
+
* Typically used for hex dumps and binary protocol data.
|
|
182
|
+
*
|
|
183
|
+
* @param data - Values to log.
|
|
184
|
+
*/
|
|
83
185
|
raw(...data: any[]): void;
|
|
186
|
+
/**
|
|
187
|
+
* Logs a warning-level message (yellow). Only printed when the 'warn' group is enabled.
|
|
188
|
+
*
|
|
189
|
+
* @param data - Values to log.
|
|
190
|
+
*/
|
|
84
191
|
warn(...data: any[]): void;
|
|
85
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Global log output controller that manages which debug groups are active.
|
|
195
|
+
* All {@link Logger} instances check the singleton {@link reporter} before printing.
|
|
196
|
+
*/
|
|
86
197
|
declare class Reporter {
|
|
87
198
|
#private;
|
|
199
|
+
/** Enables all debug groups (except 'raw' which is very verbose). */
|
|
88
200
|
all(): void;
|
|
201
|
+
/** Disables all debug groups, silencing all log output. */
|
|
89
202
|
none(): void;
|
|
203
|
+
/**
|
|
204
|
+
* Disables a specific debug group.
|
|
205
|
+
*
|
|
206
|
+
* @param group - The debug group to disable.
|
|
207
|
+
*/
|
|
90
208
|
disable(group: DebugGroup): void;
|
|
209
|
+
/**
|
|
210
|
+
* Enables a specific debug group.
|
|
211
|
+
*
|
|
212
|
+
* @param group - The debug group to enable.
|
|
213
|
+
*/
|
|
91
214
|
enable(group: DebugGroup): void;
|
|
215
|
+
/**
|
|
216
|
+
* Checks whether a specific debug group is currently enabled.
|
|
217
|
+
*
|
|
218
|
+
* @param group - The debug group to check.
|
|
219
|
+
* @returns True if the group is enabled.
|
|
220
|
+
*/
|
|
92
221
|
isEnabled(group: DebugGroup): boolean;
|
|
93
222
|
}
|
|
223
|
+
/** Global reporter singleton controlling which debug groups produce output. */
|
|
94
224
|
declare const reporter: Reporter;
|
|
95
225
|
//#endregion
|
|
96
226
|
//#region src/context.d.ts
|
|
227
|
+
/**
|
|
228
|
+
* Describes the identity that this client presents to Apple devices during pairing
|
|
229
|
+
* and protocol negotiation. Mimics a real Apple device to ensure compatibility.
|
|
230
|
+
*/
|
|
231
|
+
type DeviceIdentity = {
|
|
232
|
+
name: string;
|
|
233
|
+
model: string;
|
|
234
|
+
osName: string;
|
|
235
|
+
osVersion: string;
|
|
236
|
+
osBuildVersion: string;
|
|
237
|
+
sourceVersion: string;
|
|
238
|
+
applicationBundleIdentifier: string;
|
|
239
|
+
applicationBundleVersion: string;
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Shared context for a device connection, carrying the device identifier,
|
|
243
|
+
* the client identity presented to the accessory, and a scoped logger.
|
|
244
|
+
* Passed through the entire protocol stack for consistent identification and logging.
|
|
245
|
+
*/
|
|
97
246
|
declare class Context {
|
|
98
247
|
#private;
|
|
248
|
+
/** Unique identifier of the target device (typically its mDNS hostname). */
|
|
99
249
|
get deviceId(): string;
|
|
250
|
+
/** The identity this client presents to the Apple device. */
|
|
251
|
+
get identity(): DeviceIdentity;
|
|
252
|
+
/** Scoped logger instance tagged with the device identifier. */
|
|
100
253
|
get logger(): Logger;
|
|
101
|
-
|
|
254
|
+
/**
|
|
255
|
+
* @param deviceId - Unique identifier of the target device.
|
|
256
|
+
* @param identity - Optional partial override of the default device identity.
|
|
257
|
+
*/
|
|
258
|
+
constructor(deviceId: string, identity?: Partial<DeviceIdentity>);
|
|
102
259
|
}
|
|
103
260
|
//#endregion
|
|
104
261
|
//#region src/pairing.d.ts
|
|
262
|
+
/**
|
|
263
|
+
* Abstract base class for HAP pairing operations. Provides shared TLV8
|
|
264
|
+
* decoding with automatic error checking.
|
|
265
|
+
*/
|
|
105
266
|
declare abstract class BasePairing {
|
|
106
267
|
#private;
|
|
268
|
+
/** The shared context carrying device identity and logger. */
|
|
107
269
|
get context(): Context;
|
|
270
|
+
/**
|
|
271
|
+
* @param context - Shared context for logging and device identity.
|
|
272
|
+
*/
|
|
108
273
|
constructor(context: Context);
|
|
274
|
+
/**
|
|
275
|
+
* Decodes a TLV8 buffer and checks for error codes. If the TLV contains
|
|
276
|
+
* an error value, it throws via TLV8.bail.
|
|
277
|
+
*
|
|
278
|
+
* @param buffer - The raw TLV8-encoded response.
|
|
279
|
+
* @returns A map of TLV type numbers to their buffer values.
|
|
280
|
+
* @throws If the TLV contains an error value.
|
|
281
|
+
*/
|
|
109
282
|
tlv(buffer: Buffer): Map<number, Buffer>;
|
|
110
283
|
}
|
|
111
284
|
/**
|
|
@@ -121,9 +294,32 @@ declare abstract class BasePairing {
|
|
|
121
294
|
*/
|
|
122
295
|
declare class AccessoryPair extends BasePairing {
|
|
123
296
|
#private;
|
|
297
|
+
/**
|
|
298
|
+
* @param context - Shared context for logging and device identity.
|
|
299
|
+
* @param requestHandler - Callback that sends TLV8-encoded data and returns the response.
|
|
300
|
+
*/
|
|
124
301
|
constructor(context: Context, requestHandler: RequestHandler);
|
|
302
|
+
/** Generates a new Ed25519 key pair for long-term identity. Must be called before pin() or transient(). */
|
|
125
303
|
start(): Promise<void>;
|
|
304
|
+
/**
|
|
305
|
+
* Performs the full PIN-based pair-setup flow (M1 through M6).
|
|
306
|
+
* Prompts for a PIN via the provided callback, then completes SRP authentication
|
|
307
|
+
* and Ed25519 credential exchange with the accessory.
|
|
308
|
+
*
|
|
309
|
+
* @param askPin - Async callback that returns the user-entered PIN.
|
|
310
|
+
* @returns Long-term credentials for future pair-verify sessions.
|
|
311
|
+
* @throws {PairingError} If any step fails.
|
|
312
|
+
*/
|
|
126
313
|
pin(askPin: () => Promise<string>): Promise<AccessoryCredentials>;
|
|
314
|
+
/**
|
|
315
|
+
* Performs the transient (non-persistent) pair-setup flow (M1 through M4 only).
|
|
316
|
+
* Uses the default transient PIN ('3939'). No long-term credentials are stored;
|
|
317
|
+
* session keys are derived directly from the SRP shared secret.
|
|
318
|
+
*
|
|
319
|
+
* Primarily used for HomePod connections where persistent pairing is not required.
|
|
320
|
+
*
|
|
321
|
+
* @returns Session keys for the current connection (not reusable across sessions).
|
|
322
|
+
*/
|
|
127
323
|
transient(): Promise<AccessoryKeys>;
|
|
128
324
|
/**
|
|
129
325
|
* SRP Step 1: Initiates pair-setup by requesting the accessory's SRP public key and salt.
|
|
@@ -186,54 +382,93 @@ declare class AccessoryPair extends BasePairing {
|
|
|
186
382
|
*/
|
|
187
383
|
declare class AccessoryVerify extends BasePairing {
|
|
188
384
|
#private;
|
|
385
|
+
/**
|
|
386
|
+
* @param context - Shared context for logging and device identity.
|
|
387
|
+
* @param requestHandler - Callback that sends TLV8-encoded data and returns the response.
|
|
388
|
+
*/
|
|
189
389
|
constructor(context: Context, requestHandler: RequestHandler);
|
|
390
|
+
/**
|
|
391
|
+
* Performs the full pair-verify flow (M1 through M4) using stored credentials
|
|
392
|
+
* from a previous pair-setup. Establishes a new session with forward secrecy
|
|
393
|
+
* via ephemeral Curve25519 key exchange.
|
|
394
|
+
*
|
|
395
|
+
* @param credentials - Long-term credentials from a previous pair-setup.
|
|
396
|
+
* @returns Session keys derived from the ECDH shared secret.
|
|
397
|
+
* @throws {AuthenticationError} If the accessory's identity cannot be verified.
|
|
398
|
+
*/
|
|
190
399
|
start(credentials: AccessoryCredentials): Promise<AccessoryKeys>;
|
|
191
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* Callback for sending TLV8-encoded pair-setup/pair-verify requests.
|
|
403
|
+
* Implementations typically wrap HTTP POST or OPack frame sends.
|
|
404
|
+
*
|
|
405
|
+
* @param step - The pairing step identifier ('m1', 'm3', or 'm5').
|
|
406
|
+
* @param data - The TLV8-encoded request payload.
|
|
407
|
+
* @returns The TLV8-encoded response from the accessory.
|
|
408
|
+
*/
|
|
192
409
|
type RequestHandler = (step: 'm1' | 'm3' | 'm5', data: Buffer) => Promise<Buffer>;
|
|
410
|
+
/** Pair-Setup M1 result: the accessory's SRP public key and salt. */
|
|
193
411
|
type PairM1 = {
|
|
194
412
|
readonly publicKey: Buffer;
|
|
195
413
|
readonly salt: Buffer;
|
|
196
414
|
};
|
|
415
|
+
/** Pair-Setup M2 result: the client's SRP public key and proof. */
|
|
197
416
|
type PairM2 = {
|
|
198
417
|
readonly publicKey: Buffer;
|
|
199
418
|
readonly proof: Buffer;
|
|
200
419
|
};
|
|
420
|
+
/** Pair-Setup M3 result: the server's SRP proof. */
|
|
201
421
|
type PairM3 = {
|
|
202
422
|
readonly serverProof: Buffer;
|
|
203
423
|
};
|
|
424
|
+
/** Pair-Setup M4 result: the derived SRP shared secret. */
|
|
204
425
|
type PairM4 = {
|
|
205
426
|
readonly sharedSecret: Buffer;
|
|
206
427
|
};
|
|
428
|
+
/** Pair-Setup M5 result: the encrypted accessory response data and session key. */
|
|
207
429
|
type PairM5 = {
|
|
208
430
|
readonly authTag: Buffer;
|
|
209
431
|
readonly data: Buffer;
|
|
210
432
|
readonly sessionKey: Buffer;
|
|
211
433
|
};
|
|
434
|
+
/**
|
|
435
|
+
* Long-term pairing credentials obtained from a successful PIN-based pair-setup.
|
|
436
|
+
* Stored persistently and used for subsequent pair-verify sessions without
|
|
437
|
+
* requiring the PIN again.
|
|
438
|
+
*/
|
|
212
439
|
type AccessoryCredentials = {
|
|
213
|
-
readonly accessoryIdentifier: string;
|
|
214
|
-
readonly accessoryLongTermPublicKey: Buffer;
|
|
215
|
-
readonly pairingId: Buffer;
|
|
216
|
-
readonly publicKey: Buffer;
|
|
440
|
+
/** The accessory's unique identifier string. */readonly accessoryIdentifier: string; /** The accessory's Ed25519 long-term public key for signature verification. */
|
|
441
|
+
readonly accessoryLongTermPublicKey: Buffer; /** This controller's unique pairing identifier (UUID). */
|
|
442
|
+
readonly pairingId: Buffer; /** This controller's Ed25519 public key. */
|
|
443
|
+
readonly publicKey: Buffer; /** This controller's Ed25519 secret key for signing proofs. */
|
|
217
444
|
readonly secretKey: Buffer;
|
|
218
445
|
};
|
|
446
|
+
/**
|
|
447
|
+
* Session keys derived from a pairing flow (either transient pair-setup or pair-verify).
|
|
448
|
+
* Used to derive encryption keys for the subsequent encrypted connection.
|
|
449
|
+
*/
|
|
219
450
|
type AccessoryKeys = {
|
|
220
|
-
readonly pairingId: Buffer;
|
|
221
|
-
readonly sharedSecret: Buffer;
|
|
222
|
-
readonly accessoryToControllerKey: Buffer;
|
|
451
|
+
/** This controller's pairing identifier. */readonly pairingId: Buffer; /** The ECDH or SRP shared secret, root key for HKDF derivation. */
|
|
452
|
+
readonly sharedSecret: Buffer; /** Derived key for decrypting data sent by the accessory (may be empty after pair-verify). */
|
|
453
|
+
readonly accessoryToControllerKey: Buffer; /** Derived key for encrypting data sent to the accessory (may be empty after pair-verify). */
|
|
223
454
|
readonly controllerToAccessoryKey: Buffer;
|
|
224
455
|
};
|
|
225
456
|
//#endregion
|
|
226
457
|
//#region src/storage.d.ts
|
|
458
|
+
/** Protocol types that can have stored pairing credentials. */
|
|
227
459
|
type ProtocolType = 'airplay' | 'companionLink' | 'raop';
|
|
460
|
+
/** A device record stored in persistent storage. */
|
|
228
461
|
type StoredDevice = {
|
|
229
462
|
readonly identifier: string;
|
|
230
463
|
readonly name: string;
|
|
231
464
|
};
|
|
465
|
+
/** Top-level structure of the storage file, versioned for future migration. */
|
|
232
466
|
type StorageData = {
|
|
233
467
|
version: 1;
|
|
234
468
|
devices: Record<string, StoredDevice>;
|
|
235
469
|
credentials: Record<string, SerializedCredentials>;
|
|
236
470
|
};
|
|
471
|
+
/** Base64-serialized form of {@link AccessoryCredentials} for JSON persistence. */
|
|
237
472
|
type SerializedCredentials = {
|
|
238
473
|
readonly accessoryIdentifier: string;
|
|
239
474
|
readonly accessoryLongTermPublicKey: string;
|
|
@@ -241,36 +476,114 @@ type SerializedCredentials = {
|
|
|
241
476
|
readonly publicKey: string;
|
|
242
477
|
readonly secretKey: string;
|
|
243
478
|
};
|
|
479
|
+
/**
|
|
480
|
+
* Abstract base class for persistent storage of device registrations and
|
|
481
|
+
* pairing credentials. Subclasses implement the actual load/save mechanism.
|
|
482
|
+
*
|
|
483
|
+
* Credentials are stored keyed by "deviceId:protocol" to support per-protocol
|
|
484
|
+
* pairing (a device can have separate AirPlay and Companion Link credentials).
|
|
485
|
+
*/
|
|
244
486
|
declare abstract class Storage {
|
|
245
487
|
#private;
|
|
488
|
+
/** The current storage data. */
|
|
246
489
|
get data(): StorageData;
|
|
490
|
+
/** Loads storage data from the underlying persistence mechanism. */
|
|
247
491
|
abstract load(): Promise<void>;
|
|
492
|
+
/** Saves the current storage data to the underlying persistence mechanism. */
|
|
248
493
|
abstract save(): Promise<void>;
|
|
494
|
+
/**
|
|
495
|
+
* Replaces the internal data with the given storage data.
|
|
496
|
+
* Used by subclasses during load.
|
|
497
|
+
*
|
|
498
|
+
* @param data - The loaded storage data to set.
|
|
499
|
+
*/
|
|
249
500
|
protected setData(data: StorageData): void;
|
|
501
|
+
/**
|
|
502
|
+
* Retrieves a stored device by its identifier.
|
|
503
|
+
*
|
|
504
|
+
* @param identifier - The device identifier.
|
|
505
|
+
* @returns The stored device, or undefined if not found.
|
|
506
|
+
*/
|
|
250
507
|
getDevice(identifier: string): StoredDevice | undefined;
|
|
508
|
+
/**
|
|
509
|
+
* Stores or updates a device registration.
|
|
510
|
+
*
|
|
511
|
+
* @param identifier - The device identifier.
|
|
512
|
+
* @param device - The device data to store.
|
|
513
|
+
*/
|
|
251
514
|
setDevice(identifier: string, device: StoredDevice): void;
|
|
515
|
+
/**
|
|
516
|
+
* Removes a device and all its associated credentials from storage.
|
|
517
|
+
*
|
|
518
|
+
* @param identifier - The device identifier to remove.
|
|
519
|
+
*/
|
|
252
520
|
removeDevice(identifier: string): void;
|
|
521
|
+
/**
|
|
522
|
+
* Returns all stored devices.
|
|
523
|
+
*
|
|
524
|
+
* @returns An array of all stored device records.
|
|
525
|
+
*/
|
|
253
526
|
listDevices(): StoredDevice[];
|
|
527
|
+
/**
|
|
528
|
+
* Retrieves pairing credentials for a device and protocol combination.
|
|
529
|
+
*
|
|
530
|
+
* @param deviceId - The device identifier.
|
|
531
|
+
* @param protocol - The protocol type.
|
|
532
|
+
* @returns The deserialized credentials, or undefined if not found.
|
|
533
|
+
*/
|
|
254
534
|
getCredentials(deviceId: string, protocol: ProtocolType): AccessoryCredentials | undefined;
|
|
535
|
+
/**
|
|
536
|
+
* Stores pairing credentials for a device and protocol combination.
|
|
537
|
+
*
|
|
538
|
+
* @param deviceId - The device identifier.
|
|
539
|
+
* @param protocol - The protocol type.
|
|
540
|
+
* @param credentials - The credentials to store.
|
|
541
|
+
*/
|
|
255
542
|
setCredentials(deviceId: string, protocol: ProtocolType, credentials: AccessoryCredentials): void;
|
|
543
|
+
/**
|
|
544
|
+
* Removes pairing credentials for a device and protocol combination.
|
|
545
|
+
*
|
|
546
|
+
* @param deviceId - The device identifier.
|
|
547
|
+
* @param protocol - The protocol type.
|
|
548
|
+
*/
|
|
256
549
|
removeCredentials(deviceId: string, protocol: ProtocolType): void;
|
|
257
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* JSON file-based storage implementation. Persists data to a JSON file on disk,
|
|
553
|
+
* defaulting to `~/.config/apple-protocols/storage.json`.
|
|
554
|
+
*/
|
|
258
555
|
declare class JsonStorage extends Storage {
|
|
259
556
|
#private;
|
|
557
|
+
/**
|
|
558
|
+
* @param path - Optional custom file path. Defaults to `~/.config/apple-protocols/storage.json`.
|
|
559
|
+
*/
|
|
260
560
|
constructor(path?: string);
|
|
561
|
+
/** Loads storage data from the JSON file, if it exists. */
|
|
261
562
|
load(): Promise<void>;
|
|
563
|
+
/** Saves the current storage data to the JSON file, creating directories as needed. */
|
|
262
564
|
save(): Promise<void>;
|
|
263
565
|
}
|
|
566
|
+
/**
|
|
567
|
+
* In-memory storage implementation. Data is not persisted between sessions.
|
|
568
|
+
* Useful for testing or environments without filesystem access.
|
|
569
|
+
*/
|
|
264
570
|
declare class MemoryStorage extends Storage {
|
|
571
|
+
/** No-op: memory storage has nothing to load. */
|
|
265
572
|
load(): Promise<void>;
|
|
573
|
+
/** No-op: memory storage has nothing to persist. */
|
|
266
574
|
save(): Promise<void>;
|
|
267
575
|
}
|
|
268
576
|
//#endregion
|
|
269
577
|
//#region src/types.d.ts
|
|
578
|
+
/** Possible states of a TCP connection managed by {@link Connection}. */
|
|
270
579
|
type ConnectionState = 'closing' | 'connected' | 'connecting' | 'disconnected' | 'failed';
|
|
580
|
+
/** Generic event map type used as a constraint for typed EventEmitter subclasses. */
|
|
271
581
|
type EventMap = Record<string, any>;
|
|
582
|
+
/** DNS record class identifiers as defined in RFC 1035. */
|
|
272
583
|
type DnsRecordClass = 'IN' | 'CS' | 'CH' | 'HS' | 'ANY';
|
|
584
|
+
/** DNS record types relevant to mDNS service discovery. */
|
|
273
585
|
type DnsRecordType = 'A' | 'AAAA' | 'CNAME' | 'MX' | 'NS' | 'NSEC' | 'PTR' | 'SOA' | 'SRV' | 'TXT';
|
|
586
|
+
/** Base fields shared by all DNS resource records. */
|
|
274
587
|
type DnsRecordBase = {
|
|
275
588
|
readonly name: string;
|
|
276
589
|
readonly type: DnsRecordType;
|
|
@@ -278,23 +591,28 @@ type DnsRecordBase = {
|
|
|
278
591
|
readonly flash: boolean;
|
|
279
592
|
readonly ttl: number;
|
|
280
593
|
};
|
|
594
|
+
/** DNS A record containing an IPv4 address. */
|
|
281
595
|
type DnsRecordA = DnsRecordBase & {
|
|
282
596
|
readonly type: 'A';
|
|
283
597
|
readonly rdata: string;
|
|
284
598
|
};
|
|
599
|
+
/** DNS AAAA record containing an IPv6 address. */
|
|
285
600
|
type DnsRecordAAAA = DnsRecordBase & {
|
|
286
601
|
readonly type: 'AAAA';
|
|
287
602
|
readonly rdata: string;
|
|
288
603
|
};
|
|
604
|
+
/** DNS PTR record containing a domain name pointer. */
|
|
289
605
|
type DnsRecordPTR = DnsRecordBase & {
|
|
290
606
|
readonly type: 'PTR';
|
|
291
607
|
readonly rdata: string;
|
|
292
608
|
};
|
|
609
|
+
/** DNS TXT record containing key-value properties (used for mDNS service metadata). */
|
|
293
610
|
type DnsRecordTXT = DnsRecordBase & {
|
|
294
611
|
readonly type: 'TXT';
|
|
295
612
|
readonly rdata: Record<string, string>;
|
|
296
613
|
readonly rdata_buffer: Record<string, Buffer>;
|
|
297
614
|
};
|
|
615
|
+
/** DNS SRV record containing a service location (host, port, priority, weight). */
|
|
298
616
|
type DnsRecordSRV = DnsRecordBase & {
|
|
299
617
|
readonly type: 'SRV';
|
|
300
618
|
readonly rdata: {
|
|
@@ -304,11 +622,14 @@ type DnsRecordSRV = DnsRecordBase & {
|
|
|
304
622
|
readonly target: string;
|
|
305
623
|
};
|
|
306
624
|
};
|
|
625
|
+
/** DNS NSEC record containing next secure domain name. */
|
|
307
626
|
type DnsRecordNSEC = DnsRecordBase & {
|
|
308
627
|
readonly type: 'NSEC';
|
|
309
628
|
readonly rdata: string;
|
|
310
629
|
};
|
|
630
|
+
/** Union of all supported DNS record types. */
|
|
311
631
|
type DnsRecord = DnsRecordA | DnsRecordAAAA | DnsRecordPTR | DnsRecordTXT | DnsRecordSRV | DnsRecordNSEC;
|
|
632
|
+
/** Parsed DNS packet header fields. */
|
|
312
633
|
type DnsPacketHeader = {
|
|
313
634
|
readonly id: number;
|
|
314
635
|
readonly qr: number;
|
|
@@ -326,6 +647,7 @@ type DnsPacketHeader = {
|
|
|
326
647
|
readonly authorities: number;
|
|
327
648
|
readonly additionals: number;
|
|
328
649
|
};
|
|
650
|
+
/** A complete parsed DNS packet with header and all record sections. */
|
|
329
651
|
type DnsPacket = {
|
|
330
652
|
readonly address: string;
|
|
331
653
|
readonly header: DnsPacketHeader;
|
|
@@ -334,6 +656,7 @@ type DnsPacket = {
|
|
|
334
656
|
readonly authorities: DnsRecord[];
|
|
335
657
|
readonly additionals: DnsRecord[];
|
|
336
658
|
};
|
|
659
|
+
/** Base discovery result from an mDNS service query. */
|
|
337
660
|
type Result = {
|
|
338
661
|
readonly fqdn: string;
|
|
339
662
|
readonly address: string;
|
|
@@ -347,11 +670,16 @@ type Result = {
|
|
|
347
670
|
readonly packet: DnsPacket;
|
|
348
671
|
readonly [key: string]: unknown;
|
|
349
672
|
};
|
|
673
|
+
/** Extended discovery result with device identifier, TXT record properties, and parsed feature flags. */
|
|
350
674
|
type DiscoveryResult = {
|
|
351
675
|
readonly id: string;
|
|
352
676
|
readonly txt: Record<string, string>;
|
|
353
677
|
readonly features?: bigint;
|
|
354
678
|
} & Result;
|
|
679
|
+
/**
|
|
680
|
+
* Aggregated discovery result combining AirPlay, Companion Link, and RAOP
|
|
681
|
+
* service information for a single physical device.
|
|
682
|
+
*/
|
|
355
683
|
type CombinedDiscoveryResult = {
|
|
356
684
|
readonly id: string;
|
|
357
685
|
readonly name: string;
|
|
@@ -362,20 +690,78 @@ type CombinedDiscoveryResult = {
|
|
|
362
690
|
};
|
|
363
691
|
//#endregion
|
|
364
692
|
//#region src/discovery.d.ts
|
|
693
|
+
/**
|
|
694
|
+
* mDNS service discovery for Apple devices on the local network.
|
|
695
|
+
*
|
|
696
|
+
* Supports discovering AirPlay, Companion Link, and RAOP services via multicast DNS.
|
|
697
|
+
* Results are cached for 30 seconds to avoid excessive network traffic.
|
|
698
|
+
* Use the static factory methods {@link Discovery.airplay}, {@link Discovery.companionLink},
|
|
699
|
+
* and {@link Discovery.raop} for convenience.
|
|
700
|
+
*/
|
|
365
701
|
declare class Discovery {
|
|
366
702
|
#private;
|
|
703
|
+
/**
|
|
704
|
+
* @param service - The mDNS service type to discover (e.g. '_airplay._tcp.local').
|
|
705
|
+
*/
|
|
367
706
|
constructor(service: string);
|
|
707
|
+
/**
|
|
708
|
+
* Discovers devices advertising this service type via mDNS multicast.
|
|
709
|
+
* Returns cached results if available and not expired.
|
|
710
|
+
*
|
|
711
|
+
* @param useCache - Whether to use cached results. Defaults to true.
|
|
712
|
+
* @returns An array of discovered devices.
|
|
713
|
+
*/
|
|
368
714
|
find(useCache?: boolean): Promise<DiscoveryResult[]>;
|
|
715
|
+
/**
|
|
716
|
+
* Repeatedly searches for a specific device by ID until found or retries are exhausted.
|
|
717
|
+
* Does not use the cache to ensure fresh results on each attempt.
|
|
718
|
+
*
|
|
719
|
+
* @param id - The device ID to search for.
|
|
720
|
+
* @param tries - Maximum number of discovery attempts. Defaults to 10.
|
|
721
|
+
* @param timeout - Delay in milliseconds between attempts. Defaults to 1000.
|
|
722
|
+
* @returns The discovered device.
|
|
723
|
+
* @throws {DiscoveryError} If the device is not found after all attempts.
|
|
724
|
+
*/
|
|
369
725
|
findUntil(id: string, tries?: number, timeout?: number): Promise<DiscoveryResult>;
|
|
726
|
+
/** Clears all cached discovery results across all service types. */
|
|
370
727
|
static clearCache(): void;
|
|
728
|
+
/**
|
|
729
|
+
* Attempts to wake a sleeping Apple device by knocking on well-known ports.
|
|
730
|
+
* Sends TCP connection attempts to ports 7000, 3689, 49152, and 32498.
|
|
731
|
+
*
|
|
732
|
+
* @param address - The IP address of the device to wake.
|
|
733
|
+
*/
|
|
371
734
|
static wake(address: string): Promise<void>;
|
|
735
|
+
/**
|
|
736
|
+
* Discovers all Apple devices on the network across all supported service types
|
|
737
|
+
* (AirPlay, Companion Link, RAOP) and merges them by device ID.
|
|
738
|
+
*
|
|
739
|
+
* @returns An array of combined results, each representing a single physical device
|
|
740
|
+
* with its available service endpoints.
|
|
741
|
+
*/
|
|
372
742
|
static discoverAll(): Promise<CombinedDiscoveryResult[]>;
|
|
743
|
+
/**
|
|
744
|
+
* Creates a Discovery instance for AirPlay services.
|
|
745
|
+
*
|
|
746
|
+
* @returns A new Discovery instance targeting `_airplay._tcp.local`.
|
|
747
|
+
*/
|
|
373
748
|
static airplay(): Discovery;
|
|
749
|
+
/**
|
|
750
|
+
* Creates a Discovery instance for Companion Link services.
|
|
751
|
+
*
|
|
752
|
+
* @returns A new Discovery instance targeting `_companion-link._tcp.local`.
|
|
753
|
+
*/
|
|
374
754
|
static companionLink(): Discovery;
|
|
755
|
+
/**
|
|
756
|
+
* Creates a Discovery instance for RAOP services.
|
|
757
|
+
*
|
|
758
|
+
* @returns A new Discovery instance targeting `_raop._tcp.local`.
|
|
759
|
+
*/
|
|
375
760
|
static raop(): Discovery;
|
|
376
761
|
}
|
|
377
762
|
//#endregion
|
|
378
763
|
//#region src/mdns.d.ts
|
|
764
|
+
/** A resolved mDNS service with its name, type, address, port, and TXT properties. */
|
|
379
765
|
type MdnsService = {
|
|
380
766
|
readonly name: string;
|
|
381
767
|
readonly type: string;
|
|
@@ -383,14 +769,50 @@ type MdnsService = {
|
|
|
383
769
|
readonly port: number;
|
|
384
770
|
readonly properties: Record<string, string>;
|
|
385
771
|
};
|
|
772
|
+
/**
|
|
773
|
+
* Performs unicast DNS-SD queries to specific hosts. First wakes the devices
|
|
774
|
+
* via TCP knocking, then repeatedly sends DNS queries via UDP to port 5353 on
|
|
775
|
+
* each host, collecting responses for the specified duration.
|
|
776
|
+
*
|
|
777
|
+
* @param hosts - IP addresses of the specific devices to query.
|
|
778
|
+
* @param services - mDNS service types to discover.
|
|
779
|
+
* @param timeout - Discovery duration in seconds. Defaults to 4.
|
|
780
|
+
* @returns An array of resolved mDNS services.
|
|
781
|
+
*/
|
|
386
782
|
declare function unicast(hosts: string[], services: string[], timeout?: number): Promise<MdnsService[]>;
|
|
783
|
+
/**
|
|
784
|
+
* Performs multicast DNS-SD discovery on the local network. Creates UDP sockets
|
|
785
|
+
* on all network interfaces, joins the mDNS multicast group (224.0.0.251),
|
|
786
|
+
* and sends periodic queries for the specified duration.
|
|
787
|
+
*
|
|
788
|
+
* Creates two types of sockets:
|
|
789
|
+
* - One on 0.0.0.0:5353 to receive multicast responses (may fail on some platforms)
|
|
790
|
+
* - One per local network interface on a random port with multicast membership
|
|
791
|
+
*
|
|
792
|
+
* @param services - mDNS service types to discover.
|
|
793
|
+
* @param timeout - Discovery duration in seconds. Defaults to 4.
|
|
794
|
+
* @returns An array of resolved mDNS services found on the network.
|
|
795
|
+
*/
|
|
387
796
|
declare function multicast(services: string[], timeout?: number): Promise<MdnsService[]>;
|
|
388
797
|
//#endregion
|
|
389
798
|
//#region src/cli.d.ts
|
|
799
|
+
/**
|
|
800
|
+
* Prompts the user for input via stdin and returns their response.
|
|
801
|
+
*
|
|
802
|
+
* @param message - The message to display before the input cursor.
|
|
803
|
+
* @returns The user's input string.
|
|
804
|
+
*/
|
|
390
805
|
declare function prompt(message: string): Promise<string>;
|
|
806
|
+
/**
|
|
807
|
+
* Returns a promise that resolves after the specified delay.
|
|
808
|
+
* Commonly used for timing gaps in HID press/release sequences.
|
|
809
|
+
*
|
|
810
|
+
* @param ms - The delay in milliseconds.
|
|
811
|
+
*/
|
|
391
812
|
declare function waitFor(ms: number): Promise<void>;
|
|
392
813
|
//#endregion
|
|
393
814
|
//#region src/connection.d.ts
|
|
815
|
+
/** Event map for the base Connection class socket events. */
|
|
394
816
|
type ConnectionEventMap = {
|
|
395
817
|
close: [hadError: boolean];
|
|
396
818
|
connect: [];
|
|
@@ -399,89 +821,325 @@ type ConnectionEventMap = {
|
|
|
399
821
|
error: [err: Error];
|
|
400
822
|
timeout: [];
|
|
401
823
|
};
|
|
824
|
+
/**
|
|
825
|
+
* TCP socket connection wrapper with built-in retry logic and typed events.
|
|
826
|
+
*
|
|
827
|
+
* Manages a single TCP socket to an Apple device, providing automatic reconnection
|
|
828
|
+
* on failure (configurable attempts and interval), keep-alive, and no-delay settings.
|
|
829
|
+
* Subclasses can extend the event map with protocol-specific events.
|
|
830
|
+
*
|
|
831
|
+
* Default retry behavior: 3 attempts with 3-second intervals between retries.
|
|
832
|
+
*/
|
|
402
833
|
declare class Connection<TEventMap extends EventMap = {}> extends EventEmitter<ConnectionEventMap & TEventMap> {
|
|
403
834
|
#private;
|
|
835
|
+
/** The remote IP address this connection targets. */
|
|
404
836
|
get address(): string;
|
|
837
|
+
/** The shared context carrying device identity and logger. */
|
|
405
838
|
get context(): Context;
|
|
839
|
+
/** The remote port this connection targets. */
|
|
406
840
|
get port(): number;
|
|
841
|
+
/** Whether the connection is currently established and open. */
|
|
407
842
|
get isConnected(): boolean;
|
|
843
|
+
/** The local IP address of the socket, or '0.0.0.0' if not connected. */
|
|
844
|
+
get localAddress(): string;
|
|
845
|
+
/** The current connection state, derived from both internal state and socket readyState. */
|
|
408
846
|
get state(): ConnectionState;
|
|
847
|
+
/**
|
|
848
|
+
* @param context - Shared context with device identity and logger.
|
|
849
|
+
* @param address - The remote IP address to connect to.
|
|
850
|
+
* @param port - The remote port to connect to.
|
|
851
|
+
*/
|
|
409
852
|
constructor(context: Context, address: string, port: number);
|
|
853
|
+
/**
|
|
854
|
+
* Establishes a TCP connection to the remote address. If already connected,
|
|
855
|
+
* returns immediately. Enables retry logic for the duration of this connection.
|
|
856
|
+
*
|
|
857
|
+
* @throws {ConnectionError} If already connecting or all retry attempts are exhausted.
|
|
858
|
+
*/
|
|
410
859
|
connect(): Promise<void>;
|
|
860
|
+
/** Immediately destroys the underlying socket without graceful shutdown. */
|
|
411
861
|
destroy(): void;
|
|
862
|
+
/**
|
|
863
|
+
* Gracefully disconnects by ending the socket and waiting for the 'close' event.
|
|
864
|
+
* Disables retry logic so the connection does not automatically reconnect.
|
|
865
|
+
*/
|
|
412
866
|
disconnect(): Promise<void>;
|
|
867
|
+
/**
|
|
868
|
+
* Enables or disables debug logging for incoming data (hex + ASCII dumps).
|
|
869
|
+
*
|
|
870
|
+
* @param enabled - Whether to enable debug output.
|
|
871
|
+
* @returns This connection instance for chaining.
|
|
872
|
+
*/
|
|
413
873
|
debug(enabled: boolean): this;
|
|
874
|
+
/**
|
|
875
|
+
* Configures the retry behavior for connection attempts.
|
|
876
|
+
*
|
|
877
|
+
* @param attempts - Maximum number of retry attempts.
|
|
878
|
+
* @param interval - Delay in milliseconds between retry attempts.
|
|
879
|
+
* @returns This connection instance for chaining.
|
|
880
|
+
*/
|
|
414
881
|
retry(attempts: number, interval?: number): this;
|
|
882
|
+
/**
|
|
883
|
+
* Writes data to the underlying TCP socket.
|
|
884
|
+
* Emits an error event if the socket is not writable.
|
|
885
|
+
*
|
|
886
|
+
* @param data - The data to send.
|
|
887
|
+
*/
|
|
415
888
|
write(data: Buffer | Uint8Array): void;
|
|
889
|
+
/**
|
|
890
|
+
* Handles the socket 'close' event. If the connection was active and closed
|
|
891
|
+
* unexpectedly with an error, triggers a retry.
|
|
892
|
+
*
|
|
893
|
+
* @param hadError - Whether the close was caused by an error.
|
|
894
|
+
*/
|
|
895
|
+
onClose(hadError: boolean): void;
|
|
896
|
+
/**
|
|
897
|
+
* Handles successful TCP connection. Enables keep-alive (10s interval),
|
|
898
|
+
* disables the connection timeout, resets retry counter, and resolves the connect promise.
|
|
899
|
+
*/
|
|
900
|
+
onConnect(): void;
|
|
901
|
+
/**
|
|
902
|
+
* Handles incoming data from the socket. When debug mode is enabled,
|
|
903
|
+
* logs a hex and ASCII dump of the first 64 bytes.
|
|
904
|
+
*
|
|
905
|
+
* @param data - The received data buffer.
|
|
906
|
+
*/
|
|
907
|
+
onData(data: Buffer): void;
|
|
908
|
+
/** Handles the socket 'end' event (remote end sent FIN). */
|
|
909
|
+
onEnd(): void;
|
|
910
|
+
/**
|
|
911
|
+
* Handles socket errors. If connecting, schedules a retry; otherwise marks
|
|
912
|
+
* the connection as failed. Warns if no error listener is registered.
|
|
913
|
+
*
|
|
914
|
+
* @param err - The socket error.
|
|
915
|
+
*/
|
|
916
|
+
onError(err: Error): void;
|
|
917
|
+
/**
|
|
918
|
+
* Handles socket timeout. If connecting, schedules a retry;
|
|
919
|
+
* otherwise destroys the socket and marks the connection as failed.
|
|
920
|
+
*/
|
|
921
|
+
onTimeout(): void;
|
|
416
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Connection subclass that adds optional ChaCha20-Poly1305 encryption.
|
|
925
|
+
* Once encryption is enabled, subclasses use the {@link EncryptionState}
|
|
926
|
+
* to encrypt outgoing data and decrypt incoming data with per-message nonce counters.
|
|
927
|
+
*/
|
|
417
928
|
declare class EncryptionAwareConnection<TEventMap extends EventMap> extends Connection<TEventMap> {
|
|
929
|
+
/** Whether encryption has been enabled on this connection. */
|
|
418
930
|
get isEncrypted(): boolean;
|
|
931
|
+
/** The current encryption state, or undefined if encryption is not enabled. */
|
|
419
932
|
_encryption?: EncryptionState;
|
|
933
|
+
/**
|
|
934
|
+
* Enables ChaCha20-Poly1305 encryption for this connection.
|
|
935
|
+
* After calling this, all subsequent data must be encrypted/decrypted
|
|
936
|
+
* using the provided keys.
|
|
937
|
+
*
|
|
938
|
+
* @param readKey - The 32-byte key for decrypting incoming data.
|
|
939
|
+
* @param writeKey - The 32-byte key for encrypting outgoing data.
|
|
940
|
+
*/
|
|
420
941
|
enableEncryption(readKey: Buffer, writeKey: Buffer): void;
|
|
421
942
|
}
|
|
943
|
+
/**
|
|
944
|
+
* Holds the symmetric encryption keys and nonce counters for a single
|
|
945
|
+
* encrypted connection. Each message increments the corresponding counter
|
|
946
|
+
* to ensure unique nonces for ChaCha20-Poly1305.
|
|
947
|
+
*/
|
|
422
948
|
declare class EncryptionState {
|
|
949
|
+
/** The 32-byte key used to decrypt incoming data. */
|
|
423
950
|
readKey: Buffer;
|
|
951
|
+
/** Monotonically increasing counter used as part of the read nonce. */
|
|
424
952
|
readCount: number;
|
|
953
|
+
/** The 32-byte key used to encrypt outgoing data. */
|
|
425
954
|
writeKey: Buffer;
|
|
955
|
+
/** Monotonically increasing counter used as part of the write nonce. */
|
|
426
956
|
writeCount: number;
|
|
957
|
+
/**
|
|
958
|
+
* @param readKey - The 32-byte decryption key.
|
|
959
|
+
* @param writeKey - The 32-byte encryption key.
|
|
960
|
+
*/
|
|
427
961
|
constructor(readKey: Buffer, writeKey: Buffer);
|
|
428
962
|
}
|
|
429
963
|
//#endregion
|
|
430
964
|
//#region src/const.d.ts
|
|
965
|
+
/** Default PIN used for transient (non-persistent) AirPlay pairing sessions. */
|
|
431
966
|
declare const AIRPLAY_TRANSIENT_PIN = "3939";
|
|
967
|
+
/** Timeout in milliseconds for HTTP requests during setup and control. */
|
|
432
968
|
declare const HTTP_TIMEOUT = 6000;
|
|
969
|
+
/** mDNS service type for AirPlay device discovery. */
|
|
433
970
|
declare const AIRPLAY_SERVICE = "_airplay._tcp.local";
|
|
971
|
+
/** mDNS service type for Companion Link (remote control protocol) device discovery. */
|
|
434
972
|
declare const COMPANION_LINK_SERVICE = "_companion-link._tcp.local";
|
|
973
|
+
/** mDNS service type for RAOP (Remote Audio Output Protocol) device discovery. */
|
|
435
974
|
declare const RAOP_SERVICE = "_raop._tcp.local";
|
|
436
975
|
//#endregion
|
|
437
976
|
//#region src/symbols.d.ts
|
|
977
|
+
/**
|
|
978
|
+
* Unique symbol used as a key for accessing encryption state on connection instances.
|
|
979
|
+
* Provides type-safe access to internal encryption fields without exposing them publicly.
|
|
980
|
+
*/
|
|
438
981
|
declare const ENCRYPTION: unique symbol;
|
|
439
982
|
//#endregion
|
|
440
983
|
//#region src/recovery.d.ts
|
|
984
|
+
/** Events emitted by {@link ConnectionRecovery}. */
|
|
441
985
|
type EventMap$1 = {
|
|
442
986
|
recovering: [attempt: number];
|
|
443
987
|
recovered: [];
|
|
444
988
|
failed: [errors: Error[]];
|
|
445
989
|
};
|
|
990
|
+
/** Configuration options for {@link ConnectionRecovery}. */
|
|
446
991
|
type ConnectionRecoveryOptions = {
|
|
447
|
-
maxAttempts?: number;
|
|
448
|
-
baseDelay?: number;
|
|
449
|
-
maxDelay?: number;
|
|
450
|
-
useExponentialBackoff?: boolean;
|
|
451
|
-
reconnectInterval?: number;
|
|
992
|
+
/** Maximum number of recovery attempts before giving up. Defaults to 3. */maxAttempts?: number; /** Base delay in milliseconds for the first retry. Defaults to 1000. */
|
|
993
|
+
baseDelay?: number; /** Maximum delay in milliseconds when using exponential backoff. Defaults to 30000. */
|
|
994
|
+
maxDelay?: number; /** Whether to use exponential backoff (delay doubles each attempt). Defaults to true. */
|
|
995
|
+
useExponentialBackoff?: boolean; /** If set to a positive value, periodically calls onReconnect at this interval (ms). Defaults to 0 (disabled). */
|
|
996
|
+
reconnectInterval?: number; /** Callback that performs the actual reconnection. Called during recovery and scheduled reconnects. */
|
|
452
997
|
onReconnect: () => Promise<void>;
|
|
453
998
|
};
|
|
999
|
+
/**
|
|
1000
|
+
* Manages automatic connection recovery with exponential backoff.
|
|
1001
|
+
*
|
|
1002
|
+
* When an unexpected disconnect occurs, this class schedules retry attempts
|
|
1003
|
+
* with configurable delay (exponential backoff by default: base=1s, max=30s).
|
|
1004
|
+
* Emits 'recovering', 'recovered', and 'failed' events for monitoring.
|
|
1005
|
+
*
|
|
1006
|
+
* Optionally supports a periodic reconnect interval for proactive
|
|
1007
|
+
* connection health checks (failures are silent; unexpected disconnects
|
|
1008
|
+
* trigger the full recovery flow).
|
|
1009
|
+
*/
|
|
454
1010
|
declare class ConnectionRecovery extends EventEmitter<EventMap$1> {
|
|
455
1011
|
#private;
|
|
1012
|
+
/**
|
|
1013
|
+
* @param options - Recovery configuration including the reconnect callback.
|
|
1014
|
+
*/
|
|
456
1015
|
constructor(options: ConnectionRecoveryOptions);
|
|
1016
|
+
/** Whether a recovery attempt is currently in progress. */
|
|
457
1017
|
get isRecovering(): boolean;
|
|
1018
|
+
/** The current retry attempt number (0 when not recovering). */
|
|
458
1019
|
get attempt(): number;
|
|
1020
|
+
/**
|
|
1021
|
+
* Called when a disconnect is detected. Only triggers recovery for
|
|
1022
|
+
* unexpected disconnects; intentional disconnects are ignored.
|
|
1023
|
+
*
|
|
1024
|
+
* @param unexpected - Whether the disconnect was unexpected (e.g. socket error).
|
|
1025
|
+
*/
|
|
459
1026
|
handleDisconnect(unexpected: boolean): void;
|
|
1027
|
+
/** Resets the recovery state and restarts the periodic reconnect interval if configured. */
|
|
460
1028
|
reset(): void;
|
|
1029
|
+
/** Permanently disposes this recovery instance, cancelling all timers and removing listeners. */
|
|
461
1030
|
dispose(): void;
|
|
462
1031
|
}
|
|
463
1032
|
//#endregion
|
|
464
1033
|
//#region src/timing.d.ts
|
|
1034
|
+
/**
|
|
1035
|
+
* NTP timing server for AirPlay audio synchronization.
|
|
1036
|
+
*
|
|
1037
|
+
* Apple devices send NTP timing requests to synchronize their clocks with the
|
|
1038
|
+
* controller during audio streaming. This server responds with the current
|
|
1039
|
+
* wall-clock time using NTP packet format, enabling the device to calculate
|
|
1040
|
+
* the correct playback offset for synchronized multi-room audio.
|
|
1041
|
+
*
|
|
1042
|
+
* Must use wall-clock time (Date.now), not monotonic time (process.hrtime),
|
|
1043
|
+
* because NTP timestamps are anchored to the Unix epoch.
|
|
1044
|
+
*/
|
|
465
1045
|
declare class TimingServer {
|
|
466
1046
|
#private;
|
|
1047
|
+
/** The UDP port the timing server is listening on, or 0 if not yet bound. */
|
|
467
1048
|
get port(): number;
|
|
468
1049
|
constructor();
|
|
1050
|
+
/** Closes the UDP socket and resets the port. */
|
|
469
1051
|
close(): void;
|
|
1052
|
+
/**
|
|
1053
|
+
* Binds the UDP socket to a random available port and starts listening
|
|
1054
|
+
* for NTP timing requests.
|
|
1055
|
+
*
|
|
1056
|
+
* @throws If the socket fails to bind.
|
|
1057
|
+
*/
|
|
470
1058
|
listen(): Promise<void>;
|
|
1059
|
+
/**
|
|
1060
|
+
* Handles the socket 'connect' event by configuring buffer sizes.
|
|
1061
|
+
*/
|
|
1062
|
+
onConnect(): void;
|
|
1063
|
+
/**
|
|
1064
|
+
* Handles socket errors by logging them.
|
|
1065
|
+
*
|
|
1066
|
+
* @param err - The error that occurred.
|
|
1067
|
+
*/
|
|
1068
|
+
onError(err: Error): void;
|
|
1069
|
+
/**
|
|
1070
|
+
* Handles incoming NTP timing requests from Apple devices.
|
|
1071
|
+
* Decodes the request, captures the current NTP timestamp, and sends back
|
|
1072
|
+
* a response with reference, receive, and send timestamps populated.
|
|
1073
|
+
*
|
|
1074
|
+
* @param data - The raw UDP packet data.
|
|
1075
|
+
* @param info - Remote address information of the sender.
|
|
1076
|
+
*/
|
|
1077
|
+
onMessage(data: Buffer, info: RemoteInfo): void;
|
|
471
1078
|
}
|
|
472
1079
|
//#endregion
|
|
473
1080
|
//#region src/utils.d.ts
|
|
1081
|
+
/**
|
|
1082
|
+
* Generates a random Active-Remote identifier for DACP (Digital Audio Control Protocol).
|
|
1083
|
+
* Used in RTSP headers to identify the remote controller.
|
|
1084
|
+
*
|
|
1085
|
+
* @returns A random 32-bit unsigned integer as a decimal string.
|
|
1086
|
+
*/
|
|
474
1087
|
declare function generateActiveRemoteId(): string;
|
|
1088
|
+
/**
|
|
1089
|
+
* Generates a random DACP-ID for identifying this controller in DACP sessions.
|
|
1090
|
+
*
|
|
1091
|
+
* @returns A random 64-bit integer as an uppercase hexadecimal string.
|
|
1092
|
+
*/
|
|
475
1093
|
declare function generateDacpId(): string;
|
|
1094
|
+
/**
|
|
1095
|
+
* Generates a random session identifier for RTSP and AirPlay sessions.
|
|
1096
|
+
*
|
|
1097
|
+
* @returns A random 32-bit unsigned integer as a decimal string.
|
|
1098
|
+
*/
|
|
476
1099
|
declare function generateSessionId(): string;
|
|
1100
|
+
/**
|
|
1101
|
+
* Finds the first non-internal IPv4 address on this machine.
|
|
1102
|
+
*
|
|
1103
|
+
* @returns The local IPv4 address, or null if none is found.
|
|
1104
|
+
*/
|
|
477
1105
|
declare function getLocalIP(): string | null;
|
|
1106
|
+
/**
|
|
1107
|
+
* Finds the first non-internal MAC address on this machine.
|
|
1108
|
+
*
|
|
1109
|
+
* @returns The MAC address in uppercase colon-separated format, or '00:00:00:00:00:00' if none is found.
|
|
1110
|
+
*/
|
|
478
1111
|
declare function getMacAddress(): string;
|
|
1112
|
+
/**
|
|
1113
|
+
* Generates a cryptographically random 32-bit unsigned integer.
|
|
1114
|
+
*
|
|
1115
|
+
* @returns A random unsigned 32-bit integer.
|
|
1116
|
+
*/
|
|
479
1117
|
declare function randomInt32(): number;
|
|
1118
|
+
/**
|
|
1119
|
+
* Generates a cryptographically random 64-bit unsigned integer.
|
|
1120
|
+
*
|
|
1121
|
+
* @returns A random unsigned 64-bit bigint.
|
|
1122
|
+
*/
|
|
480
1123
|
declare function randomInt64(): bigint;
|
|
1124
|
+
/**
|
|
1125
|
+
* Encodes a 16-bit unsigned integer into a big-endian buffer.
|
|
1126
|
+
*
|
|
1127
|
+
* @param value - The 16-bit unsigned integer to encode.
|
|
1128
|
+
* @returns A 2-byte buffer containing the value in big-endian byte order.
|
|
1129
|
+
*/
|
|
481
1130
|
declare function uint16ToBE(value: number): Buffer;
|
|
1131
|
+
/**
|
|
1132
|
+
* Encodes a 53-bit unsigned integer into an 8-byte little-endian buffer.
|
|
1133
|
+
* Useful for encoding JavaScript-safe integers into 64-bit wire formats.
|
|
1134
|
+
*
|
|
1135
|
+
* @param value - The unsigned integer to encode (must be in range [0, 2^53-1]).
|
|
1136
|
+
* @returns An 8-byte buffer containing the value in little-endian byte order.
|
|
1137
|
+
* @throws If the value is out of range or not an integer.
|
|
1138
|
+
*/
|
|
482
1139
|
declare function uint53ToLE(value: number): Buffer;
|
|
483
1140
|
//#endregion
|
|
484
1141
|
//#region src/deviceModel.d.ts
|
|
1142
|
+
/** Known Apple device models that can be discovered and controlled via AirPlay/Companion Link. */
|
|
485
1143
|
declare enum DeviceModel {
|
|
486
1144
|
Unknown = 0,
|
|
487
1145
|
AppleTVGen2 = 1,
|
|
@@ -496,70 +1154,165 @@ declare enum DeviceModel {
|
|
|
496
1154
|
AirPortExpress = 20,
|
|
497
1155
|
AirPortExpressGen2 = 21
|
|
498
1156
|
}
|
|
1157
|
+
/** High-level device categories derived from the specific device model. */
|
|
499
1158
|
declare enum DeviceType {
|
|
500
1159
|
Unknown = 0,
|
|
501
1160
|
AppleTV = 1,
|
|
502
1161
|
HomePod = 2,
|
|
503
1162
|
AirPort = 3
|
|
504
1163
|
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Resolves an Apple model identifier or internal code name to a known device model.
|
|
1166
|
+
*
|
|
1167
|
+
* @param identifier - Model identifier (e.g. "AppleTV6,2") or internal name (e.g. "J305AP").
|
|
1168
|
+
* @returns The matching device model, or {@link DeviceModel.Unknown} if unrecognized.
|
|
1169
|
+
*/
|
|
505
1170
|
declare const lookupDeviceModel: (identifier: string) => DeviceModel;
|
|
1171
|
+
/**
|
|
1172
|
+
* Returns the human-readable display name for a device model.
|
|
1173
|
+
*
|
|
1174
|
+
* @param model - The device model to look up.
|
|
1175
|
+
* @returns A display name like "Apple TV 4K (2nd generation)", or "Unknown".
|
|
1176
|
+
*/
|
|
506
1177
|
declare const getDeviceModelName: (model: DeviceModel) => string;
|
|
1178
|
+
/**
|
|
1179
|
+
* Returns the high-level device type category for a device model.
|
|
1180
|
+
*
|
|
1181
|
+
* @param model - The device model to categorize.
|
|
1182
|
+
* @returns The device type (AppleTV, HomePod, AirPort, or Unknown).
|
|
1183
|
+
*/
|
|
507
1184
|
declare const getDeviceType: (model: DeviceModel) => DeviceType;
|
|
1185
|
+
/**
|
|
1186
|
+
* Checks whether the given model is an Apple TV.
|
|
1187
|
+
*
|
|
1188
|
+
* @param model - The device model to check.
|
|
1189
|
+
* @returns True if the model is any Apple TV generation.
|
|
1190
|
+
*/
|
|
508
1191
|
declare const isAppleTV: (model: DeviceModel) => boolean;
|
|
1192
|
+
/**
|
|
1193
|
+
* Checks whether the given model is a HomePod.
|
|
1194
|
+
*
|
|
1195
|
+
* @param model - The device model to check.
|
|
1196
|
+
* @returns True if the model is any HomePod variant.
|
|
1197
|
+
*/
|
|
509
1198
|
declare const isHomePod: (model: DeviceModel) => boolean;
|
|
1199
|
+
/**
|
|
1200
|
+
* Checks whether the given model is an AirPort Express.
|
|
1201
|
+
*
|
|
1202
|
+
* @param model - The device model to check.
|
|
1203
|
+
* @returns True if the model is any AirPort Express generation.
|
|
1204
|
+
*/
|
|
510
1205
|
declare const isAirPort: (model: DeviceModel) => boolean;
|
|
511
1206
|
//#endregion
|
|
512
1207
|
//#region src/errors.d.ts
|
|
1208
|
+
/**
|
|
1209
|
+
* Base error class for all Apple protocol errors.
|
|
1210
|
+
* All domain-specific errors in this library extend from this class,
|
|
1211
|
+
* enabling consumers to catch any protocol error with a single handler.
|
|
1212
|
+
*/
|
|
513
1213
|
declare class AppleProtocolError extends Error {
|
|
1214
|
+
/** @param message - Human-readable description of the error. */
|
|
514
1215
|
constructor(message: string);
|
|
515
1216
|
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Thrown when a TCP connection cannot be established or encounters a fatal error.
|
|
1219
|
+
* Parent class for more specific connection errors.
|
|
1220
|
+
*/
|
|
516
1221
|
declare class ConnectionError extends AppleProtocolError {
|
|
1222
|
+
/** @param message - Human-readable description of the connection failure. */
|
|
517
1223
|
constructor(message: string);
|
|
518
1224
|
}
|
|
1225
|
+
/** Thrown when a TCP connection attempt exceeds the configured socket timeout. */
|
|
519
1226
|
declare class ConnectionTimeoutError extends ConnectionError {
|
|
1227
|
+
/** @param message - Optional custom message; defaults to a standard timeout message. */
|
|
520
1228
|
constructor(message?: string);
|
|
521
1229
|
}
|
|
1230
|
+
/** Thrown when a TCP connection is closed unexpectedly by the remote end or the OS. */
|
|
522
1231
|
declare class ConnectionClosedError extends ConnectionError {
|
|
1232
|
+
/** @param message - Optional custom message; defaults to a standard closed message. */
|
|
523
1233
|
constructor(message?: string);
|
|
524
1234
|
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Thrown when a pairing operation fails during the HAP pair-setup or pair-verify flow.
|
|
1237
|
+
* Parent class for authentication and credentials errors.
|
|
1238
|
+
*/
|
|
525
1239
|
declare class PairingError extends AppleProtocolError {
|
|
1240
|
+
/** @param message - Human-readable description of the pairing failure. */
|
|
526
1241
|
constructor(message: string);
|
|
527
1242
|
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Thrown when the accessory's identity verification fails, such as an invalid
|
|
1245
|
+
* Ed25519 signature or mismatched accessory identifier during pair-verify.
|
|
1246
|
+
*/
|
|
528
1247
|
declare class AuthenticationError extends PairingError {
|
|
1248
|
+
/** @param message - Human-readable description of the authentication failure. */
|
|
529
1249
|
constructor(message: string);
|
|
530
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Thrown when stored credentials are invalid, missing, or incompatible
|
|
1253
|
+
* with the accessory (e.g. after a factory reset).
|
|
1254
|
+
*/
|
|
531
1255
|
declare class CredentialsError extends PairingError {
|
|
1256
|
+
/** @param message - Human-readable description of the credentials issue. */
|
|
532
1257
|
constructor(message: string);
|
|
533
1258
|
}
|
|
1259
|
+
/** Thrown when a protocol command fails to execute on the target device. */
|
|
534
1260
|
declare class CommandError extends AppleProtocolError {
|
|
1261
|
+
/** @param message - Human-readable description of the command failure. */
|
|
535
1262
|
constructor(message: string);
|
|
536
1263
|
}
|
|
1264
|
+
/** Thrown when a protocol setup step fails (e.g. RTSP SETUP, AirPlay stream setup). */
|
|
537
1265
|
declare class SetupError extends AppleProtocolError {
|
|
1266
|
+
/** @param message - Human-readable description of the setup failure. */
|
|
538
1267
|
constructor(message: string);
|
|
539
1268
|
}
|
|
1269
|
+
/** Thrown when mDNS device discovery fails or a device cannot be found after retries. */
|
|
540
1270
|
declare class DiscoveryError extends AppleProtocolError {
|
|
1271
|
+
/** @param message - Human-readable description of the discovery failure. */
|
|
541
1272
|
constructor(message: string);
|
|
542
1273
|
}
|
|
1274
|
+
/** Thrown when an encryption or decryption operation fails (e.g. ChaCha20 auth tag mismatch). */
|
|
543
1275
|
declare class EncryptionError extends AppleProtocolError {
|
|
1276
|
+
/** @param message - Human-readable description of the encryption failure. */
|
|
544
1277
|
constructor(message: string);
|
|
545
1278
|
}
|
|
1279
|
+
/** Thrown when a response from the accessory is malformed or has an unexpected format. */
|
|
546
1280
|
declare class InvalidResponseError extends AppleProtocolError {
|
|
1281
|
+
/** @param message - Human-readable description of the invalid response. */
|
|
547
1282
|
constructor(message: string);
|
|
548
1283
|
}
|
|
1284
|
+
/** Thrown when a protocol operation exceeds its expected time limit. */
|
|
549
1285
|
declare class TimeoutError extends AppleProtocolError {
|
|
1286
|
+
/** @param message - Human-readable description of the timeout. */
|
|
550
1287
|
constructor(message: string);
|
|
551
1288
|
}
|
|
1289
|
+
/** Thrown when a media playback operation fails on the target device. */
|
|
552
1290
|
declare class PlaybackError extends AppleProtocolError {
|
|
1291
|
+
/** @param message - Human-readable description of the playback failure. */
|
|
553
1292
|
constructor(message: string);
|
|
554
1293
|
}
|
|
555
1294
|
//#endregion
|
|
556
1295
|
//#region src/audioSource.d.ts
|
|
1296
|
+
/**
|
|
1297
|
+
* Represents a source of audio data that can be read in frames.
|
|
1298
|
+
* Implementations include MP3, OGG, WAV, PCM, FFmpeg, URL, SineWave, and Live sources.
|
|
1299
|
+
*/
|
|
557
1300
|
interface AudioSource {
|
|
1301
|
+
/** Total duration of the audio source in seconds. */
|
|
558
1302
|
get duration(): number;
|
|
1303
|
+
/**
|
|
1304
|
+
* Reads the specified number of audio frames from the source.
|
|
1305
|
+
*
|
|
1306
|
+
* @param count - The number of frames to read.
|
|
1307
|
+
* @returns A buffer containing the audio data, or null if the source is exhausted.
|
|
1308
|
+
*/
|
|
559
1309
|
readFrames(count: number): Promise<Buffer | null>;
|
|
1310
|
+
/** Resets the source to the beginning, allowing it to be read again. */
|
|
560
1311
|
reset(): Promise<void>;
|
|
1312
|
+
/** Starts the audio source, initializing any underlying decoders or streams. */
|
|
561
1313
|
start(): Promise<void>;
|
|
1314
|
+
/** Stops the audio source and releases any underlying resources. */
|
|
562
1315
|
stop(): Promise<void>;
|
|
563
1316
|
}
|
|
564
1317
|
//#endregion
|
|
565
|
-
export { AIRPLAY_SERVICE, AIRPLAY_TRANSIENT_PIN, type AccessoryCredentials, type AccessoryKeys, AccessoryPair, AccessoryVerify, type AirPlayFeatureFlagName, AirPlayFeatureFlags, AppleProtocolError, type AudioSource, AuthenticationError, COMPANION_LINK_SERVICE, type CombinedDiscoveryResult, CommandError, Connection, ConnectionClosedError, ConnectionError, ConnectionRecovery, type ConnectionRecoveryOptions, type ConnectionState, ConnectionTimeoutError, Context, CredentialsError, DeviceModel, DeviceType, Discovery, DiscoveryError, type DiscoveryResult, ENCRYPTION, EncryptionAwareConnection, EncryptionError, EncryptionState, type EventMap, HTTP_TIMEOUT, InvalidResponseError, JsonStorage, type Logger, type MdnsService, MemoryStorage, PairingError, type PairingRequirement, PlaybackError, type ProtocolType, RAOP_SERVICE, type Reporter, SetupError, Storage, type StorageData, type StoredDevice, TimeoutError, TimingServer, describeFlags, generateActiveRemoteId, generateDacpId, generateSessionId, getDeviceModelName, getDeviceType, getLocalIP, getMacAddress, getPairingRequirement, getProtocolVersion, hasFeatureFlag, isAirPort, isAppleTV, isHomePod, isPasswordRequired, isRemoteControlSupported, lookupDeviceModel, multicast as mdnsMulticast, unicast as mdnsUnicast, parseFeatures, prompt, randomInt32, randomInt64, reporter, uint16ToBE, uint53ToLE, v4 as uuid, waitFor };
|
|
1318
|
+
export { AIRPLAY_SERVICE, AIRPLAY_TRANSIENT_PIN, type AccessoryCredentials, type AccessoryKeys, AccessoryPair, AccessoryVerify, type AirPlayFeatureFlagName, AirPlayFeatureFlags, AppleProtocolError, type AudioSource, AuthenticationError, COMPANION_LINK_SERVICE, type CombinedDiscoveryResult, CommandError, Connection, ConnectionClosedError, ConnectionError, ConnectionRecovery, type ConnectionRecoveryOptions, type ConnectionState, ConnectionTimeoutError, Context, CredentialsError, type DeviceIdentity, DeviceModel, DeviceType, Discovery, DiscoveryError, type DiscoveryResult, ENCRYPTION, EncryptionAwareConnection, EncryptionError, EncryptionState, type EventMap, HTTP_TIMEOUT, InvalidResponseError, JsonStorage, type Logger, type MdnsService, MemoryStorage, PairingError, type PairingRequirement, PlaybackError, type ProtocolType, RAOP_SERVICE, type Reporter, SetupError, Storage, type StorageData, type StoredDevice, TimeoutError, TimingServer, describeFlags, generateActiveRemoteId, generateDacpId, generateSessionId, getDeviceModelName, getDeviceType, getLocalIP, getMacAddress, getPairingRequirement, getProtocolVersion, hasFeatureFlag, isAirPort, isAppleTV, isHomePod, isPasswordRequired, isRemoteControlSupported, lookupDeviceModel, multicast as mdnsMulticast, unicast as mdnsUnicast, parseFeatures, prompt, randomInt32, randomInt64, reporter, uint16ToBE, uint53ToLE, v4 as uuid, waitFor };
|