appium-ios-remotexpc 0.11.0 → 0.13.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.
Files changed (172) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +28 -0
  3. package/build/src/constants.d.ts +2 -0
  4. package/build/src/constants.d.ts.map +1 -0
  5. package/build/src/constants.js +3 -0
  6. package/build/src/index.d.ts +2 -1
  7. package/build/src/index.d.ts.map +1 -1
  8. package/build/src/index.js +2 -1
  9. package/build/src/lib/apple-tv/constants.d.ts +0 -1
  10. package/build/src/lib/apple-tv/constants.d.ts.map +1 -1
  11. package/build/src/lib/apple-tv/constants.js +0 -1
  12. package/build/src/lib/apple-tv/discovery/device-discovery.d.ts +10 -0
  13. package/build/src/lib/apple-tv/discovery/device-discovery.d.ts.map +1 -0
  14. package/build/src/lib/apple-tv/discovery/device-discovery.js +22 -0
  15. package/build/src/lib/apple-tv/discovery/index.d.ts +2 -0
  16. package/build/src/lib/apple-tv/discovery/index.d.ts.map +1 -0
  17. package/build/src/lib/apple-tv/discovery/index.js +1 -0
  18. package/build/src/lib/apple-tv/encryption/chacha20-poly1305.js +2 -2
  19. package/build/src/lib/apple-tv/encryption/ed25519.js +2 -2
  20. package/build/src/lib/apple-tv/encryption/hkdf.js +2 -2
  21. package/build/src/lib/apple-tv/index.d.ts +5 -0
  22. package/build/src/lib/apple-tv/index.d.ts.map +1 -1
  23. package/build/src/lib/apple-tv/index.js +5 -0
  24. package/build/src/lib/apple-tv/network/constants.d.ts +10 -0
  25. package/build/src/lib/apple-tv/network/constants.d.ts.map +1 -0
  26. package/build/src/lib/apple-tv/network/constants.js +9 -0
  27. package/build/src/lib/apple-tv/network/index.d.ts +4 -0
  28. package/build/src/lib/apple-tv/network/index.d.ts.map +1 -0
  29. package/build/src/lib/apple-tv/network/index.js +2 -0
  30. package/build/src/lib/apple-tv/network/network-client.d.ts +16 -0
  31. package/build/src/lib/apple-tv/network/network-client.d.ts.map +1 -0
  32. package/build/src/lib/apple-tv/network/network-client.js +169 -0
  33. package/build/src/lib/apple-tv/network/types.d.ts +8 -0
  34. package/build/src/lib/apple-tv/network/types.d.ts.map +1 -0
  35. package/build/src/lib/apple-tv/network/types.js +1 -0
  36. package/build/src/lib/apple-tv/pairing/index.d.ts +3 -0
  37. package/build/src/lib/apple-tv/pairing/index.d.ts.map +1 -0
  38. package/build/src/lib/apple-tv/pairing/index.js +2 -0
  39. package/build/src/lib/apple-tv/pairing/pairing-service.d.ts +15 -0
  40. package/build/src/lib/apple-tv/pairing/pairing-service.d.ts.map +1 -0
  41. package/build/src/lib/apple-tv/pairing/pairing-service.js +112 -0
  42. package/build/src/lib/apple-tv/pairing/user-input-service.d.ts +8 -0
  43. package/build/src/lib/apple-tv/pairing/user-input-service.d.ts.map +1 -0
  44. package/build/src/lib/apple-tv/pairing/user-input-service.js +61 -0
  45. package/build/src/lib/apple-tv/pairing-protocol/constants.d.ts +18 -0
  46. package/build/src/lib/apple-tv/pairing-protocol/constants.d.ts.map +1 -0
  47. package/build/src/lib/apple-tv/pairing-protocol/constants.js +17 -0
  48. package/build/src/lib/apple-tv/pairing-protocol/index.d.ts +4 -0
  49. package/build/src/lib/apple-tv/pairing-protocol/index.d.ts.map +1 -0
  50. package/build/src/lib/apple-tv/pairing-protocol/index.js +2 -0
  51. package/build/src/lib/apple-tv/pairing-protocol/pairing-protocol.d.ts +159 -0
  52. package/build/src/lib/apple-tv/pairing-protocol/pairing-protocol.d.ts.map +1 -0
  53. package/build/src/lib/apple-tv/pairing-protocol/pairing-protocol.js +494 -0
  54. package/build/src/lib/apple-tv/pairing-protocol/types.d.ts +57 -0
  55. package/build/src/lib/apple-tv/pairing-protocol/types.d.ts.map +1 -0
  56. package/build/src/lib/apple-tv/pairing-protocol/types.js +1 -0
  57. package/build/src/lib/apple-tv/srp/srp-client.js +2 -2
  58. package/build/src/lib/apple-tv/storage/index.d.ts +3 -0
  59. package/build/src/lib/apple-tv/storage/index.d.ts.map +1 -0
  60. package/build/src/lib/apple-tv/storage/index.js +1 -0
  61. package/build/src/lib/apple-tv/storage/pairing-storage.d.ts +12 -0
  62. package/build/src/lib/apple-tv/storage/pairing-storage.d.ts.map +1 -0
  63. package/build/src/lib/apple-tv/storage/pairing-storage.js +36 -0
  64. package/build/src/lib/apple-tv/storage/types.d.ts +5 -0
  65. package/build/src/lib/apple-tv/storage/types.d.ts.map +1 -0
  66. package/build/src/lib/apple-tv/storage/types.js +1 -0
  67. package/build/src/lib/apple-tv/types.d.ts +0 -1
  68. package/build/src/lib/apple-tv/types.d.ts.map +1 -1
  69. package/build/src/lib/bonjour/bonjour-discovery.d.ts.map +1 -1
  70. package/build/src/lib/bonjour/bonjour-discovery.js +4 -2
  71. package/build/src/lib/lockdown/index.d.ts.map +1 -1
  72. package/build/src/lib/lockdown/index.js +4 -4
  73. package/build/src/lib/logger.d.ts +2 -0
  74. package/build/src/lib/logger.d.ts.map +1 -0
  75. package/build/src/lib/logger.js +7 -0
  76. package/build/src/lib/pair-record/pair-record.d.ts.map +1 -1
  77. package/build/src/lib/pair-record/pair-record.js +2 -2
  78. package/build/src/lib/plist/binary-plist-parser.d.ts.map +1 -1
  79. package/build/src/lib/plist/binary-plist-parser.js +2 -2
  80. package/build/src/lib/plist/length-based-splitter.d.ts.map +1 -1
  81. package/build/src/lib/plist/length-based-splitter.js +2 -2
  82. package/build/src/lib/plist/plist-decoder.d.ts.map +1 -1
  83. package/build/src/lib/plist/plist-decoder.js +2 -2
  84. package/build/src/lib/plist/plist-parser.js +2 -2
  85. package/build/src/lib/plist/plist-service.d.ts.map +1 -1
  86. package/build/src/lib/plist/plist-service.js +3 -3
  87. package/build/src/lib/remote-xpc/remote-xpc-connection.js +2 -2
  88. package/build/src/lib/tss/index.js +2 -2
  89. package/build/src/lib/tunnel/index.d.ts.map +1 -1
  90. package/build/src/lib/tunnel/index.js +2 -2
  91. package/build/src/lib/tunnel/packet-stream-client.d.ts.map +1 -1
  92. package/build/src/lib/tunnel/packet-stream-client.js +2 -2
  93. package/build/src/lib/tunnel/packet-stream-server.d.ts.map +1 -1
  94. package/build/src/lib/tunnel/packet-stream-server.js +2 -2
  95. package/build/src/lib/tunnel/tunnel-api-client.d.ts.map +1 -1
  96. package/build/src/lib/tunnel/tunnel-api-client.js +2 -2
  97. package/build/src/lib/tunnel/tunnel-registry-server.js +2 -2
  98. package/build/src/lib/usbmux/index.d.ts.map +1 -1
  99. package/build/src/lib/usbmux/index.js +2 -2
  100. package/build/src/services/ios/afc/index.d.ts.map +1 -1
  101. package/build/src/services/ios/afc/index.js +2 -2
  102. package/build/src/services/ios/base-service.d.ts.map +1 -1
  103. package/build/src/services/ios/base-service.js +2 -2
  104. package/build/src/services/ios/diagnostic-service/index.d.ts.map +1 -1
  105. package/build/src/services/ios/diagnostic-service/index.js +2 -2
  106. package/build/src/services/ios/mobile-config/index.d.ts.map +1 -1
  107. package/build/src/services/ios/mobile-config/index.js +3 -2
  108. package/build/src/services/ios/mobile-image-mounter/index.js +2 -2
  109. package/build/src/services/ios/notification-proxy/index.d.ts.map +1 -1
  110. package/build/src/services/ios/notification-proxy/index.js +2 -2
  111. package/build/src/services/ios/power-assertion/index.d.ts.map +1 -1
  112. package/build/src/services/ios/power-assertion/index.js +2 -2
  113. package/build/src/services/ios/syslog-service/index.d.ts.map +1 -1
  114. package/build/src/services/ios/syslog-service/index.js +3 -3
  115. package/build/src/services/ios/tunnel-service/index.d.ts.map +1 -1
  116. package/build/src/services/ios/tunnel-service/index.js +2 -2
  117. package/build/src/services/ios/webinspector/index.js +2 -2
  118. package/package.json +4 -2
  119. package/scripts/pair-appletv.ts +79 -0
  120. package/scripts/test-tunnel-creation.ts +1 -1
  121. package/src/constants.ts +4 -0
  122. package/src/index.ts +2 -0
  123. package/src/lib/apple-tv/constants.ts +0 -1
  124. package/src/lib/apple-tv/discovery/device-discovery.ts +34 -0
  125. package/src/lib/apple-tv/discovery/index.ts +1 -0
  126. package/src/lib/apple-tv/encryption/chacha20-poly1305.ts +2 -2
  127. package/src/lib/apple-tv/encryption/ed25519.ts +2 -2
  128. package/src/lib/apple-tv/encryption/hkdf.ts +2 -2
  129. package/src/lib/apple-tv/index.ts +5 -0
  130. package/src/lib/apple-tv/network/constants.ts +9 -0
  131. package/src/lib/apple-tv/network/index.ts +3 -0
  132. package/src/lib/apple-tv/network/network-client.ts +214 -0
  133. package/src/lib/apple-tv/network/types.ts +7 -0
  134. package/src/lib/apple-tv/pairing/index.ts +2 -0
  135. package/src/lib/apple-tv/pairing/pairing-service.ts +175 -0
  136. package/src/lib/apple-tv/pairing/user-input-service.ts +71 -0
  137. package/src/lib/apple-tv/pairing-protocol/constants.ts +19 -0
  138. package/src/lib/apple-tv/pairing-protocol/index.ts +8 -0
  139. package/src/lib/apple-tv/pairing-protocol/pairing-protocol.ts +636 -0
  140. package/src/lib/apple-tv/pairing-protocol/types.ts +60 -0
  141. package/src/lib/apple-tv/srp/srp-client.ts +2 -2
  142. package/src/lib/apple-tv/storage/index.ts +2 -0
  143. package/src/lib/apple-tv/storage/pairing-storage.ts +60 -0
  144. package/src/lib/apple-tv/storage/types.ts +9 -0
  145. package/src/lib/apple-tv/types.ts +0 -1
  146. package/src/lib/bonjour/bonjour-discovery.ts +4 -2
  147. package/src/lib/lockdown/index.ts +4 -4
  148. package/src/lib/logger.ts +9 -0
  149. package/src/lib/pair-record/pair-record.ts +3 -2
  150. package/src/lib/plist/binary-plist-parser.ts +2 -3
  151. package/src/lib/plist/length-based-splitter.ts +2 -2
  152. package/src/lib/plist/plist-decoder.ts +2 -2
  153. package/src/lib/plist/plist-parser.ts +2 -2
  154. package/src/lib/plist/plist-service.ts +3 -3
  155. package/src/lib/remote-xpc/remote-xpc-connection.ts +2 -2
  156. package/src/lib/tss/index.ts +2 -2
  157. package/src/lib/tunnel/index.ts +2 -2
  158. package/src/lib/tunnel/packet-stream-client.ts +3 -2
  159. package/src/lib/tunnel/packet-stream-server.ts +3 -2
  160. package/src/lib/tunnel/tunnel-api-client.ts +2 -3
  161. package/src/lib/tunnel/tunnel-registry-server.ts +2 -2
  162. package/src/lib/usbmux/index.ts +2 -2
  163. package/src/services/ios/afc/index.ts +2 -2
  164. package/src/services/ios/base-service.ts +2 -3
  165. package/src/services/ios/diagnostic-service/index.ts +2 -3
  166. package/src/services/ios/mobile-config/index.ts +3 -2
  167. package/src/services/ios/mobile-image-mounter/index.ts +2 -2
  168. package/src/services/ios/notification-proxy/index.ts +2 -3
  169. package/src/services/ios/power-assertion/index.ts +2 -3
  170. package/src/services/ios/syslog-service/index.ts +3 -3
  171. package/src/services/ios/tunnel-service/index.ts +2 -2
  172. package/src/services/ios/webinspector/index.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [0.13.0](https://github.com/appium/appium-ios-remotexpc/compare/v0.12.0...v0.13.0) (2025-11-07)
2
+
3
+ ### Features
4
+
5
+ * appletv pairing ([#76](https://github.com/appium/appium-ios-remotexpc/issues/76)) ([f974b12](https://github.com/appium/appium-ios-remotexpc/commit/f974b12f137152421f359f667d60d7e116a89353))
6
+
7
+ ## [0.12.0](https://github.com/appium/appium-ios-remotexpc/compare/v0.11.0...v0.12.0) (2025-11-05)
8
+
9
+ ### Features
10
+
11
+ * add configurable log levels via LOG_LEVEL env var ([#92](https://github.com/appium/appium-ios-remotexpc/issues/92)) ([0a027a6](https://github.com/appium/appium-ios-remotexpc/commit/0a027a6377462ea0364e6eaf3de5c1321d8094c8))
12
+
1
13
  ## [0.11.0](https://github.com/appium/appium-ios-remotexpc/compare/v0.10.2...v0.11.0) (2025-11-05)
2
14
 
3
15
  ### Features
package/README.md CHANGED
@@ -42,6 +42,34 @@ npm install appium-ios-remotexpc
42
42
  - **Pair Record Management**: Read and write device pairing records.
43
43
  - **Packet Streaming**: Stream packets between host and device for service communication.
44
44
 
45
+ ## Configuration
46
+
47
+ ### Environment Variables
48
+
49
+ #### APPIUM_IOS_REMOTEXPC_LOG_LEVEL
50
+
51
+ Controls the logging verbosity of the library.
52
+
53
+ - **Default**: `info`
54
+ - **Possible values**: Standard log levels supported by @appium/support logger
55
+ - `silly` - Most verbose, logs everything
56
+ - `verbose` - Very detailed logs
57
+ - `debug` - Detailed debugging information
58
+ - `info` - General informational messages (default)
59
+ - `warn` - Warning messages
60
+ - `error` - Error messages only
61
+ - **Usage**:
62
+
63
+ ```bash
64
+ # Set log level to debug for verbose output
65
+ APPIUM_IOS_REMOTEXPC_LOG_LEVEL=debug npm test
66
+
67
+ # Set log level to error for minimal output
68
+ APPIUM_IOS_REMOTEXPC_LOG_LEVEL=error node your-script.js
69
+ ```
70
+
71
+ This is particularly useful for debugging issues or reducing log noise in production environments.
72
+
45
73
  ## Architecture Flow
46
74
 
47
75
  The following diagram illustrates the high-level flow of how the tunnel is created:
@@ -0,0 +1,2 @@
1
+ export declare const STRONGBOX_CONTAINER_NAME = "appium-ios-remotexpc";
2
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Global constants used across the appium-ios-remotexpc package
2
+ // Strongbox container name for storing credentials and configuration
3
+ export const STRONGBOX_CONTAINER_NAME = 'appium-ios-remotexpc';
@@ -1,3 +1,4 @@
1
+ import { STRONGBOX_CONTAINER_NAME } from './constants.js';
1
2
  import { createLockdownServiceByUDID } from './lib/lockdown/index.js';
2
3
  import { PacketStreamClient, PacketStreamServer, TunnelManager } from './lib/tunnel/index.js';
3
4
  import { TunnelRegistryServer, startTunnelRegistryServer } from './lib/tunnel/tunnel-registry-server.js';
@@ -6,5 +7,5 @@ import * as Services from './services.js';
6
7
  import { startCoreDeviceProxy } from './services/ios/tunnel-service/index.js';
7
8
  export type { DiagnosticsService, MobileImageMounterService, NotificationProxyService, MobileConfigService, PowerAssertionService, PowerAssertionOptions, SpringboardService, WebInspectorService, MisagentService, SyslogService, SocketInfo, TunnelResult, TunnelRegistry, TunnelRegistryEntry, DiagnosticsServiceWithConnection, MobileImageMounterServiceWithConnection, NotificationProxyServiceWithConnection, MobileConfigServiceWithConnection, PowerAssertionServiceWithConnection, SpringboardServiceWithConnection, WebInspectorServiceWithConnection, MisagentServiceWithConnection, } from './lib/types.js';
8
9
  export { PowerAssertionType } from './lib/types.js';
9
- export { createUsbmux, Services, Usbmux, TunnelManager, PacketStreamServer, PacketStreamClient, createLockdownServiceByUDID, startCoreDeviceProxy, TunnelRegistryServer, startTunnelRegistryServer, };
10
+ export { STRONGBOX_CONTAINER_NAME, createUsbmux, Services, Usbmux, TunnelManager, PacketStreamServer, PacketStreamClient, createLockdownServiceByUDID, startCoreDeviceProxy, TunnelRegistryServer, startTunnelRegistryServer, };
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,YAAY,EACV,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,gCAAgC,EAChC,uCAAuC,EACvC,sCAAsC,EACtC,iCAAiC,EACjC,mCAAmC,EACnC,gCAAgC,EAChC,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,GAC1B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,YAAY,EACV,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,gCAAgC,EAChC,uCAAuC,EACvC,sCAAsC,EACtC,iCAAiC,EACjC,mCAAmC,EACnC,gCAAgC,EAChC,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,GAC1B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { STRONGBOX_CONTAINER_NAME } from './constants.js';
1
2
  import { createLockdownServiceByUDID } from './lib/lockdown/index.js';
2
3
  import { PacketStreamClient, PacketStreamServer, TunnelManager, } from './lib/tunnel/index.js';
3
4
  import { TunnelRegistryServer, startTunnelRegistryServer, } from './lib/tunnel/tunnel-registry-server.js';
@@ -5,4 +6,4 @@ import { Usbmux, createUsbmux } from './lib/usbmux/index.js';
5
6
  import * as Services from './services.js';
6
7
  import { startCoreDeviceProxy } from './services/ios/tunnel-service/index.js';
7
8
  export { PowerAssertionType } from './lib/types.js';
8
- export { createUsbmux, Services, Usbmux, TunnelManager, PacketStreamServer, PacketStreamClient, createLockdownServiceByUDID, startCoreDeviceProxy, TunnelRegistryServer, startTunnelRegistryServer, };
9
+ export { STRONGBOX_CONTAINER_NAME, createUsbmux, Services, Usbmux, TunnelManager, PacketStreamServer, PacketStreamClient, createLockdownServiceByUDID, startCoreDeviceProxy, TunnelRegistryServer, startTunnelRegistryServer, };
@@ -2,7 +2,6 @@ export declare const DEFAULT_PAIRING_CONFIG: {
2
2
  readonly timeout: 30000;
3
3
  readonly discoveryTimeout: 5000;
4
4
  readonly maxRetries: 3;
5
- readonly pairingDirectory: ".pairing";
6
5
  };
7
6
  export declare const PairingDataComponentType: {
8
7
  readonly METHOD: 0;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/apple-tv/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB;;;;;CAKzB,CAAC;AAGX,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC3B,CAAC;AAGX,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAG1C,eAAO,MAAM,cAAc,QAc1B,CAAC;AAGF,eAAO,MAAM,aAAa,QAAY,CAAC;AAGvC,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAG3C,eAAO,MAAM,YAAY,eAAe,CAAC;AAGzC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAGxC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAGxC,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAG5C,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAGnC,eAAO,MAAM,WAAW,IAAO,CAAC;AAChC,eAAO,MAAM,WAAW,IAAO,CAAC;AAChC,eAAO,MAAM,YAAY,IAAO,CAAC;AACjC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,KAAO,CAAC;AACzC,eAAO,MAAM,uBAAuB,KAAO,CAAC;AAC5C,eAAO,MAAM,sBAAsB,KAAO,CAAC;AAC3C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAGxC,eAAO,MAAM,kBAAkB,KAAO,CAAC;AACvC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AACxC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AACxC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AAGxC,eAAO,MAAM,wBAAwB,KAAO,CAAC;AAC7C,eAAO,MAAM,6BAA6B,KAAO,CAAC;AAClD,eAAO,MAAM,8BAA8B,KAAO,CAAC;AACnD,eAAO,MAAM,8BAA8B,KAAO,CAAC;AAGnD,eAAO,MAAM,uBAAuB,MAAO,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAO,CAAC;AACjD,eAAO,MAAM,6BAA6B,MAAO,CAAC;AAClD,eAAO,MAAM,6BAA6B,MAAO,CAAC;AAGlD,eAAO,MAAM,uBAAuB,MAAO,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAO,CAAC;AAGjD,eAAO,MAAM,sBAAsB,MAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAO,CAAC;AAGhD,eAAO,MAAM,gBAAgB,MAAO,CAAC;AACrC,eAAO,MAAM,iBAAiB,QAAS,CAAC;AACxC,eAAO,MAAM,iBAAiB,aAAa,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/apple-tv/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB;;;;CAIzB,CAAC;AAGX,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC3B,CAAC;AAGX,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAG1C,eAAO,MAAM,cAAc,QAc1B,CAAC;AAGF,eAAO,MAAM,aAAa,QAAY,CAAC;AAGvC,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAG3C,eAAO,MAAM,YAAY,eAAe,CAAC;AAGzC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAGxC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAGxC,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAG5C,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAGnC,eAAO,MAAM,WAAW,IAAO,CAAC;AAChC,eAAO,MAAM,WAAW,IAAO,CAAC;AAChC,eAAO,MAAM,YAAY,IAAO,CAAC;AACjC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,KAAO,CAAC;AACzC,eAAO,MAAM,uBAAuB,KAAO,CAAC;AAC5C,eAAO,MAAM,sBAAsB,KAAO,CAAC;AAC3C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAGxC,eAAO,MAAM,kBAAkB,KAAO,CAAC;AACvC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AACxC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AACxC,eAAO,MAAM,mBAAmB,KAAO,CAAC;AAGxC,eAAO,MAAM,wBAAwB,KAAO,CAAC;AAC7C,eAAO,MAAM,6BAA6B,KAAO,CAAC;AAClD,eAAO,MAAM,8BAA8B,KAAO,CAAC;AACnD,eAAO,MAAM,8BAA8B,KAAO,CAAC;AAGnD,eAAO,MAAM,uBAAuB,MAAO,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAO,CAAC;AACjD,eAAO,MAAM,6BAA6B,MAAO,CAAC;AAClD,eAAO,MAAM,6BAA6B,MAAO,CAAC;AAGlD,eAAO,MAAM,uBAAuB,MAAO,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAO,CAAC;AAGjD,eAAO,MAAM,sBAAsB,MAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAO,CAAC;AAGhD,eAAO,MAAM,gBAAgB,MAAO,CAAC;AACrC,eAAO,MAAM,iBAAiB,QAAS,CAAC;AACxC,eAAO,MAAM,iBAAiB,aAAa,CAAC"}
@@ -3,7 +3,6 @@ export const DEFAULT_PAIRING_CONFIG = {
3
3
  timeout: 30000,
4
4
  discoveryTimeout: 5000,
5
5
  maxRetries: 3,
6
- pairingDirectory: '.pairing',
7
6
  };
8
7
  // TLV8 component type identifiers used in pairing data exchange
9
8
  export const PairingDataComponentType = {
@@ -0,0 +1,10 @@
1
+ import { type AppleTVDevice } from '../../bonjour/bonjour-discovery.js';
2
+ import type { PairingConfig } from '../types.js';
3
+ /** Discovers Apple TV devices on the local network using Bonjour */
4
+ export declare class DeviceDiscoveryService {
5
+ private readonly config;
6
+ private readonly log;
7
+ constructor(config: PairingConfig);
8
+ discoverDevices(): Promise<AppleTVDevice[]>;
9
+ }
10
+ //# sourceMappingURL=device-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-discovery.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/discovery/device-discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,oEAAoE;AACpE,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA8C;gBAErC,MAAM,EAAE,aAAa;IAE5C,eAAe,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAkBlD"}
@@ -0,0 +1,22 @@
1
+ import { logger } from '@appium/support';
2
+ import { BonjourDiscovery, } from '../../bonjour/bonjour-discovery.js';
3
+ import { PairingError } from '../errors.js';
4
+ /** Discovers Apple TV devices on the local network using Bonjour */
5
+ export class DeviceDiscoveryService {
6
+ config;
7
+ log = logger.getLogger('DeviceDiscoveryService');
8
+ constructor(config) {
9
+ this.config = config;
10
+ }
11
+ async discoverDevices() {
12
+ try {
13
+ const discovery = new BonjourDiscovery();
14
+ this.log.info(`Discovering Apple TV devices (waiting ${this.config.discoveryTimeout / 1000} seconds)...`);
15
+ return await discovery.discoverAppleTVDevicesWithIP(this.config.discoveryTimeout);
16
+ }
17
+ catch (error) {
18
+ this.log.error('Device discovery failed:', error);
19
+ throw new PairingError('Device discovery failed', 'DISCOVERY_ERROR', error);
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ export { DeviceDiscoveryService } from './device-discovery.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export { DeviceDiscoveryService } from './device-discovery.js';
@@ -1,7 +1,7 @@
1
- import { logger } from '@appium/support';
2
1
  import { createCipheriv, createDecipheriv } from 'node:crypto';
2
+ import { getLogger } from '../../logger.js';
3
3
  import { CryptographyError } from '../errors.js';
4
- const log = logger.getLogger('ChaCha20Poly1305');
4
+ const log = getLogger('ChaCha20Poly1305');
5
5
  /**
6
6
  * Encrypts data using ChaCha20-Poly1305 AEAD cipher
7
7
  * @param params - Encryption parameters including plaintext, key, nonce, and optional AAD
@@ -1,7 +1,7 @@
1
- import { logger } from '@appium/support';
2
1
  import { generateKeyPairSync, sign, } from 'node:crypto';
2
+ import { getLogger } from '../../logger.js';
3
3
  import { CryptographyError } from '../errors.js';
4
- const log = logger.getLogger('Ed25519');
4
+ const log = getLogger('Ed25519');
5
5
  const ED25519_PUBLIC_KEY_LENGTH = 32;
6
6
  const ED25519_PRIVATE_KEY_LENGTH = 32;
7
7
  const ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');
@@ -1,8 +1,8 @@
1
- import { logger } from '@appium/support';
2
1
  import { createHmac } from 'node:crypto';
2
+ import { getLogger } from '../../logger.js';
3
3
  import { HKDF_HASH_ALGORITHM, HKDF_HASH_LENGTH } from '../constants.js';
4
4
  import { CryptographyError } from '../errors.js';
5
- const log = logger.getLogger('HKDF');
5
+ const log = getLogger('HKDF');
6
6
  const MAX_OUTPUT_LENGTH = 255 * HKDF_HASH_LENGTH;
7
7
  /**
8
8
  * HMAC-based Key Derivation Function (HKDF) as defined in RFC 5869
@@ -6,4 +6,9 @@ export * from './deviceInfo/index.js';
6
6
  export * from './encryption/index.js';
7
7
  export * from './tlv/index.js';
8
8
  export * from './srp/index.js';
9
+ export * from './network/index.js';
10
+ export * from './pairing-protocol/index.js';
11
+ export * from './storage/index.js';
12
+ export * from './discovery/index.js';
13
+ export * from './pairing/index.js';
9
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/apple-tv/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,QAAQ,EACR,6BAA6B,EAC7B,WAAW,EACX,WAAW,EACX,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/apple-tv/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,QAAQ,EACR,6BAA6B,EAC7B,WAAW,EACX,WAAW,EACX,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC"}
@@ -5,3 +5,8 @@ export * from './deviceInfo/index.js';
5
5
  export * from './encryption/index.js';
6
6
  export * from './tlv/index.js';
7
7
  export * from './srp/index.js';
8
+ export * from './network/index.js';
9
+ export * from './pairing-protocol/index.js';
10
+ export * from './storage/index.js';
11
+ export * from './discovery/index.js';
12
+ export * from './pairing/index.js';
@@ -0,0 +1,10 @@
1
+ /** Constants for network protocol */
2
+ export declare const NETWORK_CONSTANTS: {
3
+ readonly MAGIC: "RPPairing";
4
+ readonly MAGIC_LENGTH: 9;
5
+ readonly HEADER_LENGTH: 11;
6
+ readonly LENGTH_FIELD_SIZE: 2;
7
+ readonly MAX_TLV_FRAGMENT_SIZE: 255;
8
+ readonly PIN_INPUT_TIMEOUT_MS: 30000;
9
+ };
10
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/network/constants.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,eAAO,MAAM,iBAAiB;;;;;;;CAOpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** Constants for network protocol */
2
+ export const NETWORK_CONSTANTS = {
3
+ MAGIC: 'RPPairing',
4
+ MAGIC_LENGTH: 9,
5
+ HEADER_LENGTH: 11,
6
+ LENGTH_FIELD_SIZE: 2,
7
+ MAX_TLV_FRAGMENT_SIZE: 255,
8
+ PIN_INPUT_TIMEOUT_MS: 30000,
9
+ };
@@ -0,0 +1,4 @@
1
+ export { NetworkClient } from './network-client.js';
2
+ export { NETWORK_CONSTANTS } from './constants.js';
3
+ export type { NetworkClientInterface } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/network/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { NetworkClient } from './network-client.js';
2
+ export { NETWORK_CONSTANTS } from './constants.js';
@@ -0,0 +1,16 @@
1
+ import type { PairingConfig } from '../types.js';
2
+ import type { NetworkClientInterface } from './types.js';
3
+ /** Handles TCP socket communication with Apple TV devices */
4
+ export declare class NetworkClient implements NetworkClientInterface {
5
+ private readonly config;
6
+ private socket;
7
+ private connectionTimeoutId;
8
+ constructor(config: PairingConfig);
9
+ connect(ip: string, port: number): Promise<void>;
10
+ sendPacket(data: any): Promise<void>;
11
+ receiveResponse(): Promise<any>;
12
+ disconnect(): void;
13
+ private createRPPairingPacket;
14
+ private cleanup;
15
+ }
16
+ //# sourceMappingURL=network-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-client.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/network/network-client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAIzD,6DAA6D;AAC7D,qBAAa,aAAc,YAAW,sBAAsB;IAI9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,mBAAmB,CAA+B;gBAE7B,MAAM,EAAE,aAAa;IAE5C,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDhD,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBpC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC;IAmGrC,UAAU,IAAI,IAAI;IAIlB,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,OAAO;CAWhB"}
@@ -0,0 +1,169 @@
1
+ import { logger } from '@appium/support';
2
+ import * as net from 'node:net';
3
+ import { NetworkError } from '../errors.js';
4
+ import { NETWORK_CONSTANTS } from './constants.js';
5
+ const log = logger.getLogger('NetworkClient');
6
+ /** Handles TCP socket communication with Apple TV devices */
7
+ export class NetworkClient {
8
+ config;
9
+ socket = null;
10
+ connectionTimeoutId = null;
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ async connect(ip, port) {
15
+ log.debug(`Connecting to ${ip}:${port}`);
16
+ return new Promise((resolve, reject) => {
17
+ const cancelTimeout = () => {
18
+ if (this.connectionTimeoutId) {
19
+ clearTimeout(this.connectionTimeoutId);
20
+ this.connectionTimeoutId = null;
21
+ }
22
+ };
23
+ this.socket = new net.Socket();
24
+ this.socket.setTimeout(this.config.timeout);
25
+ this.socket.once('connect', () => {
26
+ log.debug('Connected successfully');
27
+ cancelTimeout();
28
+ resolve();
29
+ });
30
+ this.socket.once('error', (error) => {
31
+ log.error('Connection error:', error);
32
+ cancelTimeout();
33
+ reject(new NetworkError(`Connection failed: ${error.message}`));
34
+ });
35
+ this.socket.once('timeout', () => {
36
+ log.error('Socket timeout');
37
+ cancelTimeout();
38
+ reject(new NetworkError('Socket timeout'));
39
+ });
40
+ this.socket.once('close', () => {
41
+ cancelTimeout();
42
+ });
43
+ this.connectionTimeoutId = setTimeout(() => {
44
+ log.error('Connection attempt timeout');
45
+ this.cleanup();
46
+ reject(new NetworkError(`Connection timeout after ${this.config.timeout}ms`));
47
+ }, this.config.timeout);
48
+ this.socket.connect(port, ip);
49
+ });
50
+ }
51
+ async sendPacket(data) {
52
+ if (!this.socket) {
53
+ throw new NetworkError('Socket not connected');
54
+ }
55
+ const packet = this.createRPPairingPacket(data);
56
+ log.debug('Sending packet:', { size: packet.length });
57
+ return new Promise((resolve, reject) => {
58
+ if (!this.socket) {
59
+ reject(new NetworkError('Socket disconnected during send'));
60
+ return;
61
+ }
62
+ this.socket.write(packet, (error) => {
63
+ if (error) {
64
+ log.error('Send packet error:', error);
65
+ reject(new NetworkError('Failed to send packet'));
66
+ }
67
+ else {
68
+ resolve();
69
+ }
70
+ });
71
+ });
72
+ }
73
+ async receiveResponse() {
74
+ if (!this.socket) {
75
+ throw new NetworkError('Socket not connected');
76
+ }
77
+ return new Promise((resolve, reject) => {
78
+ let buffer = Buffer.alloc(0);
79
+ let expectedLength = null;
80
+ let headerRead = false;
81
+ let timeoutId = null;
82
+ const cleanup = () => {
83
+ if (timeoutId) {
84
+ clearTimeout(timeoutId);
85
+ timeoutId = null;
86
+ }
87
+ if (this.socket) {
88
+ this.socket.removeListener('data', onData);
89
+ this.socket.removeListener('error', onError);
90
+ }
91
+ };
92
+ const onData = (chunk) => {
93
+ try {
94
+ buffer = Buffer.concat([buffer, chunk]);
95
+ if (!headerRead && buffer.length >= NETWORK_CONSTANTS.HEADER_LENGTH) {
96
+ const magic = buffer
97
+ .slice(0, NETWORK_CONSTANTS.MAGIC_LENGTH)
98
+ .toString('ascii');
99
+ if (magic !== NETWORK_CONSTANTS.MAGIC) {
100
+ throw new NetworkError(`Invalid protocol magic: expected '${NETWORK_CONSTANTS.MAGIC}', got '${magic}'`);
101
+ }
102
+ expectedLength = buffer.readUInt16BE(NETWORK_CONSTANTS.MAGIC_LENGTH);
103
+ headerRead = true;
104
+ log.debug(`Response header parsed: expecting ${expectedLength} bytes`);
105
+ }
106
+ if (headerRead &&
107
+ expectedLength !== null &&
108
+ buffer.length >= NETWORK_CONSTANTS.HEADER_LENGTH + expectedLength) {
109
+ const bodyBytes = buffer.slice(NETWORK_CONSTANTS.HEADER_LENGTH, NETWORK_CONSTANTS.HEADER_LENGTH + expectedLength);
110
+ const response = JSON.parse(bodyBytes.toString('utf8'));
111
+ log.debug('Response received and parsed successfully');
112
+ cleanup();
113
+ resolve(response);
114
+ }
115
+ }
116
+ catch (error) {
117
+ log.error('Parse response error:', error);
118
+ cleanup();
119
+ reject(new NetworkError(`Failed to parse response: ${error.message}`));
120
+ }
121
+ };
122
+ const onError = (error) => {
123
+ log.error('Socket error during receive:', error);
124
+ cleanup();
125
+ reject(new NetworkError(`Socket error: ${error.message}`));
126
+ };
127
+ const onClose = () => {
128
+ if (timeoutId) {
129
+ clearTimeout(timeoutId);
130
+ }
131
+ };
132
+ if (this.socket) {
133
+ this.socket.once('data', onData);
134
+ this.socket.once('error', onError);
135
+ this.socket.once('close', onClose);
136
+ timeoutId = setTimeout(() => {
137
+ log.error(`Response timeout after ${this.config.timeout}ms`);
138
+ cleanup();
139
+ reject(new NetworkError(`Response timeout after ${this.config.timeout}ms`));
140
+ }, this.config.timeout);
141
+ }
142
+ else {
143
+ reject(new NetworkError('Socket not available'));
144
+ }
145
+ });
146
+ }
147
+ disconnect() {
148
+ this.cleanup();
149
+ }
150
+ createRPPairingPacket(jsonData) {
151
+ const jsonString = JSON.stringify(jsonData);
152
+ const bodyBytes = Buffer.from(jsonString, 'utf8');
153
+ const magic = Buffer.from(NETWORK_CONSTANTS.MAGIC, 'ascii');
154
+ const length = Buffer.alloc(NETWORK_CONSTANTS.LENGTH_FIELD_SIZE);
155
+ length.writeUInt16BE(bodyBytes.length, 0);
156
+ return Buffer.concat([magic, length, bodyBytes]);
157
+ }
158
+ cleanup() {
159
+ if (this.connectionTimeoutId) {
160
+ clearTimeout(this.connectionTimeoutId);
161
+ this.connectionTimeoutId = null;
162
+ }
163
+ if (this.socket) {
164
+ this.socket.removeAllListeners();
165
+ this.socket.destroy();
166
+ this.socket = null;
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,8 @@
1
+ /** Interface for network communication with Apple TV devices */
2
+ export interface NetworkClientInterface {
3
+ connect(ip: string, port: number): Promise<void>;
4
+ sendPacket(data: any): Promise<void>;
5
+ receiveResponse(): Promise<any>;
6
+ disconnect(): void;
7
+ }
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/network/types.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,UAAU,IAAI,IAAI,CAAC;CACpB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export { UserInputService } from './user-input-service.js';
2
+ export { AppleTVPairingService } from './pairing-service.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/pairing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { UserInputService } from './user-input-service.js';
2
+ export { AppleTVPairingService } from './pairing-service.js';
@@ -0,0 +1,15 @@
1
+ import type { AppleTVDevice } from '../../bonjour/bonjour-discovery.js';
2
+ import type { UserInputInterface } from '../pairing-protocol/types.js';
3
+ import type { PairingConfig, PairingResult } from '../types.js';
4
+ /** Main service orchestrating Apple TV device discovery and pairing */
5
+ export declare class AppleTVPairingService {
6
+ private readonly networkClient;
7
+ private readonly discoveryService;
8
+ private readonly userInput;
9
+ private readonly pairingProtocol;
10
+ constructor(userInput: UserInputInterface, config?: PairingConfig);
11
+ discoverAndPair(deviceSelector?: string): Promise<PairingResult>;
12
+ pairWithDevice(device: AppleTVDevice): Promise<string>;
13
+ private selectDevice;
14
+ }
15
+ //# sourceMappingURL=pairing-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing-service.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/pairing/pairing-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAOxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIhE,uEAAuE;AACvE,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;gBAGhD,SAAS,EAAE,kBAAkB,EAC7B,MAAM,GAAE,aAAsC;IAW1C,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA6BhE,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;YAyB9C,YAAY;CAwF3B"}
@@ -0,0 +1,112 @@
1
+ import { getLogger } from '../../logger.js';
2
+ import { DEFAULT_PAIRING_CONFIG } from '../constants.js';
3
+ import { DeviceDiscoveryService } from '../discovery/index.js';
4
+ import { PairingError } from '../errors.js';
5
+ import { NetworkClient } from '../network/index.js';
6
+ import { PairingProtocol } from '../pairing-protocol/index.js';
7
+ const log = getLogger('AppleTVPairingService');
8
+ /** Main service orchestrating Apple TV device discovery and pairing */
9
+ export class AppleTVPairingService {
10
+ networkClient;
11
+ discoveryService;
12
+ userInput;
13
+ pairingProtocol;
14
+ constructor(userInput, config = DEFAULT_PAIRING_CONFIG) {
15
+ this.networkClient = new NetworkClient(config);
16
+ this.discoveryService = new DeviceDiscoveryService(config);
17
+ this.userInput = userInput;
18
+ this.pairingProtocol = new PairingProtocol(this.networkClient, this.userInput);
19
+ }
20
+ async discoverAndPair(deviceSelector) {
21
+ try {
22
+ const devices = await this.discoveryService.discoverDevices();
23
+ if (devices.length === 0) {
24
+ const errorMessage = 'No Apple TV pairing devices found. Please ensure your Apple TV is on the same network and in pairing mode.';
25
+ log.error(errorMessage);
26
+ throw new PairingError(errorMessage, 'NO_DEVICES');
27
+ }
28
+ const device = await this.selectDevice(devices, deviceSelector);
29
+ const pairingFile = await this.pairWithDevice(device);
30
+ return {
31
+ success: true,
32
+ deviceId: device.identifier,
33
+ pairingFile,
34
+ };
35
+ }
36
+ catch (error) {
37
+ log.error('Pairing failed:', error);
38
+ return {
39
+ success: false,
40
+ deviceId: 'unknown',
41
+ error: error instanceof Error ? error : new Error(String(error)),
42
+ };
43
+ }
44
+ }
45
+ async pairWithDevice(device) {
46
+ try {
47
+ // Use IP if available, otherwise fall back to hostname
48
+ const connectionTarget = device.ip ?? device.hostname;
49
+ if (!connectionTarget) {
50
+ throw new PairingError('Neither IP address nor hostname available for device', 'NO_CONNECTION_TARGET');
51
+ }
52
+ log.info(`Connecting to device ${device.name} at ${connectionTarget}:${device.port}`);
53
+ await this.networkClient.connect(connectionTarget, device.port);
54
+ return await this.pairingProtocol.executePairingFlow(device);
55
+ }
56
+ catch (error) {
57
+ log.error(`Pairing with device ${device.name} failed:`, error);
58
+ throw error;
59
+ }
60
+ finally {
61
+ this.networkClient.disconnect();
62
+ }
63
+ }
64
+ async selectDevice(devices, deviceSelector) {
65
+ // If no selector provided, always prompt user to choose (even for single device)
66
+ if (!deviceSelector) {
67
+ log.info(`Found ${devices.length} device(s):`);
68
+ devices.forEach((device, index) => {
69
+ log.info(` [${index}] ${device.name} (${device.identifier}) - ${device.model} v${device.version}`);
70
+ });
71
+ const prompt = devices.length === 1
72
+ ? 'Press Enter to select device [0], or enter index: '
73
+ : `Select device by index (0-${devices.length - 1}): `;
74
+ const indexStr = await this.userInput.promptForInput(prompt);
75
+ const trimmed = indexStr.trim();
76
+ // If user just presses Enter and there's only one device, select it
77
+ if (trimmed === '' && devices.length === 1) {
78
+ log.info(`Selected device: ${devices[0].name} (${devices[0].identifier})`);
79
+ return devices[0];
80
+ }
81
+ const index = parseInt(trimmed, 10);
82
+ if (isNaN(index) || index < 0 || index >= devices.length) {
83
+ throw new PairingError(`Invalid device index: ${trimmed}. Must be between 0 and ${devices.length - 1}`, 'INVALID_DEVICE_SELECTION');
84
+ }
85
+ log.info(`Selected device: ${devices[index].name} (${devices[index].identifier})`);
86
+ return devices[index];
87
+ }
88
+ // Try to match by index first
89
+ const indexMatch = parseInt(deviceSelector, 10);
90
+ if (!isNaN(indexMatch) && indexMatch >= 0 && indexMatch < devices.length) {
91
+ log.info(`Selected device by index ${indexMatch}: ${devices[indexMatch].name}`);
92
+ return devices[indexMatch];
93
+ }
94
+ // Try to match by name (case-insensitive)
95
+ const nameMatch = devices.find((device) => device.name.toLowerCase() === deviceSelector.toLowerCase());
96
+ if (nameMatch) {
97
+ log.info(`Selected device by name: ${nameMatch.name} (${nameMatch.identifier})`);
98
+ return nameMatch;
99
+ }
100
+ // Try to match by identifier (case-insensitive)
101
+ const identifierMatch = devices.find((device) => device.identifier.toLowerCase() === deviceSelector.toLowerCase());
102
+ if (identifierMatch) {
103
+ log.info(`Selected device by identifier: ${identifierMatch.name} (${identifierMatch.identifier})`);
104
+ return identifierMatch;
105
+ }
106
+ // No match found
107
+ const availableDevices = devices
108
+ .map((device, index) => ` [${index}] ${device.name} (${device.identifier})`)
109
+ .join('\n');
110
+ throw new PairingError(`Device '${deviceSelector}' not found. Available devices:\n${availableDevices}`, 'DEVICE_NOT_FOUND');
111
+ }
112
+ }