@basmilius/apple-common 0.9.18 → 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 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
- constructor(deviceId: string);
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,71 +821,498 @@ 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
983
+ //#region src/recovery.d.ts
984
+ /** Events emitted by {@link ConnectionRecovery}. */
985
+ type EventMap$1 = {
986
+ recovering: [attempt: number];
987
+ recovered: [];
988
+ failed: [errors: Error[]];
989
+ };
990
+ /** Configuration options for {@link ConnectionRecovery}. */
991
+ type ConnectionRecoveryOptions = {
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. */
997
+ onReconnect: () => Promise<void>;
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
+ */
1010
+ declare class ConnectionRecovery extends EventEmitter<EventMap$1> {
1011
+ #private;
1012
+ /**
1013
+ * @param options - Recovery configuration including the reconnect callback.
1014
+ */
1015
+ constructor(options: ConnectionRecoveryOptions);
1016
+ /** Whether a recovery attempt is currently in progress. */
1017
+ get isRecovering(): boolean;
1018
+ /** The current retry attempt number (0 when not recovering). */
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
+ */
1026
+ handleDisconnect(unexpected: boolean): void;
1027
+ /** Resets the recovery state and restarts the periodic reconnect interval if configured. */
1028
+ reset(): void;
1029
+ /** Permanently disposes this recovery instance, cancelling all timers and removing listeners. */
1030
+ dispose(): void;
1031
+ }
1032
+ //#endregion
440
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
+ */
441
1045
  declare class TimingServer {
442
1046
  #private;
1047
+ /** The UDP port the timing server is listening on, or 0 if not yet bound. */
443
1048
  get port(): number;
444
1049
  constructor();
1050
+ /** Closes the UDP socket and resets the port. */
445
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
+ */
446
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;
447
1078
  }
448
1079
  //#endregion
449
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
+ */
450
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
+ */
451
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
+ */
452
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
+ */
453
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
+ */
454
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
+ */
455
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
+ */
456
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
+ */
457
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
+ */
458
1139
  declare function uint53ToLE(value: number): Buffer;
459
1140
  //#endregion
1141
+ //#region src/deviceModel.d.ts
1142
+ /** Known Apple device models that can be discovered and controlled via AirPlay/Companion Link. */
1143
+ declare enum DeviceModel {
1144
+ Unknown = 0,
1145
+ AppleTVGen2 = 1,
1146
+ AppleTVGen3 = 2,
1147
+ AppleTVHD = 3,
1148
+ AppleTV4K = 4,
1149
+ AppleTV4KGen2 = 5,
1150
+ AppleTV4KGen3 = 6,
1151
+ HomePod = 10,
1152
+ HomePodMini = 11,
1153
+ HomePodGen2 = 12,
1154
+ AirPortExpress = 20,
1155
+ AirPortExpressGen2 = 21
1156
+ }
1157
+ /** High-level device categories derived from the specific device model. */
1158
+ declare enum DeviceType {
1159
+ Unknown = 0,
1160
+ AppleTV = 1,
1161
+ HomePod = 2,
1162
+ AirPort = 3
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
+ */
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
+ */
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
+ */
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
+ */
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
+ */
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
+ */
1205
+ declare const isAirPort: (model: DeviceModel) => boolean;
1206
+ //#endregion
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
+ */
1213
+ declare class AppleProtocolError extends Error {
1214
+ /** @param message - Human-readable description of the error. */
1215
+ constructor(message: string);
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
+ */
1221
+ declare class ConnectionError extends AppleProtocolError {
1222
+ /** @param message - Human-readable description of the connection failure. */
1223
+ constructor(message: string);
1224
+ }
1225
+ /** Thrown when a TCP connection attempt exceeds the configured socket timeout. */
1226
+ declare class ConnectionTimeoutError extends ConnectionError {
1227
+ /** @param message - Optional custom message; defaults to a standard timeout message. */
1228
+ constructor(message?: string);
1229
+ }
1230
+ /** Thrown when a TCP connection is closed unexpectedly by the remote end or the OS. */
1231
+ declare class ConnectionClosedError extends ConnectionError {
1232
+ /** @param message - Optional custom message; defaults to a standard closed message. */
1233
+ constructor(message?: string);
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
+ */
1239
+ declare class PairingError extends AppleProtocolError {
1240
+ /** @param message - Human-readable description of the pairing failure. */
1241
+ constructor(message: string);
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
+ */
1247
+ declare class AuthenticationError extends PairingError {
1248
+ /** @param message - Human-readable description of the authentication failure. */
1249
+ constructor(message: string);
1250
+ }
1251
+ /**
1252
+ * Thrown when stored credentials are invalid, missing, or incompatible
1253
+ * with the accessory (e.g. after a factory reset).
1254
+ */
1255
+ declare class CredentialsError extends PairingError {
1256
+ /** @param message - Human-readable description of the credentials issue. */
1257
+ constructor(message: string);
1258
+ }
1259
+ /** Thrown when a protocol command fails to execute on the target device. */
1260
+ declare class CommandError extends AppleProtocolError {
1261
+ /** @param message - Human-readable description of the command failure. */
1262
+ constructor(message: string);
1263
+ }
1264
+ /** Thrown when a protocol setup step fails (e.g. RTSP SETUP, AirPlay stream setup). */
1265
+ declare class SetupError extends AppleProtocolError {
1266
+ /** @param message - Human-readable description of the setup failure. */
1267
+ constructor(message: string);
1268
+ }
1269
+ /** Thrown when mDNS device discovery fails or a device cannot be found after retries. */
1270
+ declare class DiscoveryError extends AppleProtocolError {
1271
+ /** @param message - Human-readable description of the discovery failure. */
1272
+ constructor(message: string);
1273
+ }
1274
+ /** Thrown when an encryption or decryption operation fails (e.g. ChaCha20 auth tag mismatch). */
1275
+ declare class EncryptionError extends AppleProtocolError {
1276
+ /** @param message - Human-readable description of the encryption failure. */
1277
+ constructor(message: string);
1278
+ }
1279
+ /** Thrown when a response from the accessory is malformed or has an unexpected format. */
1280
+ declare class InvalidResponseError extends AppleProtocolError {
1281
+ /** @param message - Human-readable description of the invalid response. */
1282
+ constructor(message: string);
1283
+ }
1284
+ /** Thrown when a protocol operation exceeds its expected time limit. */
1285
+ declare class TimeoutError extends AppleProtocolError {
1286
+ /** @param message - Human-readable description of the timeout. */
1287
+ constructor(message: string);
1288
+ }
1289
+ /** Thrown when a media playback operation fails on the target device. */
1290
+ declare class PlaybackError extends AppleProtocolError {
1291
+ /** @param message - Human-readable description of the playback failure. */
1292
+ constructor(message: string);
1293
+ }
1294
+ //#endregion
460
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
+ */
461
1300
  interface AudioSource {
1301
+ /** Total duration of the audio source in seconds. */
462
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
+ */
463
1309
  readFrames(count: number): Promise<Buffer | null>;
1310
+ /** Resets the source to the beginning, allowing it to be read again. */
464
1311
  reset(): Promise<void>;
1312
+ /** Starts the audio source, initializing any underlying decoders or streams. */
465
1313
  start(): Promise<void>;
1314
+ /** Stops the audio source and releases any underlying resources. */
466
1315
  stop(): Promise<void>;
467
1316
  }
468
1317
  //#endregion
469
- export { AIRPLAY_SERVICE, AIRPLAY_TRANSIENT_PIN, type AccessoryCredentials, type AccessoryKeys, AccessoryPair, AccessoryVerify, type AirPlayFeatureFlagName, AirPlayFeatureFlags, type AudioSource, COMPANION_LINK_SERVICE, type CombinedDiscoveryResult, Connection, type ConnectionState, Context, Discovery, type DiscoveryResult, ENCRYPTION, EncryptionAwareConnection, EncryptionState, type EventMap, HTTP_TIMEOUT, JsonStorage, type Logger, type MdnsService, MemoryStorage, type PairingRequirement, type ProtocolType, RAOP_SERVICE, type Reporter, Storage, type StorageData, type StoredDevice, TimingServer, describeFlags, generateActiveRemoteId, generateDacpId, generateSessionId, getLocalIP, getMacAddress, getPairingRequirement, getProtocolVersion, hasFeatureFlag, isPasswordRequired, isRemoteControlSupported, 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 };