@basmilius/apple-encoding 0.9.19 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,10 @@
1
1
  declare namespace daap_d_exports {
2
- export { ContentCode, ContentCodeKey, DecodedTag, PlaybackStatus, TagType, TrackMetadata, decode$3 as decode, decodeTag, decodeToObject, decodeTrackMetadata, encodeContainer, encodePlaybackStatus, encodeTag, encodeTagWithSize, encodeTrackMetadata };
2
+ export { ContentCode, ContentCodeKey, DecodedTag, PlaybackStatus, TagType, TrackMetadata, decode$4 as decode, decodeTag, decodeToObject, decodeTrackMetadata, encodeContainer, encodePlaybackStatus, encodeTag, encodeTagWithSize, encodeTrackMetadata };
3
3
  }
4
+ /**
5
+ * Maps four-character DAAP tag codes to their human-readable DMAP/DAAP content code names.
6
+ * Used to identify the semantic meaning of tags in DAAP protocol messages.
7
+ */
4
8
  declare const ContentCode: {
5
9
  readonly mlit: "dmap.listingitem";
6
10
  readonly mlcl: "dmap.listing";
@@ -30,6 +34,15 @@ declare const ContentCode: {
30
34
  readonly cavs: "daap.songvisiblestate";
31
35
  readonly aePP: "com.apple.itunes.photo-properties";
32
36
  };
37
+ /**
38
+ * Maps four-character DAAP tag codes to their data type identifiers.
39
+ *
40
+ * Type values: 1=byte, 2=unsigned byte, 3=short, 4=unsigned short,
41
+ * 5=int, 6=unsigned int, 7=long, 8=unsigned long,
42
+ * 9=string, 10=date, 11=version, 12=container.
43
+ *
44
+ * Used by the decoder to determine how to interpret the raw bytes of each tag.
45
+ */
33
46
  declare const TagType: {
34
47
  readonly mlit: 12;
35
48
  readonly mlcl: 12;
@@ -59,87 +72,288 @@ declare const TagType: {
59
72
  readonly cavs: 1;
60
73
  readonly aePP: 9;
61
74
  };
75
+ /**
76
+ * Encodes a single DAAP tag with an automatically sized value.
77
+ * Numbers are encoded in the smallest big-endian representation that fits.
78
+ *
79
+ * @param tag - Four-character ASCII tag code (e.g. 'minm', 'asar').
80
+ * @param value - The value to encode: string (UTF-8), number (auto-sized BE), bigint (8-byte BE), or raw Buffer.
81
+ * @returns A buffer containing the tag, length, and value.
82
+ * @throws Error if the tag is not exactly 4 characters.
83
+ */
62
84
  declare function encodeTag(tag: string, value: Buffer | string | number | bigint): Buffer;
85
+ /**
86
+ * Encodes a DAAP container tag that wraps other encoded tags.
87
+ *
88
+ * @param tag - Four-character ASCII container tag code (e.g. 'mlit', 'mlcl').
89
+ * @param content - Pre-encoded buffer containing the container's child tags.
90
+ * @returns A buffer containing the container tag, length, and nested content.
91
+ * @throws Error if the tag is not exactly 4 characters.
92
+ */
63
93
  declare function encodeContainer(tag: string, content: Buffer): Buffer;
94
+ /**
95
+ * Encodes playback status fields (playing, shuffle, repeat) into DAAP tags.
96
+ * Only includes tags for fields that are defined in the status object.
97
+ *
98
+ * @param status - The playback status to encode.
99
+ * @returns A buffer containing the encoded DAAP status tags.
100
+ */
64
101
  declare function encodePlaybackStatus(status: PlaybackStatus): Buffer;
102
+ /**
103
+ * Encodes a DAAP tag with an explicitly specified byte size for the numeric value.
104
+ * Useful when the protocol requires a specific size regardless of the value magnitude.
105
+ *
106
+ * @param tag - Four-character ASCII tag code.
107
+ * @param value - The numeric value to encode.
108
+ * @param byteSize - The exact number of bytes to use for the value (1, 2, 4, or 8).
109
+ * @returns A buffer containing the tag, length, and fixed-size value.
110
+ * @throws Error if the tag is not exactly 4 characters.
111
+ */
65
112
  declare function encodeTagWithSize(tag: string, value: number, byteSize: 1 | 2 | 4 | 8): Buffer;
113
+ /**
114
+ * Encodes track metadata into a DAAP listing item (`mlit`) container.
115
+ * Only includes tags for fields that are defined in the metadata object.
116
+ * Duration is converted from seconds to milliseconds for the `astm` tag.
117
+ *
118
+ * @param metadata - The track metadata to encode.
119
+ * @returns A buffer containing an `mlit` container with all defined metadata tags.
120
+ */
66
121
  declare function encodeTrackMetadata(metadata: TrackMetadata): Buffer;
67
- declare function decode$3(buffer: Buffer): DecodedTag[];
122
+ /**
123
+ * Decodes all DAAP tags from a buffer sequentially.
124
+ * Stops when the buffer is exhausted or a tag cannot be fully decoded.
125
+ *
126
+ * @param buffer - The raw DAAP-encoded buffer.
127
+ * @returns An array of decoded tags with their raw value buffers.
128
+ */
129
+ declare function decode$4(buffer: Buffer): DecodedTag[];
130
+ /**
131
+ * Decodes a single DAAP tag from the start of a buffer.
132
+ * Returns the decoded tag and the remaining unconsumed buffer.
133
+ *
134
+ * @param buffer - The buffer to decode from. Must contain at least 8 bytes (4 tag + 4 length).
135
+ * @returns A tuple of the decoded tag and remaining buffer, or null if the buffer is too short.
136
+ */
68
137
  declare function decodeTag(buffer: Buffer): [DecodedTag, Buffer] | null;
138
+ /**
139
+ * Decodes a DAAP buffer into a plain object, interpreting values based on {@link TagType}.
140
+ * Container tags (type 12) are recursively decoded. Unknown tags are kept as raw buffers.
141
+ *
142
+ * @param buffer - The raw DAAP-encoded buffer.
143
+ * @returns An object mapping tag codes to their decoded values.
144
+ */
69
145
  declare function decodeToObject(buffer: Buffer): Record<string, unknown>;
146
+ /**
147
+ * Decodes a DAAP buffer into a structured {@link TrackMetadata} object.
148
+ * Handles both bare tag lists and `mlit`-wrapped containers.
149
+ * Duration is converted from the DAAP millisecond `astm` value back to seconds.
150
+ *
151
+ * @param buffer - The raw DAAP-encoded buffer containing track metadata.
152
+ * @returns The decoded track metadata.
153
+ */
70
154
  declare function decodeTrackMetadata(buffer: Buffer): TrackMetadata;
155
+ /** Union type of all valid four-character DAAP content code keys. */
71
156
  type ContentCodeKey = keyof typeof ContentCode;
157
+ /** Represents a single decoded DAAP tag with its raw value buffer. */
72
158
  type DecodedTag = {
73
- readonly tag: string;
74
- readonly length: number;
159
+ /** The four-character ASCII tag code. */readonly tag: string; /** The byte length of the value. */
160
+ readonly length: number; /** The raw undecoded value bytes. */
75
161
  readonly value: Buffer;
76
162
  };
163
+ /** Represents the playback state of a DAAP media player. */
77
164
  type PlaybackStatus = {
78
- readonly playing?: boolean;
79
- readonly shuffle?: boolean;
165
+ /** Whether the player is currently playing. */readonly playing?: boolean; /** Whether shuffle mode is enabled. */
166
+ readonly shuffle?: boolean; /** The repeat mode: off, repeat one track, or repeat all. */
80
167
  readonly repeat?: "off" | "one" | "all";
81
168
  };
169
+ /** Metadata for a single media track in the DAAP protocol. */
82
170
  type TrackMetadata = {
83
- readonly title?: string;
84
- readonly artist?: string;
85
- readonly albumArtist?: string;
86
- readonly album?: string;
87
- readonly composer?: string;
88
- readonly genre?: string;
89
- readonly duration?: number;
90
- readonly trackNumber?: number;
91
- readonly trackCount?: number;
92
- readonly discNumber?: number;
93
- readonly discCount?: number;
94
- readonly year?: number;
95
- readonly bitrate?: number;
96
- readonly sampleRate?: number;
171
+ /** Track title (DAAP tag `minm`). */readonly title?: string; /** Track artist (DAAP tag `asar`). */
172
+ readonly artist?: string; /** Album artist (DAAP tag `asaa`). */
173
+ readonly albumArtist?: string; /** Album name (DAAP tag `asal`). */
174
+ readonly album?: string; /** Composer name (DAAP tag `ascp`). */
175
+ readonly composer?: string; /** Genre name (DAAP tag `asgn`). */
176
+ readonly genre?: string; /** Track duration in seconds. Converted to/from milliseconds during encoding/decoding. */
177
+ readonly duration?: number; /** Track number within the album (DAAP tag `astn`). */
178
+ readonly trackNumber?: number; /** Total number of tracks on the album (DAAP tag `astc`). */
179
+ readonly trackCount?: number; /** Disc number within the set (DAAP tag `asdn`). */
180
+ readonly discNumber?: number; /** Total number of discs in the set (DAAP tag `asdc`). */
181
+ readonly discCount?: number; /** Release year (DAAP tag `asyr`). */
182
+ readonly year?: number; /** Bitrate in kbps (DAAP tag `asbr`). */
183
+ readonly bitrate?: number; /** Sample rate in Hz (DAAP tag `assr`). */
184
+ readonly sampleRate?: number; /** File size in bytes (DAAP tag `assz`). */
97
185
  readonly size?: number;
98
186
  };
187
+ declare namespace nskeyedarchiver_d_exports {
188
+ export { decode$3 as decode, decodeAsArray };
189
+ }
190
+ /**
191
+ * Decodes an NSKeyedArchiver binary plist into plain JavaScript objects.
192
+ * Resolves CF$UID references, decodes NS.objects/NS.keys into arrays/dicts,
193
+ * and strips $class metadata.
194
+ *
195
+ * @param archive - The parsed plist archive containing `$objects` and `$top` keys.
196
+ * @returns The resolved root object, or null if the archive is invalid.
197
+ */
198
+ declare function decode$3(archive: any): unknown;
199
+ /**
200
+ * Decodes an NSKeyedArchiver plist and returns the root as an array.
201
+ * If the root is not an array, wraps it in one.
202
+ *
203
+ * @param archive - The parsed plist archive containing `$objects` and `$top` keys.
204
+ * @returns The resolved root as an array. Non-array roots are wrapped in a single-element array.
205
+ */
206
+ declare function decodeAsArray(archive: any): unknown[];
99
207
  declare namespace ntp_d_exports {
100
- export { PacketFields, decode$2 as decode, encode$2 as encode, now, ns, parts };
208
+ export { PacketFields, decode$2 as decode, encode$2 as encode, now, parts };
101
209
  }
210
+ /**
211
+ * Returns the current wall-clock time as a 64-bit NTP timestamp.
212
+ * The upper 32 bits are whole seconds since the NTP epoch (1900-01-01),
213
+ * and the lower 32 bits are the fractional second.
214
+ *
215
+ * Uses `Date.now()` (wall-clock) rather than a monotone clock because Apple
216
+ * devices expect NTP timestamps anchored to real time.
217
+ *
218
+ * @returns The current time as a 64-bit NTP timestamp.
219
+ */
102
220
  declare function now(): bigint;
103
- declare function ns(): bigint;
221
+ /**
222
+ * Splits a 64-bit NTP timestamp into its seconds and fractional parts.
223
+ *
224
+ * @param ntp - A 64-bit NTP timestamp (upper 32 bits = seconds, lower 32 bits = fraction).
225
+ * @returns A tuple of [seconds, fraction] as 32-bit unsigned integers.
226
+ */
104
227
  declare function parts(ntp: bigint): [number, number];
228
+ /**
229
+ * Decodes an NTP timing packet from a buffer into its constituent fields.
230
+ * Expects at least 24 bytes; the send timestamp fields (bytes 24-31) default
231
+ * to 0 if the buffer is shorter than 32 bytes.
232
+ *
233
+ * @param buffer - The raw NTP packet buffer (minimum 24 bytes).
234
+ * @returns The decoded packet fields.
235
+ * @throws RangeError if the buffer is shorter than 24 bytes.
236
+ */
105
237
  declare function decode$2(buffer: Buffer): PacketFields;
238
+ /**
239
+ * Encodes NTP timing packet fields into a 32-byte buffer.
240
+ *
241
+ * @param fields - The packet fields to encode.
242
+ * @returns A 32-byte buffer containing the encoded NTP packet.
243
+ */
106
244
  declare function encode$2(fields: PacketFields): Buffer;
245
+ /** Fields of an NTP timing packet used for clock synchronization with Apple devices. */
107
246
  type PacketFields = {
108
- readonly proto: number;
109
- readonly type: number;
110
- readonly seqno: number;
111
- readonly padding: number;
112
- readonly reftime_sec: number;
113
- readonly reftime_frac: number;
114
- readonly recvtime_sec: number;
115
- readonly recvtime_frac: number;
116
- readonly sendtime_sec: number;
247
+ /** Protocol identifier byte. */readonly proto: number; /** Packet type (e.g. request or response). */
248
+ readonly type: number; /** Sequence number for correlating requests and responses. */
249
+ readonly seqno: number; /** Padding field (typically zero). */
250
+ readonly padding: number; /** Reference timestamp, seconds part. */
251
+ readonly reftime_sec: number; /** Reference timestamp, fractional part. */
252
+ readonly reftime_frac: number; /** Receive timestamp, seconds part. */
253
+ readonly recvtime_sec: number; /** Receive timestamp, fractional part. */
254
+ readonly recvtime_frac: number; /** Send timestamp, seconds part. */
255
+ readonly sendtime_sec: number; /** Send timestamp, fractional part. */
117
256
  readonly sendtime_frac: number;
118
257
  };
119
258
  declare namespace opack_d_exports {
120
259
  export { decode$1 as decode, encode$1 as encode, float, int, sizedInteger };
121
260
  }
261
+ /**
262
+ * Wrapper that forces a number to be encoded as an OPack float (FLOAT64).
263
+ * Without this wrapper, JavaScript numbers that happen to be integers
264
+ * would be encoded as OPack integers instead.
265
+ */
122
266
  declare class Float {
123
267
  #private;
268
+ /** The wrapped floating-point value. */
124
269
  get value(): number;
270
+ /**
271
+ * @param value - The floating-point number to wrap.
272
+ */
125
273
  constructor(value: number);
126
274
  }
275
+ /**
276
+ * Wrapper that forces a number to be encoded as an OPack integer.
277
+ * Useful when a value must be encoded as an integer even if it could
278
+ * be represented as an inline value.
279
+ */
127
280
  declare class Integer {
128
281
  #private;
282
+ /** The wrapped integer value. */
129
283
  get value(): number;
284
+ /**
285
+ * @param value - The integer number to wrap.
286
+ */
130
287
  constructor(value: number);
131
288
  }
289
+ /**
290
+ * An integer with an explicit byte size. Produced during OPack decoding when
291
+ * the wire format specifies the exact byte width (1, 2, 4, or 8). During
292
+ * encoding, the specified size is preserved to maintain wire compatibility.
293
+ */
132
294
  declare class SizedInteger {
133
295
  #private;
296
+ /** The byte width of this integer on the wire (1, 2, 4, or 8). */
134
297
  get size(): number;
298
+ /** The numeric value. */
135
299
  get value(): number;
300
+ /**
301
+ * @param value - The integer value.
302
+ * @param size - The byte width for wire encoding (1, 2, 4, or 8).
303
+ */
136
304
  constructor(value: number, size: number);
305
+ /**
306
+ * Returns the numeric value, enabling implicit numeric coercion.
307
+ *
308
+ * @returns The integer value.
309
+ */
137
310
  valueOf(): number;
138
311
  }
312
+ /**
313
+ * Creates an OPack float wrapper, ensuring the value is encoded as FLOAT64
314
+ * on the wire regardless of whether it is a whole number.
315
+ *
316
+ * @param value - The floating-point number.
317
+ * @returns A Float wrapper for OPack encoding.
318
+ */
139
319
  declare function float(value: number): Float;
320
+ /**
321
+ * Creates an OPack integer wrapper, ensuring the value is encoded as an
322
+ * explicit integer type on the wire.
323
+ *
324
+ * @param value - The integer number.
325
+ * @returns An Integer wrapper for OPack encoding.
326
+ */
140
327
  declare function int(value: number): Integer;
328
+ /**
329
+ * Creates an OPack sized integer with an explicit byte width.
330
+ * Used during decoding to preserve the original wire size, and during
331
+ * encoding to force a specific byte width.
332
+ *
333
+ * @param value - The integer value.
334
+ * @param size - The byte width (1, 2, 4, or 8).
335
+ * @returns A SizedInteger wrapper for OPack encoding.
336
+ */
141
337
  declare function sizedInteger(value: number, size: number): SizedInteger;
338
+ /**
339
+ * Decodes an OPack-encoded byte array into a JavaScript value.
340
+ * OPack is Apple's compact binary serialization format used in
341
+ * Companion Link and other protocols.
342
+ *
343
+ * @param data - The raw OPack-encoded bytes.
344
+ * @returns The decoded JavaScript value (object, array, string, number, boolean, null, or Uint8Array).
345
+ */
142
346
  declare function decode$1(data: Uint8Array): any;
347
+ /**
348
+ * Encodes a JavaScript value into OPack binary format.
349
+ * Supports null, booleans, numbers, strings, Uint8Array/Buffer, arrays,
350
+ * plain objects, and the explicit type wrappers ({@link float}, {@link int}, {@link sizedInteger}).
351
+ * Automatically deduplicates repeated values using back-references.
352
+ *
353
+ * @param data - The value to encode.
354
+ * @returns The OPack-encoded bytes.
355
+ * @throws TypeError if the value type is unsupported.
356
+ */
143
357
  declare function encode$1(data: any): Uint8Array;
144
358
  //#endregion
145
359
  //#region ../../node_modules/.bun/@plist+common@1.1.0/node_modules/@plist/common/lib/cjs/types.d.ts
@@ -159,9 +373,17 @@ declare namespace plist_d_exports {
159
373
  declare namespace tlv8_d_exports {
160
374
  export { ErrorCode, Flags, Method, State, TLV8PairingError, Value, bail, decode, encode };
161
375
  }
376
+ /**
377
+ * TLV8 pairing flags used during HAP pair-setup and pair-verify.
378
+ * Sent as part of the TLV8 Flags (0x13) value.
379
+ */
162
380
  declare const Flags: {
163
381
  readonly TransientPairing: 0x10;
164
382
  };
383
+ /**
384
+ * TLV8 error codes returned by the accessory during pairing.
385
+ * Included in the Error (0x07) TLV value.
386
+ */
165
387
  declare const ErrorCode: {
166
388
  readonly Unknown: 0x01;
167
389
  readonly Authentication: 0x02;
@@ -171,6 +393,10 @@ declare const ErrorCode: {
171
393
  readonly Unavailable: 0x06;
172
394
  readonly Busy: 0x07;
173
395
  };
396
+ /**
397
+ * HAP pairing method identifiers. Sent in the Method (0x00) TLV value
398
+ * to indicate which pairing operation is being performed.
399
+ */
174
400
  declare const Method: {
175
401
  readonly PairSetup: 0x00;
176
402
  readonly PairSetupWithAuth: 0x01;
@@ -179,6 +405,10 @@ declare const Method: {
179
405
  readonly RemovePairing: 0x04;
180
406
  readonly ListPairing: 0x05;
181
407
  };
408
+ /**
409
+ * HAP pairing state machine steps (M1 through M6).
410
+ * Each state corresponds to a message in the SRP pair-setup or pair-verify flow.
411
+ */
182
412
  declare const State: {
183
413
  readonly M1: 0x01;
184
414
  readonly M2: 0x02;
@@ -187,6 +417,10 @@ declare const State: {
187
417
  readonly M5: 0x05;
188
418
  readonly M6: 0x06;
189
419
  };
420
+ /**
421
+ * TLV8 type identifiers for the fields exchanged during HAP pairing.
422
+ * Each value is the type byte that precedes the length and data in a TLV8 entry.
423
+ */
190
424
  declare const Value: {
191
425
  readonly Method: 0x00;
192
426
  readonly Identifier: 0x01;
@@ -205,12 +439,46 @@ declare const Value: {
205
439
  readonly Name: 0x11;
206
440
  readonly Flags: 0x13;
207
441
  };
442
+ /**
443
+ * Error thrown when a TLV8 pairing exchange fails.
444
+ * Carries the numeric error code from the accessory when available.
445
+ */
208
446
  declare class TLV8PairingError extends Error {
447
+ /** The TLV8 error code from the accessory, if present. */
209
448
  readonly code: number | undefined;
449
+ /**
450
+ * @param message - Human-readable error description.
451
+ * @param code - The TLV8 error code from the accessory response.
452
+ */
210
453
  constructor(message: string, code?: number);
211
454
  }
455
+ /**
456
+ * Inspects a decoded TLV8 response for error or back-off conditions and throws
457
+ * an appropriate {@link TLV8PairingError}. Always throws; the return type `never`
458
+ * signals to the compiler that execution does not continue past this call.
459
+ *
460
+ * @param data - The decoded TLV8 map from a pairing response.
461
+ * @throws TLV8PairingError with the specific error code, back-off time, or a generic message.
462
+ */
212
463
  declare function bail(data: Map<number, Buffer>): never;
464
+ /**
465
+ * Encodes an array of TLV8 entries into a single buffer.
466
+ * Values longer than 255 bytes are automatically split into multiple
467
+ * consecutive TLV fragments of the same type, as required by the TLV8 spec.
468
+ *
469
+ * @param entries - An array of [type, value] tuples. Values can be a single byte (number),
470
+ * a Buffer, or a Uint8Array.
471
+ * @returns A buffer containing all TLV8 entries concatenated.
472
+ */
213
473
  declare function encode(entries: [number, number | Buffer | Uint8Array][]): Buffer;
474
+ /**
475
+ * Decodes a TLV8 buffer into a map of type to value.
476
+ * Consecutive entries with the same type are automatically concatenated,
477
+ * reassembling fragmented values as required by the TLV8 spec.
478
+ *
479
+ * @param buf - The raw TLV8-encoded buffer.
480
+ * @returns A map from TLV8 type byte to the reassembled value buffer.
481
+ */
214
482
  declare function decode(buf: Buffer): Map<number, Buffer>;
215
483
  //#endregion
216
- export { daap_d_exports as DAAP, ntp_d_exports as NTP, opack_d_exports as OPack, plist_d_exports as Plist, tlv8_d_exports as TLV8 };
484
+ export { daap_d_exports as DAAP, nskeyedarchiver_d_exports as NSKeyedArchiver, ntp_d_exports as NTP, opack_d_exports as OPack, plist_d_exports as Plist, tlv8_d_exports as TLV8 };
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
4
4
  var daap_exports = /* @__PURE__ */ __exportAll({
5
5
  ContentCode: () => ContentCode,
6
6
  TagType: () => TagType,
7
- decode: () => decode$3,
7
+ decode: () => decode$4,
8
8
  decodeTag: () => decodeTag,
9
9
  decodeToObject: () => decodeToObject,
10
10
  decodeTrackMetadata: () => decodeTrackMetadata,
@@ -14,6 +14,10 @@ var daap_exports = /* @__PURE__ */ __exportAll({
14
14
  encodeTagWithSize: () => encodeTagWithSize,
15
15
  encodeTrackMetadata: () => encodeTrackMetadata
16
16
  });
17
+ /**
18
+ * Maps four-character DAAP tag codes to their human-readable DMAP/DAAP content code names.
19
+ * Used to identify the semantic meaning of tags in DAAP protocol messages.
20
+ */
17
21
  const ContentCode = {
18
22
  mlit: "dmap.listingitem",
19
23
  mlcl: "dmap.listing",
@@ -43,6 +47,15 @@ const ContentCode = {
43
47
  cavs: "daap.songvisiblestate",
44
48
  aePP: "com.apple.itunes.photo-properties"
45
49
  };
50
+ /**
51
+ * Maps four-character DAAP tag codes to their data type identifiers.
52
+ *
53
+ * Type values: 1=byte, 2=unsigned byte, 3=short, 4=unsigned short,
54
+ * 5=int, 6=unsigned int, 7=long, 8=unsigned long,
55
+ * 9=string, 10=date, 11=version, 12=container.
56
+ *
57
+ * Used by the decoder to determine how to interpret the raw bytes of each tag.
58
+ */
46
59
  const TagType = {
47
60
  mlit: 12,
48
61
  mlcl: 12,
@@ -72,6 +85,15 @@ const TagType = {
72
85
  cavs: 1,
73
86
  aePP: 9
74
87
  };
88
+ /**
89
+ * Encodes a single DAAP tag with an automatically sized value.
90
+ * Numbers are encoded in the smallest big-endian representation that fits.
91
+ *
92
+ * @param tag - Four-character ASCII tag code (e.g. 'minm', 'asar').
93
+ * @param value - The value to encode: string (UTF-8), number (auto-sized BE), bigint (8-byte BE), or raw Buffer.
94
+ * @returns A buffer containing the tag, length, and value.
95
+ * @throws Error if the tag is not exactly 4 characters.
96
+ */
75
97
  function encodeTag(tag, value) {
76
98
  if (tag.length !== 4) throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
77
99
  const tagBuffer = Buffer.from(tag, "ascii");
@@ -102,6 +124,14 @@ function encodeTag(tag, value) {
102
124
  valueBuffer
103
125
  ]);
104
126
  }
127
+ /**
128
+ * Encodes a DAAP container tag that wraps other encoded tags.
129
+ *
130
+ * @param tag - Four-character ASCII container tag code (e.g. 'mlit', 'mlcl').
131
+ * @param content - Pre-encoded buffer containing the container's child tags.
132
+ * @returns A buffer containing the container tag, length, and nested content.
133
+ * @throws Error if the tag is not exactly 4 characters.
134
+ */
105
135
  function encodeContainer(tag, content) {
106
136
  if (tag.length !== 4) throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
107
137
  const tagBuffer = Buffer.from(tag, "ascii");
@@ -113,6 +143,13 @@ function encodeContainer(tag, content) {
113
143
  content
114
144
  ]);
115
145
  }
146
+ /**
147
+ * Encodes playback status fields (playing, shuffle, repeat) into DAAP tags.
148
+ * Only includes tags for fields that are defined in the status object.
149
+ *
150
+ * @param status - The playback status to encode.
151
+ * @returns A buffer containing the encoded DAAP status tags.
152
+ */
116
153
  function encodePlaybackStatus(status) {
117
154
  const tags = [];
118
155
  if (status.playing !== void 0) tags.push(encodeTagWithSize("caps", status.playing ? 4 : 3, 1));
@@ -125,6 +162,16 @@ function encodePlaybackStatus(status) {
125
162
  }
126
163
  return Buffer.concat(tags);
127
164
  }
165
+ /**
166
+ * Encodes a DAAP tag with an explicitly specified byte size for the numeric value.
167
+ * Useful when the protocol requires a specific size regardless of the value magnitude.
168
+ *
169
+ * @param tag - Four-character ASCII tag code.
170
+ * @param value - The numeric value to encode.
171
+ * @param byteSize - The exact number of bytes to use for the value (1, 2, 4, or 8).
172
+ * @returns A buffer containing the tag, length, and fixed-size value.
173
+ * @throws Error if the tag is not exactly 4 characters.
174
+ */
128
175
  function encodeTagWithSize(tag, value, byteSize) {
129
176
  if (tag.length !== 4) throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
130
177
  const tagBuffer = Buffer.from(tag, "ascii");
@@ -151,6 +198,14 @@ function encodeTagWithSize(tag, value, byteSize) {
151
198
  valueBuffer
152
199
  ]);
153
200
  }
201
+ /**
202
+ * Encodes track metadata into a DAAP listing item (`mlit`) container.
203
+ * Only includes tags for fields that are defined in the metadata object.
204
+ * Duration is converted from seconds to milliseconds for the `astm` tag.
205
+ *
206
+ * @param metadata - The track metadata to encode.
207
+ * @returns A buffer containing an `mlit` container with all defined metadata tags.
208
+ */
154
209
  function encodeTrackMetadata(metadata) {
155
210
  const tags = [];
156
211
  if (metadata.title !== void 0) tags.push(encodeTag("minm", metadata.title));
@@ -170,7 +225,14 @@ function encodeTrackMetadata(metadata) {
170
225
  if (metadata.size !== void 0) tags.push(encodeTagWithSize("assz", metadata.size, 4));
171
226
  return encodeContainer("mlit", Buffer.concat(tags));
172
227
  }
173
- function decode$3(buffer) {
228
+ /**
229
+ * Decodes all DAAP tags from a buffer sequentially.
230
+ * Stops when the buffer is exhausted or a tag cannot be fully decoded.
231
+ *
232
+ * @param buffer - The raw DAAP-encoded buffer.
233
+ * @returns An array of decoded tags with their raw value buffers.
234
+ */
235
+ function decode$4(buffer) {
174
236
  const tags = [];
175
237
  let remaining = buffer;
176
238
  while (remaining.length > 0) {
@@ -182,6 +244,13 @@ function decode$3(buffer) {
182
244
  }
183
245
  return tags;
184
246
  }
247
+ /**
248
+ * Decodes a single DAAP tag from the start of a buffer.
249
+ * Returns the decoded tag and the remaining unconsumed buffer.
250
+ *
251
+ * @param buffer - The buffer to decode from. Must contain at least 8 bytes (4 tag + 4 length).
252
+ * @returns A tuple of the decoded tag and remaining buffer, or null if the buffer is too short.
253
+ */
185
254
  function decodeTag(buffer) {
186
255
  if (buffer.length < 8) return null;
187
256
  const tag = buffer.subarray(0, 4).toString("ascii");
@@ -195,9 +264,16 @@ function decodeTag(buffer) {
195
264
  value
196
265
  }, remaining];
197
266
  }
267
+ /**
268
+ * Decodes a DAAP buffer into a plain object, interpreting values based on {@link TagType}.
269
+ * Container tags (type 12) are recursively decoded. Unknown tags are kept as raw buffers.
270
+ *
271
+ * @param buffer - The raw DAAP-encoded buffer.
272
+ * @returns An object mapping tag codes to their decoded values.
273
+ */
198
274
  function decodeToObject(buffer) {
199
275
  const result = {};
200
- const tags = decode$3(buffer);
276
+ const tags = decode$4(buffer);
201
277
  for (const { tag, value } of tags) {
202
278
  const tagType = TagType[tag];
203
279
  if (tagType === void 0) result[tag] = value;
@@ -211,6 +287,14 @@ function decodeToObject(buffer) {
211
287
  }
212
288
  return result;
213
289
  }
290
+ /**
291
+ * Decodes a DAAP buffer into a structured {@link TrackMetadata} object.
292
+ * Handles both bare tag lists and `mlit`-wrapped containers.
293
+ * Duration is converted from the DAAP millisecond `astm` value back to seconds.
294
+ *
295
+ * @param buffer - The raw DAAP-encoded buffer containing track metadata.
296
+ * @returns The decoded track metadata.
297
+ */
214
298
  function decodeTrackMetadata(buffer) {
215
299
  const obj = decodeToObject(buffer);
216
300
  const mlit = obj.mlit ?? obj;
@@ -233,28 +317,107 @@ function decodeTrackMetadata(buffer) {
233
317
  };
234
318
  }
235
319
 
320
+ //#endregion
321
+ //#region src/nskeyedarchiver.ts
322
+ var nskeyedarchiver_exports = /* @__PURE__ */ __exportAll({
323
+ decode: () => decode$3,
324
+ decodeAsArray: () => decodeAsArray
325
+ });
326
+ /**
327
+ * Decodes an NSKeyedArchiver binary plist into plain JavaScript objects.
328
+ * Resolves CF$UID references, decodes NS.objects/NS.keys into arrays/dicts,
329
+ * and strips $class metadata.
330
+ *
331
+ * @param archive - The parsed plist archive containing `$objects` and `$top` keys.
332
+ * @returns The resolved root object, or null if the archive is invalid.
333
+ */
334
+ function decode$3(archive) {
335
+ const objects = archive?.["$objects"];
336
+ const top = archive?.["$top"];
337
+ if (!objects || !top) return null;
338
+ const resolve = (ref) => {
339
+ if (ref && typeof ref === "object" && "CF$UID" in ref) return resolve(objects[ref["CF$UID"]]);
340
+ if (ref === "$null") return null;
341
+ if (ref && typeof ref === "object") {
342
+ const obj = ref;
343
+ if (obj["NS.objects"] && Array.isArray(obj["NS.objects"])) return obj["NS.objects"].map(resolve);
344
+ if (obj["NS.keys"] && Array.isArray(obj["NS.keys"])) {
345
+ const keys = obj["NS.keys"].map(resolve);
346
+ const values = obj["NS.objects"].map(resolve);
347
+ const result = {};
348
+ for (let i = 0; i < keys.length; i++) result[keys[i]] = values[i];
349
+ return result;
350
+ }
351
+ const result = {};
352
+ for (const [key, value] of Object.entries(obj)) {
353
+ if (key === "$class" || key === "$classname" || key === "$classes") continue;
354
+ result[key] = resolve(value);
355
+ }
356
+ return result;
357
+ }
358
+ return ref;
359
+ };
360
+ return resolve(top.root ?? top);
361
+ }
362
+ /**
363
+ * Decodes an NSKeyedArchiver plist and returns the root as an array.
364
+ * If the root is not an array, wraps it in one.
365
+ *
366
+ * @param archive - The parsed plist archive containing `$objects` and `$top` keys.
367
+ * @returns The resolved root as an array. Non-array roots are wrapped in a single-element array.
368
+ */
369
+ function decodeAsArray(archive) {
370
+ const root = decode$3(archive);
371
+ return Array.isArray(root) ? root : [root];
372
+ }
373
+
236
374
  //#endregion
237
375
  //#region src/ntp.ts
238
376
  var ntp_exports = /* @__PURE__ */ __exportAll({
239
377
  decode: () => decode$2,
240
378
  encode: () => encode$2,
241
379
  now: () => now,
242
- ns: () => ns,
243
380
  parts: () => parts
244
381
  });
382
+ /**
383
+ * NTP epoch offset: the number of seconds between the NTP epoch (1900-01-01)
384
+ * and the Unix epoch (1970-01-01).
385
+ */
245
386
  const EPOCH$1 = 2208988800n;
387
+ /**
388
+ * Returns the current wall-clock time as a 64-bit NTP timestamp.
389
+ * The upper 32 bits are whole seconds since the NTP epoch (1900-01-01),
390
+ * and the lower 32 bits are the fractional second.
391
+ *
392
+ * Uses `Date.now()` (wall-clock) rather than a monotone clock because Apple
393
+ * devices expect NTP timestamps anchored to real time.
394
+ *
395
+ * @returns The current time as a 64-bit NTP timestamp.
396
+ */
246
397
  function now() {
247
- const now = ns() / 1000n;
248
- const seconds = now / 1000000n;
249
- const frac = now - seconds * 1000000n;
250
- return seconds + EPOCH$1 << 32n | (frac << 32n) / 1000000n;
251
- }
252
- function ns() {
253
- return process.hrtime.bigint();
398
+ const nowMs = BigInt(Date.now());
399
+ const seconds = nowMs / 1000n;
400
+ const frac = nowMs - seconds * 1000n;
401
+ return seconds + EPOCH$1 << 32n | (frac << 32n) / 1000n;
254
402
  }
403
+ /**
404
+ * Splits a 64-bit NTP timestamp into its seconds and fractional parts.
405
+ *
406
+ * @param ntp - A 64-bit NTP timestamp (upper 32 bits = seconds, lower 32 bits = fraction).
407
+ * @returns A tuple of [seconds, fraction] as 32-bit unsigned integers.
408
+ */
255
409
  function parts(ntp) {
256
410
  return [Number(ntp >> 32n), Number(ntp & 4294967295n)];
257
411
  }
412
+ /**
413
+ * Decodes an NTP timing packet from a buffer into its constituent fields.
414
+ * Expects at least 24 bytes; the send timestamp fields (bytes 24-31) default
415
+ * to 0 if the buffer is shorter than 32 bytes.
416
+ *
417
+ * @param buffer - The raw NTP packet buffer (minimum 24 bytes).
418
+ * @returns The decoded packet fields.
419
+ * @throws RangeError if the buffer is shorter than 24 bytes.
420
+ */
258
421
  function decode$2(buffer) {
259
422
  if (buffer.length < 24) throw new RangeError(`NTP packet too small: expected at least 24 bytes, got ${buffer.length}`);
260
423
  return {
@@ -270,6 +433,12 @@ function decode$2(buffer) {
270
433
  sendtime_frac: buffer.length >= 32 ? buffer.readUInt32BE(28) : 0
271
434
  };
272
435
  }
436
+ /**
437
+ * Encodes NTP timing packet fields into a 32-byte buffer.
438
+ *
439
+ * @param fields - The packet fields to encode.
440
+ * @returns A 32-byte buffer containing the encoded NTP packet.
441
+ */
273
442
  function encode$2(fields) {
274
443
  const buffer = Buffer.allocUnsafe(32);
275
444
  buffer.writeUInt8(fields.proto, 0);
@@ -294,6 +463,11 @@ var opack_exports = /* @__PURE__ */ __exportAll({
294
463
  int: () => int,
295
464
  sizedInteger: () => sizedInteger
296
465
  });
466
+ /**
467
+ * OPack wire-format tag bytes. Each tag identifies the type and sometimes
468
+ * the inline length of the value that follows. Apple uses OPack for
469
+ * Companion Link and other device-to-device communication.
470
+ */
297
471
  const TAG = {
298
472
  TRUE: 1,
299
473
  FALSE: 2,
@@ -335,59 +509,147 @@ const TAG = {
335
509
  };
336
510
  const textDecoder = new TextDecoder();
337
511
  const textEncoder = new TextEncoder();
512
+ /**
513
+ * Wrapper that forces a number to be encoded as an OPack float (FLOAT64).
514
+ * Without this wrapper, JavaScript numbers that happen to be integers
515
+ * would be encoded as OPack integers instead.
516
+ */
338
517
  var Float = class {
518
+ /** The wrapped floating-point value. */
339
519
  get value() {
340
520
  return this.#value;
341
521
  }
342
522
  #value;
523
+ /**
524
+ * @param value - The floating-point number to wrap.
525
+ */
343
526
  constructor(value) {
344
527
  this.#value = value;
345
528
  }
346
529
  };
530
+ /**
531
+ * Wrapper that forces a number to be encoded as an OPack integer.
532
+ * Useful when a value must be encoded as an integer even if it could
533
+ * be represented as an inline value.
534
+ */
347
535
  var Integer = class {
536
+ /** The wrapped integer value. */
348
537
  get value() {
349
538
  return this.#value;
350
539
  }
351
540
  #value;
541
+ /**
542
+ * @param value - The integer number to wrap.
543
+ */
352
544
  constructor(value) {
353
545
  this.#value = value;
354
546
  }
355
547
  };
548
+ /**
549
+ * An integer with an explicit byte size. Produced during OPack decoding when
550
+ * the wire format specifies the exact byte width (1, 2, 4, or 8). During
551
+ * encoding, the specified size is preserved to maintain wire compatibility.
552
+ */
356
553
  var SizedInteger = class {
554
+ /** The byte width of this integer on the wire (1, 2, 4, or 8). */
357
555
  get size() {
358
556
  return this.#size;
359
557
  }
558
+ /** The numeric value. */
360
559
  get value() {
361
560
  return this.#value;
362
561
  }
363
562
  #size;
364
563
  #value;
564
+ /**
565
+ * @param value - The integer value.
566
+ * @param size - The byte width for wire encoding (1, 2, 4, or 8).
567
+ */
365
568
  constructor(value, size) {
366
569
  this.#size = size;
367
570
  this.#value = value;
368
571
  }
572
+ /**
573
+ * Returns the numeric value, enabling implicit numeric coercion.
574
+ *
575
+ * @returns The integer value.
576
+ */
369
577
  valueOf() {
370
578
  return this.#value;
371
579
  }
372
580
  };
581
+ /**
582
+ * Creates an OPack float wrapper, ensuring the value is encoded as FLOAT64
583
+ * on the wire regardless of whether it is a whole number.
584
+ *
585
+ * @param value - The floating-point number.
586
+ * @returns A Float wrapper for OPack encoding.
587
+ */
373
588
  function float(value) {
374
589
  return new Float(value);
375
590
  }
591
+ /**
592
+ * Creates an OPack integer wrapper, ensuring the value is encoded as an
593
+ * explicit integer type on the wire.
594
+ *
595
+ * @param value - The integer number.
596
+ * @returns An Integer wrapper for OPack encoding.
597
+ */
376
598
  function int(value) {
377
599
  return new Integer(value);
378
600
  }
601
+ /**
602
+ * Creates an OPack sized integer with an explicit byte width.
603
+ * Used during decoding to preserve the original wire size, and during
604
+ * encoding to force a specific byte width.
605
+ *
606
+ * @param value - The integer value.
607
+ * @param size - The byte width (1, 2, 4, or 8).
608
+ * @returns A SizedInteger wrapper for OPack encoding.
609
+ */
379
610
  function sizedInteger(value, size) {
380
611
  return new SizedInteger(value, size);
381
612
  }
613
+ /**
614
+ * Decodes an OPack-encoded byte array into a JavaScript value.
615
+ * OPack is Apple's compact binary serialization format used in
616
+ * Companion Link and other protocols.
617
+ *
618
+ * @param data - The raw OPack-encoded bytes.
619
+ * @returns The decoded JavaScript value (object, array, string, number, boolean, null, or Uint8Array).
620
+ */
382
621
  function decode$1(data) {
383
622
  return _unpackAt(data, 0, []).value;
384
623
  }
624
+ /**
625
+ * Encodes a JavaScript value into OPack binary format.
626
+ * Supports null, booleans, numbers, strings, Uint8Array/Buffer, arrays,
627
+ * plain objects, and the explicit type wrappers ({@link float}, {@link int}, {@link sizedInteger}).
628
+ * Automatically deduplicates repeated values using back-references.
629
+ *
630
+ * @param data - The value to encode.
631
+ * @returns The OPack-encoded bytes.
632
+ * @throws TypeError if the value type is unsupported.
633
+ */
385
634
  function encode$1(data) {
386
635
  return _pack(data, []);
387
636
  }
637
+ /**
638
+ * Creates a single-byte Uint8Array.
639
+ *
640
+ * @param b - The byte value (0-255).
641
+ * @returns A Uint8Array containing the single byte.
642
+ */
388
643
  function u8(b) {
389
644
  return Uint8Array.of(b);
390
645
  }
646
+ /**
647
+ * Converts an unsigned integer to a little-endian byte array.
648
+ *
649
+ * @param value - The integer value to convert.
650
+ * @param byteLen - The number of bytes to produce.
651
+ * @returns A Uint8Array of length `byteLen` in little-endian order.
652
+ */
391
653
  function uintToLEBytes(value, byteLen) {
392
654
  const out = new Uint8Array(byteLen);
393
655
  let v = BigInt(value);
@@ -397,6 +659,15 @@ function uintToLEBytes(value, byteLen) {
397
659
  }
398
660
  return out;
399
661
  }
662
+ /**
663
+ * Reads a little-endian unsigned integer of arbitrary byte length from a buffer.
664
+ * Returns 0 if the read would exceed the buffer bounds.
665
+ *
666
+ * @param buf - The source buffer.
667
+ * @param offset - The byte offset to start reading from.
668
+ * @param len - The number of bytes to read (1, 2, 4, or any).
669
+ * @returns The decoded unsigned integer value.
670
+ */
400
671
  function readLittleEndian(buf, offset, len) {
401
672
  if (offset + len > buf.length) return 0;
402
673
  if (len === 1) return buf[offset];
@@ -408,6 +679,16 @@ function readLittleEndian(buf, offset, len) {
408
679
  return Number(v);
409
680
  }
410
681
  }
682
+ /**
683
+ * Recursively packs a JavaScript value into OPack binary format.
684
+ * Maintains an object list for back-reference deduplication: if a packed
685
+ * value already exists in the list, a compact reference tag is emitted instead.
686
+ *
687
+ * @param data - The value to pack.
688
+ * @param objectList - Accumulator of previously packed objects for deduplication.
689
+ * @returns The OPack-encoded bytes for this value.
690
+ * @throws TypeError if the value type is unsupported.
691
+ */
411
692
  function _pack(data, objectList) {
412
693
  let packed = null;
413
694
  if (data === null || data === void 0) packed = u8(TAG.NULL);
@@ -444,6 +725,10 @@ function _pack(data, objectList) {
444
725
  packed = new Uint8Array(9);
445
726
  packed[0] = TAG.FLOAT64;
446
727
  new DataView(packed.buffer, packed.byteOffset + 1, 8).setFloat64(0, data, true);
728
+ } else if (data < 0) {
729
+ packed = new Uint8Array(9);
730
+ packed[0] = TAG.INT_8BYTE;
731
+ new DataView(packed.buffer, packed.byteOffset + 1, 8).setBigInt64(0, BigInt(data), true);
447
732
  } else if (data <= TAG.INT_INLINE_MAX_VALUE) packed = u8(TAG.INT_BASE + data);
448
733
  else if (data <= 255) {
449
734
  packed = new Uint8Array(2);
@@ -612,6 +897,18 @@ function _pack(data, objectList) {
612
897
  else if (packed.length > 1) objectList.push(packed);
613
898
  return packed;
614
899
  }
900
+ /**
901
+ * Unpacks a single OPack value starting at the given offset.
902
+ * Handles all OPack types: booleans, null, UUID, timestamp, integers, floats,
903
+ * strings, byte arrays, arrays, dictionaries, and back-references.
904
+ * Decoded non-reference values are added to the object list for future reference resolution.
905
+ *
906
+ * @param data - The full OPack-encoded buffer.
907
+ * @param offset - The byte offset to start unpacking from.
908
+ * @param objectList - Accumulator of previously unpacked objects for reference resolution.
909
+ * @returns The unpacked value and the new byte offset.
910
+ * @throws TypeError if the buffer is exhausted or an unknown tag is encountered.
911
+ */
615
912
  function _unpackAt(data, offset, objectList) {
616
913
  if (offset >= data.length) throw new TypeError("No data to unpack");
617
914
  const tag = data[offset];
@@ -1261,7 +1558,15 @@ var tlv8_exports = /* @__PURE__ */ __exportAll({
1261
1558
  decode: () => decode,
1262
1559
  encode: () => encode
1263
1560
  });
1561
+ /**
1562
+ * TLV8 pairing flags used during HAP pair-setup and pair-verify.
1563
+ * Sent as part of the TLV8 Flags (0x13) value.
1564
+ */
1264
1565
  const Flags = { TransientPairing: 16 };
1566
+ /**
1567
+ * TLV8 error codes returned by the accessory during pairing.
1568
+ * Included in the Error (0x07) TLV value.
1569
+ */
1265
1570
  const ErrorCode = {
1266
1571
  Unknown: 1,
1267
1572
  Authentication: 2,
@@ -1271,6 +1576,10 @@ const ErrorCode = {
1271
1576
  Unavailable: 6,
1272
1577
  Busy: 7
1273
1578
  };
1579
+ /**
1580
+ * HAP pairing method identifiers. Sent in the Method (0x00) TLV value
1581
+ * to indicate which pairing operation is being performed.
1582
+ */
1274
1583
  const Method = {
1275
1584
  PairSetup: 0,
1276
1585
  PairSetupWithAuth: 1,
@@ -1279,6 +1588,10 @@ const Method = {
1279
1588
  RemovePairing: 4,
1280
1589
  ListPairing: 5
1281
1590
  };
1591
+ /**
1592
+ * HAP pairing state machine steps (M1 through M6).
1593
+ * Each state corresponds to a message in the SRP pair-setup or pair-verify flow.
1594
+ */
1282
1595
  const State = {
1283
1596
  M1: 1,
1284
1597
  M2: 2,
@@ -1287,6 +1600,10 @@ const State = {
1287
1600
  M5: 5,
1288
1601
  M6: 6
1289
1602
  };
1603
+ /**
1604
+ * TLV8 type identifiers for the fields exchanged during HAP pairing.
1605
+ * Each value is the type byte that precedes the length and data in a TLV8 entry.
1606
+ */
1290
1607
  const Value = {
1291
1608
  Method: 0,
1292
1609
  Identifier: 1,
@@ -1305,14 +1622,31 @@ const Value = {
1305
1622
  Name: 17,
1306
1623
  Flags: 19
1307
1624
  };
1625
+ /**
1626
+ * Error thrown when a TLV8 pairing exchange fails.
1627
+ * Carries the numeric error code from the accessory when available.
1628
+ */
1308
1629
  var TLV8PairingError = class extends Error {
1630
+ /** The TLV8 error code from the accessory, if present. */
1309
1631
  code;
1632
+ /**
1633
+ * @param message - Human-readable error description.
1634
+ * @param code - The TLV8 error code from the accessory response.
1635
+ */
1310
1636
  constructor(message, code) {
1311
1637
  super(message);
1312
1638
  this.name = "TLV8PairingError";
1313
1639
  this.code = code;
1314
1640
  }
1315
1641
  };
1642
+ /**
1643
+ * Inspects a decoded TLV8 response for error or back-off conditions and throws
1644
+ * an appropriate {@link TLV8PairingError}. Always throws; the return type `never`
1645
+ * signals to the compiler that execution does not continue past this call.
1646
+ *
1647
+ * @param data - The decoded TLV8 map from a pairing response.
1648
+ * @throws TLV8PairingError with the specific error code, back-off time, or a generic message.
1649
+ */
1316
1650
  function bail(data) {
1317
1651
  if (data.has(Value.BackOff)) {
1318
1652
  const buffer = data.get(Value.BackOff);
@@ -1326,6 +1660,15 @@ function bail(data) {
1326
1660
  }
1327
1661
  throw new TLV8PairingError("Invalid response");
1328
1662
  }
1663
+ /**
1664
+ * Encodes an array of TLV8 entries into a single buffer.
1665
+ * Values longer than 255 bytes are automatically split into multiple
1666
+ * consecutive TLV fragments of the same type, as required by the TLV8 spec.
1667
+ *
1668
+ * @param entries - An array of [type, value] tuples. Values can be a single byte (number),
1669
+ * a Buffer, or a Uint8Array.
1670
+ * @returns A buffer containing all TLV8 entries concatenated.
1671
+ */
1329
1672
  function encode(entries) {
1330
1673
  let totalSize = 0;
1331
1674
  for (const [, valueRaw] of entries) {
@@ -1361,6 +1704,14 @@ function encode(entries) {
1361
1704
  }
1362
1705
  return result;
1363
1706
  }
1707
+ /**
1708
+ * Decodes a TLV8 buffer into a map of type to value.
1709
+ * Consecutive entries with the same type are automatically concatenated,
1710
+ * reassembling fragmented values as required by the TLV8 spec.
1711
+ *
1712
+ * @param buf - The raw TLV8-encoded buffer.
1713
+ * @returns A map from TLV8 type byte to the reassembled value buffer.
1714
+ */
1364
1715
  function decode(buf) {
1365
1716
  const map = /* @__PURE__ */ new Map();
1366
1717
  let i = 0;
@@ -1380,4 +1731,4 @@ function decode(buf) {
1380
1731
  }
1381
1732
 
1382
1733
  //#endregion
1383
- export { daap_exports as DAAP, ntp_exports as NTP, opack_exports as OPack, plist_exports as Plist, tlv8_exports as TLV8 };
1734
+ export { daap_exports as DAAP, nskeyedarchiver_exports as NSKeyedArchiver, ntp_exports as NTP, opack_exports as OPack, plist_exports as Plist, tlv8_exports as TLV8 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@basmilius/apple-encoding",
3
3
  "description": "Common encoding utilities for Apple Protocols.",
4
- "version": "0.9.19",
4
+ "version": "0.10.1",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": {