appium-ios-remotexpc 0.0.3 → 0.0.4

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 (192) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/src/base-plist-service.d.ts +51 -0
  3. package/build/src/base-plist-service.d.ts.map +1 -0
  4. package/build/src/base-plist-service.js +61 -0
  5. package/build/src/base-socket-service.d.ts +15 -0
  6. package/build/src/base-socket-service.d.ts.map +1 -0
  7. package/build/src/base-socket-service.js +46 -0
  8. package/build/src/index.d.ts +9 -0
  9. package/build/src/index.d.ts.map +1 -0
  10. package/build/src/index.js +7 -0
  11. package/build/src/lib/apple-tv/constants.d.ts +49 -0
  12. package/build/src/lib/apple-tv/constants.d.ts.map +1 -0
  13. package/build/src/lib/apple-tv/constants.js +71 -0
  14. package/build/src/lib/apple-tv/errors.d.ts +17 -0
  15. package/build/src/lib/apple-tv/errors.d.ts.map +1 -0
  16. package/build/src/lib/apple-tv/errors.js +30 -0
  17. package/build/src/lib/apple-tv/tlv/decoder.d.ts +19 -0
  18. package/build/src/lib/apple-tv/tlv/decoder.d.ts.map +1 -0
  19. package/build/src/lib/apple-tv/tlv/decoder.js +49 -0
  20. package/build/src/lib/apple-tv/tlv/encoder.d.ts +10 -0
  21. package/build/src/lib/apple-tv/tlv/encoder.d.ts.map +1 -0
  22. package/build/src/lib/apple-tv/tlv/encoder.js +20 -0
  23. package/build/src/lib/apple-tv/tlv/index.d.ts +4 -0
  24. package/build/src/lib/apple-tv/tlv/index.d.ts.map +1 -0
  25. package/build/src/lib/apple-tv/tlv/index.js +3 -0
  26. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts +14 -0
  27. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts.map +1 -0
  28. package/build/src/lib/apple-tv/tlv/pairing-tlv.js +27 -0
  29. package/build/src/lib/apple-tv/types.d.ts +36 -0
  30. package/build/src/lib/apple-tv/types.d.ts.map +1 -0
  31. package/build/src/lib/apple-tv/types.js +1 -0
  32. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts +40 -0
  33. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts.map +1 -0
  34. package/build/src/lib/apple-tv/utils/buffer-utils.js +76 -0
  35. package/build/src/lib/apple-tv/utils/index.d.ts +3 -0
  36. package/build/src/lib/apple-tv/utils/index.d.ts.map +1 -0
  37. package/build/src/lib/apple-tv/utils/index.js +2 -0
  38. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts +9 -0
  39. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts.map +1 -0
  40. package/build/src/lib/apple-tv/utils/uuid-generator.js +36 -0
  41. package/build/src/lib/lockdown/index.d.ts +87 -0
  42. package/build/src/lib/lockdown/index.d.ts.map +1 -0
  43. package/build/src/lib/lockdown/index.js +324 -0
  44. package/build/src/lib/pair-record/index.d.ts +3 -0
  45. package/build/src/lib/pair-record/index.d.ts.map +1 -0
  46. package/build/src/lib/pair-record/index.js +2 -0
  47. package/build/src/lib/pair-record/pair-record.d.ts +48 -0
  48. package/build/src/lib/pair-record/pair-record.d.ts.map +1 -0
  49. package/build/src/lib/pair-record/pair-record.js +85 -0
  50. package/build/src/lib/plist/binary-plist-creator.d.ts +14 -0
  51. package/build/src/lib/plist/binary-plist-creator.d.ts.map +1 -0
  52. package/build/src/lib/plist/binary-plist-creator.js +475 -0
  53. package/build/src/lib/plist/binary-plist-parser.d.ts +14 -0
  54. package/build/src/lib/plist/binary-plist-parser.d.ts.map +1 -0
  55. package/build/src/lib/plist/binary-plist-parser.js +449 -0
  56. package/build/src/lib/plist/constants.d.ts +36 -0
  57. package/build/src/lib/plist/constants.d.ts.map +1 -0
  58. package/build/src/lib/plist/constants.js +43 -0
  59. package/build/src/lib/plist/index.d.ts +14 -0
  60. package/build/src/lib/plist/index.d.ts.map +1 -0
  61. package/build/src/lib/plist/index.js +16 -0
  62. package/build/src/lib/plist/length-based-splitter.d.ts +43 -0
  63. package/build/src/lib/plist/length-based-splitter.d.ts.map +1 -0
  64. package/build/src/lib/plist/length-based-splitter.js +228 -0
  65. package/build/src/lib/plist/plist-creator.d.ts +8 -0
  66. package/build/src/lib/plist/plist-creator.d.ts.map +1 -0
  67. package/build/src/lib/plist/plist-creator.js +33 -0
  68. package/build/src/lib/plist/plist-decoder.d.ts +25 -0
  69. package/build/src/lib/plist/plist-decoder.d.ts.map +1 -0
  70. package/build/src/lib/plist/plist-decoder.js +103 -0
  71. package/build/src/lib/plist/plist-encoder.d.ts +10 -0
  72. package/build/src/lib/plist/plist-encoder.d.ts.map +1 -0
  73. package/build/src/lib/plist/plist-encoder.js +27 -0
  74. package/build/src/lib/plist/plist-parser.d.ts +9 -0
  75. package/build/src/lib/plist/plist-parser.d.ts.map +1 -0
  76. package/build/src/lib/plist/plist-parser.js +109 -0
  77. package/build/src/lib/plist/plist-service.d.ts +86 -0
  78. package/build/src/lib/plist/plist-service.d.ts.map +1 -0
  79. package/build/src/lib/plist/plist-service.js +180 -0
  80. package/build/src/lib/plist/unified-plist-creator.d.ts +9 -0
  81. package/build/src/lib/plist/unified-plist-creator.d.ts.map +1 -0
  82. package/build/src/lib/plist/unified-plist-creator.js +14 -0
  83. package/build/src/lib/plist/unified-plist-parser.d.ts +8 -0
  84. package/build/src/lib/plist/unified-plist-parser.d.ts.map +1 -0
  85. package/build/src/lib/plist/unified-plist-parser.js +23 -0
  86. package/build/src/lib/plist/utils.d.ts +97 -0
  87. package/build/src/lib/plist/utils.d.ts.map +1 -0
  88. package/build/src/lib/plist/utils.js +287 -0
  89. package/build/src/lib/remote-xpc/constants.d.ts +20 -0
  90. package/build/src/lib/remote-xpc/constants.d.ts.map +1 -0
  91. package/build/src/lib/remote-xpc/constants.js +21 -0
  92. package/build/src/lib/remote-xpc/handshake-frames.d.ts +74 -0
  93. package/build/src/lib/remote-xpc/handshake-frames.d.ts.map +1 -0
  94. package/build/src/lib/remote-xpc/handshake-frames.js +285 -0
  95. package/build/src/lib/remote-xpc/handshake.d.ts +14 -0
  96. package/build/src/lib/remote-xpc/handshake.d.ts.map +1 -0
  97. package/build/src/lib/remote-xpc/handshake.js +95 -0
  98. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts +55 -0
  99. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts.map +1 -0
  100. package/build/src/lib/remote-xpc/remote-xpc-connection.js +365 -0
  101. package/build/src/lib/remote-xpc/xpc-protocol.d.ts +22 -0
  102. package/build/src/lib/remote-xpc/xpc-protocol.d.ts.map +1 -0
  103. package/build/src/lib/remote-xpc/xpc-protocol.js +368 -0
  104. package/build/src/lib/tunnel/index.d.ts +69 -0
  105. package/build/src/lib/tunnel/index.d.ts.map +1 -0
  106. package/build/src/lib/tunnel/index.js +205 -0
  107. package/build/src/lib/tunnel/packet-stream-client.d.ts +46 -0
  108. package/build/src/lib/tunnel/packet-stream-client.d.ts.map +1 -0
  109. package/build/src/lib/tunnel/packet-stream-client.js +152 -0
  110. package/build/src/lib/tunnel/packet-stream-server.d.ts +37 -0
  111. package/build/src/lib/tunnel/packet-stream-server.d.ts.map +1 -0
  112. package/build/src/lib/tunnel/packet-stream-server.js +109 -0
  113. package/build/src/lib/tunnel/tunnel-api-client.d.ts +85 -0
  114. package/build/src/lib/tunnel/tunnel-api-client.d.ts.map +1 -0
  115. package/build/src/lib/tunnel/tunnel-api-client.js +207 -0
  116. package/build/src/lib/tunnel/tunnel-registry-server.d.ts +68 -0
  117. package/build/src/lib/tunnel/tunnel-registry-server.d.ts.map +1 -0
  118. package/build/src/lib/tunnel/tunnel-registry-server.js +351 -0
  119. package/build/src/lib/types.d.ts +238 -0
  120. package/build/src/lib/types.d.ts.map +1 -0
  121. package/build/src/lib/types.js +4 -0
  122. package/build/src/lib/usbmux/index.d.ts +177 -0
  123. package/build/src/lib/usbmux/index.d.ts.map +1 -0
  124. package/build/src/lib/usbmux/index.js +490 -0
  125. package/build/src/lib/usbmux/usbmux-decoder.d.ts +19 -0
  126. package/build/src/lib/usbmux/usbmux-decoder.d.ts.map +1 -0
  127. package/build/src/lib/usbmux/usbmux-decoder.js +38 -0
  128. package/build/src/lib/usbmux/usbmux-encoder.d.ts +12 -0
  129. package/build/src/lib/usbmux/usbmux-encoder.d.ts.map +1 -0
  130. package/build/src/lib/usbmux/usbmux-encoder.js +32 -0
  131. package/build/src/service-connection.d.ts +34 -0
  132. package/build/src/service-connection.d.ts.map +1 -0
  133. package/build/src/service-connection.js +51 -0
  134. package/build/src/services/index.d.ts +6 -0
  135. package/build/src/services/index.d.ts.map +1 -0
  136. package/build/src/services/index.js +5 -0
  137. package/build/src/services/ios/base-service.d.ts +35 -0
  138. package/build/src/services/ios/base-service.d.ts.map +1 -0
  139. package/build/src/services/ios/base-service.js +55 -0
  140. package/build/src/services/ios/diagnostic-service/index.d.ts +46 -0
  141. package/build/src/services/ios/diagnostic-service/index.d.ts.map +1 -0
  142. package/build/src/services/ios/diagnostic-service/index.js +169 -0
  143. package/build/src/services/ios/diagnostic-service/keys.d.ts +5 -0
  144. package/build/src/services/ios/diagnostic-service/keys.d.ts.map +1 -0
  145. package/build/src/services/ios/diagnostic-service/keys.js +770 -0
  146. package/build/src/services/ios/syslog-service/index.d.ts +91 -0
  147. package/build/src/services/ios/syslog-service/index.d.ts.map +1 -0
  148. package/build/src/services/ios/syslog-service/index.js +323 -0
  149. package/build/src/services/ios/tunnel-service/index.d.ts +17 -0
  150. package/build/src/services/ios/tunnel-service/index.d.ts.map +1 -0
  151. package/build/src/services/ios/tunnel-service/index.js +57 -0
  152. package/build/src/services.d.ts +14 -0
  153. package/build/src/services.d.ts.map +1 -0
  154. package/build/src/services.js +48 -0
  155. package/package.json +12 -3
  156. package/.github/dependabot.yml +0 -38
  157. package/.github/workflows/format-check.yml +0 -43
  158. package/.github/workflows/lint-and-build.yml +0 -40
  159. package/.github/workflows/pr-title.yml +0 -16
  160. package/.github/workflows/publish.js.yml +0 -43
  161. package/.github/workflows/test-validation.yml +0 -40
  162. package/.mocharc.json +0 -8
  163. package/.prettierignore +0 -3
  164. package/.prettierrc +0 -17
  165. package/.releaserc +0 -48
  166. package/assets/images/ios-arch.png +0 -0
  167. package/eslint.config.js +0 -45
  168. package/npm-shrinkwrap.json +0 -2711
  169. package/test/integration/diagnostics-test.ts +0 -44
  170. package/test/integration/read-pair-record-test.ts +0 -39
  171. package/test/integration/tunnel-test.ts +0 -104
  172. package/test/unit/apple-tv/tlv/decoder.spec.ts +0 -144
  173. package/test/unit/apple-tv/tlv/encoder.spec.ts +0 -91
  174. package/test/unit/apple-tv/tlv/pairing-tlv.spec.ts +0 -101
  175. package/test/unit/apple-tv/tlv/tlv-integration.spec.ts +0 -146
  176. package/test/unit/apple-tv/utils/buffer-utils.spec.ts +0 -74
  177. package/test/unit/apple-tv/utils/uuid-generator.spec.ts +0 -39
  178. package/test/unit/fixtures/index.ts +0 -88
  179. package/test/unit/fixtures/usbmuxconnectmessage.bin +0 -0
  180. package/test/unit/fixtures/usbmuxlistdevicemessage.bin +0 -0
  181. package/test/unit/plist/error-handling.spec.ts +0 -101
  182. package/test/unit/plist/fixtures/sample.binary.plist +0 -0
  183. package/test/unit/plist/fixtures/sample.xml.plist +0 -38
  184. package/test/unit/plist/plist-parser.spec.ts +0 -283
  185. package/test/unit/plist/plist.spec.ts +0 -205
  186. package/test/unit/plist/tag-position-handling.spec.ts +0 -90
  187. package/test/unit/plist/unified-plist-parser.spec.ts +0 -227
  188. package/test/unit/plist/utils.spec.ts +0 -249
  189. package/test/unit/plist/xml-cleaning.spec.ts +0 -60
  190. package/test/unit/tunnel/tunnel-registry-server.spec.ts +0 -194
  191. package/test/unit/usbmux/usbmux-specs.ts +0 -71
  192. package/tsconfig.json +0 -36
@@ -0,0 +1,85 @@
1
+ import { logger } from '@appium/support';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ const log = logger.getLogger('PairRecord');
5
+ /**
6
+ * Converts a buffer containing PEM data to a string
7
+ * @param buffer - Buffer containing PEM data
8
+ * @returns String representation of the PEM data
9
+ */
10
+ function bufferToPEMString(buffer) {
11
+ return buffer.toString('utf8');
12
+ }
13
+ /**
14
+ * Processes raw response from plist.parsePlist and formats it into a proper pair-record
15
+ * @param response - Response from plist.parsePlist(data.payload.PairRecordData)
16
+ * @returns Formatted pair-record object with properly structured data
17
+ */
18
+ export function processPlistResponse(response) {
19
+ return {
20
+ HostID: response.HostID || null,
21
+ SystemBUID: response.SystemBUID || null,
22
+ HostCertificate: response.HostCertificate
23
+ ? bufferToPEMString(response.HostCertificate)
24
+ : null,
25
+ HostPrivateKey: response.HostPrivateKey
26
+ ? bufferToPEMString(response.HostPrivateKey)
27
+ : null,
28
+ DeviceCertificate: response.DeviceCertificate
29
+ ? bufferToPEMString(response.DeviceCertificate)
30
+ : null,
31
+ RootCertificate: response.RootCertificate
32
+ ? bufferToPEMString(response.RootCertificate)
33
+ : null,
34
+ RootPrivateKey: response.RootPrivateKey
35
+ ? bufferToPEMString(response.RootPrivateKey)
36
+ : null,
37
+ WiFiMACAddress: response.WiFiMACAddress || null,
38
+ // For EscrowBag, we need it as a base64 string
39
+ EscrowBag: response.EscrowBag
40
+ ? response.EscrowBag.toString('base64')
41
+ : null,
42
+ };
43
+ }
44
+ /* --- File storage functions remain unchanged --- */
45
+ const RECORDS_DIR = path.join(process.cwd(), '../../.records');
46
+ async function ensureRecordsDirectoryExists() {
47
+ await fs.promises.mkdir(RECORDS_DIR, { recursive: true, mode: 0o777 });
48
+ }
49
+ /**
50
+ * Saves a pair record to the filesystem.
51
+ * @param udid - Device UDID.
52
+ * @param pairRecord - Pair record to save.
53
+ * @returns Promise that resolves when record is saved.
54
+ */
55
+ export async function savePairRecord(udid, pairRecord) {
56
+ await ensureRecordsDirectoryExists();
57
+ const recordPath = path.join(RECORDS_DIR, `${udid}-record.json`);
58
+ try {
59
+ await fs.promises.writeFile(recordPath, JSON.stringify(pairRecord, null, 2), { mode: 0o777 });
60
+ log.info(`Pair record saved: ${recordPath}`);
61
+ }
62
+ catch (error) {
63
+ log.error(`Failed to save pair record for ${udid}: ${error}`);
64
+ throw error;
65
+ }
66
+ }
67
+ /**
68
+ * Gets a saved pair record from the filesystem.
69
+ * @param udid - Device UDID.
70
+ * @returns Promise that resolves with the pair record or null if not found.
71
+ */
72
+ export async function getPairRecord(udid) {
73
+ const recordPath = path.join(RECORDS_DIR, `${udid}-record.json`);
74
+ try {
75
+ const data = await fs.promises.readFile(recordPath, 'utf8');
76
+ return JSON.parse(data);
77
+ }
78
+ catch (error) {
79
+ if (error.code === 'ENOENT') {
80
+ return null;
81
+ }
82
+ log.error(`Failed to read pair record for ${udid}: ${error}`);
83
+ throw error;
84
+ }
85
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Binary Property List (bplist) Creator
3
+ *
4
+ * This module provides functionality to create binary property lists (bplists)
5
+ * commonly used in Apple's iOS and macOS systems.
6
+ */
7
+ import type { PlistValue } from '../types.js';
8
+ /**
9
+ * Creates a binary plist from a JavaScript object
10
+ * @param obj - The JavaScript object to convert to a binary plist
11
+ * @returns Buffer containing the binary plist data
12
+ */
13
+ export declare function createBinaryPlist(obj: PlistValue): Buffer;
14
+ //# sourceMappingURL=binary-plist-creator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-plist-creator.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/binary-plist-creator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAmB,UAAU,EAAE,MAAM,aAAa,CAAC;AA4iB/D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAGzD"}
@@ -0,0 +1,475 @@
1
+ import { APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TRAILER_SIZE, BPLIST_TYPE, } from './constants.js';
2
+ /**
3
+ * Checks if a value is a plain object (not null, not an array, not a Date, not a Buffer)
4
+ * @param value - The value to check
5
+ * @returns True if the value is a plain object
6
+ */
7
+ function isPlainObject(value) {
8
+ return (typeof value === 'object' &&
9
+ value !== null &&
10
+ !Array.isArray(value) &&
11
+ !(value instanceof Date) &&
12
+ !(value instanceof Buffer) &&
13
+ Object.getPrototypeOf(value) === Object.prototype);
14
+ }
15
+ /**
16
+ * Class for creating binary property lists
17
+ */
18
+ class BinaryPlistCreator {
19
+ _objectTable = [];
20
+ _objectRefMap = new Map();
21
+ _objectRefSize = 0;
22
+ _offsetSize = 0;
23
+ _rootObject;
24
+ /**
25
+ * Creates a new BinaryPlistCreator
26
+ * @param rootObject - The root object to convert to a binary plist
27
+ */
28
+ constructor(rootObject) {
29
+ this._rootObject = rootObject;
30
+ }
31
+ /**
32
+ * Creates the binary plist
33
+ * @returns Buffer containing the binary plist data
34
+ */
35
+ create() {
36
+ // Collect all objects and assign IDs
37
+ this._collectObjects();
38
+ // Create object data
39
+ const objectOffsets = [];
40
+ const objectData = [];
41
+ for (const value of this._objectTable) {
42
+ objectOffsets.push(this._calculateObjectDataLength(objectData));
43
+ objectData.push(this._createObjectData(value));
44
+ }
45
+ // Calculate offset table size
46
+ const maxOffset = this._calculateObjectDataLength(objectData);
47
+ this._offsetSize = this._calculateMinByteSize(maxOffset);
48
+ // Create offset table
49
+ const offsetTable = this._createOffsetTable(objectOffsets);
50
+ // Calculate offset table offset
51
+ const offsetTableOffset = BPLIST_MAGIC_AND_VERSION.length +
52
+ this._calculateObjectDataLength(objectData);
53
+ // Create trailer
54
+ const trailer = this._createTrailer(this._objectTable.length, offsetTableOffset);
55
+ // Combine all parts
56
+ return Buffer.concat([
57
+ BPLIST_MAGIC_AND_VERSION,
58
+ ...objectData,
59
+ offsetTable,
60
+ trailer,
61
+ ]);
62
+ }
63
+ /**
64
+ * Collects all unique objects in the object hierarchy
65
+ */
66
+ _collectObjects() {
67
+ this._collectObjectsRecursive(this._rootObject);
68
+ // Calculate the object reference size based on the number of objects
69
+ const numObjects = this._objectTable.length;
70
+ this._objectRefSize = this._calculateMinByteSize(numObjects - 1);
71
+ }
72
+ /**
73
+ * Recursively collects objects from a value
74
+ * @param value - The value to collect objects from
75
+ */
76
+ _collectObjectsRecursive(value) {
77
+ // Skip if already in the table
78
+ if (this._objectRefMap.has(value)) {
79
+ return;
80
+ }
81
+ // Add to the table and map
82
+ const id = this._objectTable.length;
83
+ this._objectTable.push(value);
84
+ this._objectRefMap.set(value, id);
85
+ // Recursively collect objects for arrays and dictionaries
86
+ if (Array.isArray(value)) {
87
+ for (const item of value) {
88
+ this._collectObjectsRecursive(item);
89
+ }
90
+ }
91
+ else if (value !== null && isPlainObject(value)) {
92
+ // This is a dictionary
93
+ const dict = value;
94
+ for (const key of Object.keys(dict)) {
95
+ this._collectObjectsRecursive(key);
96
+ this._collectObjectsRecursive(dict[key]);
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Calculates the minimum number of bytes needed to represent a number
102
+ * @param value - The number to calculate for
103
+ * @returns The minimum number of bytes needed (1, 2, 4, or 8)
104
+ */
105
+ _calculateMinByteSize(value) {
106
+ if (value < 256) {
107
+ return 1;
108
+ }
109
+ else if (value < 65536) {
110
+ return 2;
111
+ }
112
+ else if (value < 4294967296) {
113
+ return 4;
114
+ }
115
+ else {
116
+ return 8;
117
+ }
118
+ }
119
+ /**
120
+ * Calculates the total length of object data buffers
121
+ * @param buffers - Array of buffers
122
+ * @returns Total length
123
+ */
124
+ _calculateObjectDataLength(buffers) {
125
+ return buffers.reduce((sum, buffer) => sum + buffer.length, 0);
126
+ }
127
+ /**
128
+ * Writes an offset value to a buffer
129
+ * @param buffer - Target buffer
130
+ * @param position - Position in the buffer
131
+ * @param value - Value to write
132
+ * @param size - Number of bytes to use
133
+ */
134
+ _writeOffsetToBuffer(buffer, position, value, size) {
135
+ if (size === 1) {
136
+ buffer.writeUInt8(Number(value), position);
137
+ }
138
+ else if (size === 2) {
139
+ buffer.writeUInt16BE(Number(value), position);
140
+ }
141
+ else if (size === 4) {
142
+ buffer.writeUInt32BE(Number(value), position);
143
+ }
144
+ else if (size === 8) {
145
+ // Use BigInt directly for the value to avoid potential precision issues
146
+ buffer.writeBigUInt64BE(typeof value === 'bigint' ? value : BigInt(value), position);
147
+ }
148
+ }
149
+ /**
150
+ * Writes a BigInt to a buffer
151
+ * @param buffer - Target buffer
152
+ * @param position - Position in the buffer
153
+ * @param value - BigInt value to write
154
+ */
155
+ _writeBigIntToBuffer(buffer, position, value) {
156
+ buffer.writeBigUInt64BE(value, position);
157
+ }
158
+ /**
159
+ * Creates binary data for a null value
160
+ * @returns Buffer containing the binary data
161
+ */
162
+ _createNullData() {
163
+ return Buffer.from([BPLIST_TYPE.NULL]);
164
+ }
165
+ /**
166
+ * Creates binary data for a boolean value
167
+ * @param value - The boolean value
168
+ * @returns Buffer containing the binary data
169
+ */
170
+ _createBooleanData(value) {
171
+ return Buffer.from([value ? BPLIST_TYPE.TRUE : BPLIST_TYPE.FALSE]);
172
+ }
173
+ /**
174
+ * Creates binary data for an integer value
175
+ * @param value - The integer value (number or bigint)
176
+ * @returns Buffer containing the binary data
177
+ */
178
+ _createIntegerData(value) {
179
+ let buffer;
180
+ // If value is a BigInt, handle it directly
181
+ if (typeof value === 'bigint') {
182
+ // For BigInt values, we always use 64-bit representation
183
+ buffer = Buffer.alloc(9);
184
+ buffer.writeUInt8(BPLIST_TYPE.INT | 3, 0);
185
+ buffer.writeBigInt64BE(value, 1);
186
+ }
187
+ // For number values, determine the smallest representation
188
+ else if (value >= 0 && value <= 255) {
189
+ buffer = Buffer.alloc(2);
190
+ buffer.writeUInt8(BPLIST_TYPE.INT | 0, 0);
191
+ buffer.writeUInt8(value, 1);
192
+ }
193
+ else if (value >= -128 && value <= 127) {
194
+ buffer = Buffer.alloc(2);
195
+ buffer.writeUInt8(BPLIST_TYPE.INT | 0, 0);
196
+ buffer.writeInt8(value, 1);
197
+ }
198
+ else if (value >= -32768 && value <= 32767) {
199
+ buffer = Buffer.alloc(3);
200
+ buffer.writeUInt8(BPLIST_TYPE.INT | 1, 0);
201
+ buffer.writeInt16BE(value, 1);
202
+ }
203
+ else if (value >= -2147483648 && value <= 2147483647) {
204
+ buffer = Buffer.alloc(5);
205
+ buffer.writeUInt8(BPLIST_TYPE.INT | 2, 0);
206
+ buffer.writeInt32BE(value, 1);
207
+ }
208
+ else {
209
+ // 64-bit integer - use BigInt directly to avoid precision issues
210
+ buffer = Buffer.alloc(9);
211
+ buffer.writeUInt8(BPLIST_TYPE.INT | 3, 0);
212
+ buffer.writeBigInt64BE(BigInt(value), 1);
213
+ }
214
+ return buffer;
215
+ }
216
+ /**
217
+ * Creates binary data for a floating point value
218
+ * @param value - The floating point value
219
+ * @returns Buffer containing the binary data
220
+ */
221
+ _createFloatData(value) {
222
+ const buffer = Buffer.alloc(9);
223
+ buffer.writeUInt8(BPLIST_TYPE.REAL | 3, 0); // Use double precision
224
+ buffer.writeDoubleBE(value, 1);
225
+ return buffer;
226
+ }
227
+ /**
228
+ * Creates binary data for a date value
229
+ * @param value - The date value
230
+ * @returns Buffer containing the binary data
231
+ */
232
+ _createDateData(value) {
233
+ const buffer = Buffer.alloc(9);
234
+ buffer.writeUInt8(BPLIST_TYPE.DATE, 0);
235
+ // Convert to seconds since Apple epoch (2001-01-01)
236
+ const timestamp = value.getTime() / 1000 - APPLE_EPOCH_OFFSET;
237
+ buffer.writeDoubleBE(timestamp, 1);
238
+ return buffer;
239
+ }
240
+ /**
241
+ * Creates a header for an integer value
242
+ * @param value - The integer value
243
+ * @returns Buffer containing the integer header
244
+ */
245
+ _createIntHeader(value) {
246
+ let buffer;
247
+ if (value < 256) {
248
+ buffer = Buffer.alloc(2);
249
+ buffer.writeUInt8(BPLIST_TYPE.INT | 0, 0);
250
+ buffer.writeUInt8(value, 1);
251
+ }
252
+ else if (value < 65536) {
253
+ buffer = Buffer.alloc(3);
254
+ buffer.writeUInt8(BPLIST_TYPE.INT | 1, 0);
255
+ buffer.writeUInt16BE(value, 1);
256
+ }
257
+ else {
258
+ buffer = Buffer.alloc(5);
259
+ buffer.writeUInt8(BPLIST_TYPE.INT | 2, 0);
260
+ buffer.writeUInt32BE(value, 1);
261
+ }
262
+ return buffer;
263
+ }
264
+ /**
265
+ * Creates binary data for a buffer (data) value
266
+ * @param value - The buffer value
267
+ * @returns Buffer containing the binary data
268
+ */
269
+ _createBufferData(value) {
270
+ const length = value.length;
271
+ let header;
272
+ if (length < 15) {
273
+ header = Buffer.from([BPLIST_TYPE.DATA | length]);
274
+ }
275
+ else {
276
+ // For longer data, we need to encode the length separately
277
+ const lengthBuffer = this._createIntHeader(length);
278
+ header = Buffer.concat([
279
+ Buffer.from([BPLIST_TYPE.DATA | 0x0f]), // 0x0F indicates length follows
280
+ lengthBuffer,
281
+ ]);
282
+ }
283
+ return Buffer.concat([header, value]);
284
+ }
285
+ /**
286
+ * Creates binary data for a string value
287
+ * @param value - The string value
288
+ * @returns Buffer containing the binary data
289
+ */
290
+ _createStringData(value) {
291
+ // Check if string can be ASCII
292
+ // eslint-disable-next-line no-control-regex
293
+ const isAscii = /^[\x00-\x7F]*$/.test(value);
294
+ const stringBuffer = isAscii
295
+ ? Buffer.from(value, 'ascii')
296
+ : Buffer.from(value, 'utf16le');
297
+ // Fixed the typo here - using stringBuffer.length instead of value.length for Unicode strings
298
+ const length = isAscii ? value.length : stringBuffer.length / 2;
299
+ let header;
300
+ if (length < 15) {
301
+ header = Buffer.from([
302
+ isAscii
303
+ ? BPLIST_TYPE.STRING_ASCII | length
304
+ : BPLIST_TYPE.STRING_UNICODE | length,
305
+ ]);
306
+ }
307
+ else {
308
+ // For longer strings, we need to encode the length separately
309
+ const lengthBuffer = this._createIntHeader(length);
310
+ header = Buffer.concat([
311
+ Buffer.from([
312
+ isAscii
313
+ ? BPLIST_TYPE.STRING_ASCII | 0x0f
314
+ : BPLIST_TYPE.STRING_UNICODE | 0x0f,
315
+ ]),
316
+ lengthBuffer,
317
+ ]);
318
+ }
319
+ return Buffer.concat([header, stringBuffer]);
320
+ }
321
+ /**
322
+ * Creates binary data for an array value
323
+ * @param value - The array value
324
+ * @returns Buffer containing the binary data
325
+ */
326
+ _createArrayData(value) {
327
+ const length = value.length;
328
+ let header;
329
+ if (length < 15) {
330
+ header = Buffer.from([BPLIST_TYPE.ARRAY | length]);
331
+ }
332
+ else {
333
+ // For longer arrays, we need to encode the length separately
334
+ const lengthBuffer = this._createIntHeader(length);
335
+ header = Buffer.concat([
336
+ Buffer.from([BPLIST_TYPE.ARRAY | 0x0f]), // 0x0F indicates length follows
337
+ lengthBuffer,
338
+ ]);
339
+ }
340
+ // Create references to each item
341
+ const refBuffer = Buffer.alloc(length * this._objectRefSize);
342
+ for (let i = 0; i < length; i++) {
343
+ const itemRef = this._objectRefMap.get(value[i]) ?? 0;
344
+ this._writeOffsetToBuffer(refBuffer, i * this._objectRefSize, itemRef, this._objectRefSize);
345
+ }
346
+ return Buffer.concat([header, refBuffer]);
347
+ }
348
+ /**
349
+ * Creates binary data for a dictionary value
350
+ * @param value - The dictionary value
351
+ * @returns Buffer containing the binary data
352
+ */
353
+ _createDictionaryData(value) {
354
+ const keys = Object.keys(value);
355
+ const length = keys.length;
356
+ let header;
357
+ if (length < 15) {
358
+ header = Buffer.from([BPLIST_TYPE.DICT | length]);
359
+ }
360
+ else {
361
+ // For larger dictionaries, we need to encode the length separately
362
+ const lengthBuffer = this._createIntHeader(length);
363
+ header = Buffer.concat([
364
+ Buffer.from([BPLIST_TYPE.DICT | 0x0f]), // 0x0F indicates length follows
365
+ lengthBuffer,
366
+ ]);
367
+ }
368
+ // Create references to keys and values
369
+ const keyRefBuffer = Buffer.alloc(length * this._objectRefSize);
370
+ const valueRefBuffer = Buffer.alloc(length * this._objectRefSize);
371
+ for (let i = 0; i < length; i++) {
372
+ const key = keys[i];
373
+ const keyRef = this._objectRefMap.get(key) ?? 0;
374
+ const valueRef = this._objectRefMap.get(value[key]) ?? 0;
375
+ this._writeOffsetToBuffer(keyRefBuffer, i * this._objectRefSize, keyRef, this._objectRefSize);
376
+ this._writeOffsetToBuffer(valueRefBuffer, i * this._objectRefSize, valueRef, this._objectRefSize);
377
+ }
378
+ return Buffer.concat([header, keyRefBuffer, valueRefBuffer]);
379
+ }
380
+ /**
381
+ * Creates binary data for an object
382
+ * @param value - The value to convert
383
+ * @returns Buffer containing the binary data
384
+ */
385
+ _createObjectData(value) {
386
+ // Handle null and booleans
387
+ if (value === null) {
388
+ return this._createNullData();
389
+ }
390
+ else if (typeof value === 'boolean') {
391
+ return this._createBooleanData(value);
392
+ }
393
+ // Handle BigInt
394
+ if (typeof value === 'bigint') {
395
+ return this._createIntegerData(value);
396
+ }
397
+ // Handle numbers
398
+ if (typeof value === 'number') {
399
+ // Check if it's an integer
400
+ if (Number.isInteger(value)) {
401
+ return this._createIntegerData(value);
402
+ }
403
+ else {
404
+ // Float
405
+ return this._createFloatData(value);
406
+ }
407
+ }
408
+ // Handle Date
409
+ if (value instanceof Date) {
410
+ return this._createDateData(value);
411
+ }
412
+ // Handle Buffer (DATA)
413
+ if (Buffer.isBuffer(value)) {
414
+ return this._createBufferData(value);
415
+ }
416
+ // Handle strings
417
+ if (typeof value === 'string') {
418
+ return this._createStringData(value);
419
+ }
420
+ // Handle arrays
421
+ if (Array.isArray(value)) {
422
+ return this._createArrayData(value);
423
+ }
424
+ // Handle objects (dictionaries) - using isPlainObject for better type checking
425
+ if (isPlainObject(value)) {
426
+ return this._createDictionaryData(value);
427
+ }
428
+ // Default fallback
429
+ return Buffer.from([BPLIST_TYPE.NULL]);
430
+ }
431
+ /**
432
+ * Creates the offset table
433
+ * @param objectOffsets - Array of object offsets
434
+ * @returns Buffer containing the offset table
435
+ */
436
+ _createOffsetTable(objectOffsets) {
437
+ const numObjects = this._objectTable.length;
438
+ const offsetTable = Buffer.alloc(numObjects * this._offsetSize);
439
+ for (let i = 0; i < numObjects; i++) {
440
+ this._writeOffsetToBuffer(offsetTable, i * this._offsetSize, objectOffsets[i], this._offsetSize);
441
+ }
442
+ return offsetTable;
443
+ }
444
+ /**
445
+ * Creates the trailer
446
+ * @param numObjects - Number of objects
447
+ * @param offsetTableOffset - Offset of the offset table
448
+ * @returns Buffer containing the trailer
449
+ */
450
+ _createTrailer(numObjects, offsetTableOffset) {
451
+ const trailer = Buffer.alloc(BPLIST_TRAILER_SIZE);
452
+ // 6 unused bytes
453
+ trailer.fill(0, 0, 6);
454
+ // offset size (1 byte)
455
+ trailer.writeUInt8(this._offsetSize, 6);
456
+ // object ref size (1 byte)
457
+ trailer.writeUInt8(this._objectRefSize, 7);
458
+ // number of objects (8 bytes)
459
+ this._writeBigIntToBuffer(trailer, 8, BigInt(numObjects));
460
+ // top object ID (8 bytes)
461
+ this._writeBigIntToBuffer(trailer, 16, BigInt(0)); // Root object is always the first one
462
+ // offset table offset (8 bytes)
463
+ this._writeBigIntToBuffer(trailer, 24, BigInt(offsetTableOffset));
464
+ return trailer;
465
+ }
466
+ }
467
+ /**
468
+ * Creates a binary plist from a JavaScript object
469
+ * @param obj - The JavaScript object to convert to a binary plist
470
+ * @returns Buffer containing the binary plist data
471
+ */
472
+ export function createBinaryPlist(obj) {
473
+ const creator = new BinaryPlistCreator(obj);
474
+ return creator.create();
475
+ }
@@ -0,0 +1,14 @@
1
+ import type { PlistValue } from '../types.js';
2
+ /**
3
+ * Parses a binary plist buffer into a JavaScript object
4
+ * @param buffer - The binary plist data as a Buffer
5
+ * @returns The parsed JavaScript object
6
+ */
7
+ export declare function parseBinaryPlist(buffer: Buffer): PlistValue;
8
+ /**
9
+ * Determines if a buffer is a binary plist
10
+ * @param buffer - The buffer to check
11
+ * @returns True if the buffer is a binary plist
12
+ */
13
+ export declare function isBinaryPlist(buffer: Buffer): boolean;
14
+ //# sourceMappingURL=binary-plist-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-plist-parser.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/binary-plist-parser.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAA+B,UAAU,EAAE,MAAM,aAAa,CAAC;AA+iB3E;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAIrD"}