@limrun/ui 0.14.0-rc.4 → 0.14.0-rc.5
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/app-store-relay/index.cjs +3 -3
- package/dist/app-store-relay/index.d.ts +108 -4
- package/dist/app-store-relay/index.js +353 -160
- package/dist/app-store-relay/react.cjs +1 -1
- package/dist/app-store-relay/react.js +1 -1
- package/dist/apple-credentials/index.cjs +1 -1
- package/dist/apple-credentials/index.d.ts +59 -8
- package/dist/apple-credentials/index.js +197 -133
- package/dist/client-C9z_sgOf.js +1 -0
- package/dist/{client-DSuNtWDv.mjs → client-CFDB4mX5.mjs} +37 -30
- package/dist/core/device-install/apple/provisioning.d.ts +25 -0
- package/dist/core/device-install/apple/relay.d.ts +13 -0
- package/dist/core/device-install/storage/secret-store.d.ts +24 -1
- package/dist/device-build/index.cjs +1 -1
- package/dist/device-build/index.js +1 -1
- package/dist/device-install/index.cjs +1 -1
- package/dist/device-install/index.js +175 -172
- package/dist/{provisioning-B_DefBEp.mjs → provisioning-CDPvxd1h.mjs} +63 -32
- package/dist/provisioning-CbC4h--7.js +1 -0
- package/package.json +1 -1
- package/src/app-store-relay/index.ts +358 -23
- package/src/apple-credentials/index.test.ts +22 -0
- package/src/apple-credentials/index.ts +161 -14
- package/src/core/device-install/apple/client.ts +13 -6
- package/src/core/device-install/apple/provisioning.test.ts +30 -0
- package/src/core/device-install/apple/provisioning.ts +39 -0
- package/src/core/device-install/apple/relay.ts +20 -0
- package/src/core/device-install/operations/operations.ts +6 -1
- package/src/core/device-install/storage/secret-store.ts +36 -2
- package/dist/client-D1drDXxE.js +0 -1
- package/dist/provisioning-BlQMccX_.js +0 -1
|
@@ -8,7 +8,7 @@ class g {
|
|
|
8
8
|
pending = /* @__PURE__ */ new Map();
|
|
9
9
|
async connect() {
|
|
10
10
|
if (this.socket && this.socket.readyState === WebSocket.OPEN) return;
|
|
11
|
-
const t = new WebSocket(
|
|
11
|
+
const t = new WebSocket(N(this.apiUrl, this.token, this.organizationId));
|
|
12
12
|
this.socket = t, t.onmessage = (r) => this.handleMessage(r), t.onclose = () => this.rejectPending(new Error("Apple relay WebSocket closed")), t.onerror = () => this.rejectPending(new Error("Apple relay WebSocket failed")), await new Promise((r, o) => {
|
|
13
13
|
t.onopen = () => r(), t.onerror = () => o(new Error("Apple relay WebSocket connection failed"));
|
|
14
14
|
});
|
|
@@ -19,7 +19,7 @@ class g {
|
|
|
19
19
|
throw new Error("Apple relay WebSocket is not connected.");
|
|
20
20
|
const c = String(this.nextId++), n = new Promise((p, i) => {
|
|
21
21
|
this.pending.set(c, {
|
|
22
|
-
resolve: (
|
|
22
|
+
resolve: (f) => p(E(f)),
|
|
23
23
|
reject: i
|
|
24
24
|
});
|
|
25
25
|
});
|
|
@@ -48,11 +48,11 @@ class g {
|
|
|
48
48
|
this.pending.clear();
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
async function
|
|
51
|
+
async function A(e, t, r) {
|
|
52
52
|
const o = new g(e, t, r);
|
|
53
53
|
return await o.connect(), o;
|
|
54
54
|
}
|
|
55
|
-
async function
|
|
55
|
+
async function b(e, t) {
|
|
56
56
|
return e.request("srpInit", t);
|
|
57
57
|
}
|
|
58
58
|
async function P(e, t) {
|
|
@@ -70,13 +70,16 @@ async function T(e, t) {
|
|
|
70
70
|
async function v(e, t, r, o = "sms") {
|
|
71
71
|
return e.request("submitPhone2FA", { phoneNumberId: t, mode: o, code: r });
|
|
72
72
|
}
|
|
73
|
-
async function
|
|
73
|
+
async function q(e) {
|
|
74
74
|
return e.request("finalize");
|
|
75
75
|
}
|
|
76
|
-
async function
|
|
76
|
+
async function x(e, t) {
|
|
77
77
|
return e.request("provisioning", t);
|
|
78
78
|
}
|
|
79
|
-
function
|
|
79
|
+
async function M(e, t) {
|
|
80
|
+
return e.request("appstoreconnect", t);
|
|
81
|
+
}
|
|
82
|
+
function E(e) {
|
|
80
83
|
if (e.body !== void 0 || !e.rawBody)
|
|
81
84
|
return e;
|
|
82
85
|
try {
|
|
@@ -88,36 +91,36 @@ function N(e) {
|
|
|
88
91
|
return e;
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
|
-
function
|
|
94
|
+
function N(e, t, r) {
|
|
92
95
|
const o = new URL(e);
|
|
93
96
|
return o.protocol = o.protocol === "https:" ? "wss:" : "ws:", o.pathname = `${o.pathname.replace(/\/$/, "")}/ios/appstoreconnect/ws`, t && o.searchParams.set("token", t), r && o.searchParams.set("organization", r), o.toString();
|
|
94
97
|
}
|
|
95
|
-
async function
|
|
98
|
+
async function $({
|
|
96
99
|
registryApiUrl: e,
|
|
97
100
|
accountName: t,
|
|
98
101
|
password: r,
|
|
99
102
|
token: o,
|
|
100
103
|
organizationId: c
|
|
101
104
|
}) {
|
|
102
|
-
const n = await
|
|
105
|
+
const n = await A(e, o, c);
|
|
103
106
|
try {
|
|
104
|
-
const p = new m(t), i = await
|
|
107
|
+
const p = new m(t), i = await b(n, await p.init());
|
|
105
108
|
if (i.status < 200 || i.status >= 300)
|
|
106
109
|
throw new Error(
|
|
107
110
|
`Apple SRP init failed: HTTP ${i.status} ${i.rawBody ?? ""}`.trim()
|
|
108
111
|
);
|
|
109
112
|
if (!i.body)
|
|
110
113
|
throw new Error("Apple SRP init response did not include a body.");
|
|
111
|
-
const
|
|
112
|
-
...
|
|
114
|
+
const f = await p.complete(r, i.body), u = await P(n, {
|
|
115
|
+
...f,
|
|
113
116
|
rememberMe: !1,
|
|
114
117
|
trustTokens: []
|
|
115
118
|
}), y = u.status === 409;
|
|
116
119
|
let s, l = { type: "trustedDevice" };
|
|
117
120
|
if (y) {
|
|
118
121
|
s = await S(n);
|
|
119
|
-
const a =
|
|
120
|
-
if (s.status === 412) {
|
|
122
|
+
const a = F(s.body);
|
|
123
|
+
if (s.status === 412 || R(s.body)) {
|
|
121
124
|
if (!a)
|
|
122
125
|
throw new Error("Apple requested phone verification but did not include a trusted phone number.");
|
|
123
126
|
l = {
|
|
@@ -147,16 +150,19 @@ async function M({
|
|
|
147
150
|
);
|
|
148
151
|
return d;
|
|
149
152
|
},
|
|
150
|
-
finalize: async () =>
|
|
153
|
+
finalize: async () => q(n),
|
|
151
154
|
close: async () => n.close()
|
|
152
155
|
};
|
|
153
156
|
} catch (p) {
|
|
154
157
|
throw n.close(), p;
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
function R(e) {
|
|
161
|
+
return h(e) && e.noTrustedDevices === !0;
|
|
162
|
+
}
|
|
163
|
+
function F(e) {
|
|
164
|
+
if (!h(e)) return;
|
|
165
|
+
const t = h(e.phoneNumberVerification) ? e.phoneNumberVerification : void 0, r = w(t?.trustedPhoneNumber) ?? w(e.trustedPhoneNumber) ?? w(e.phoneNumber);
|
|
160
166
|
if (!r) return;
|
|
161
167
|
const o = r.id;
|
|
162
168
|
if (typeof o != "number") return;
|
|
@@ -164,21 +170,22 @@ function q(e) {
|
|
|
164
170
|
return { id: o, pushMode: c };
|
|
165
171
|
}
|
|
166
172
|
function w(e) {
|
|
167
|
-
return
|
|
173
|
+
return h(e) ? e : void 0;
|
|
168
174
|
}
|
|
169
|
-
function
|
|
175
|
+
function h(e) {
|
|
170
176
|
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
171
177
|
}
|
|
172
178
|
export {
|
|
173
179
|
g as A,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
M as a,
|
|
181
|
+
v as b,
|
|
182
|
+
P as c,
|
|
183
|
+
b as d,
|
|
184
|
+
T as e,
|
|
185
|
+
q as f,
|
|
186
|
+
S as g,
|
|
187
|
+
A as o,
|
|
188
|
+
x as p,
|
|
189
|
+
$ as s,
|
|
183
190
|
k as t
|
|
184
191
|
};
|
|
@@ -94,6 +94,11 @@ export declare function findAdHocProfilesRequest({ bundleID, teamID, }: Pick<App
|
|
|
94
94
|
path: string;
|
|
95
95
|
payload: Record<string, unknown>;
|
|
96
96
|
};
|
|
97
|
+
export declare function findAppStoreProfilesRequest({ bundleID, teamID, }: Pick<AppleProvisioningContext, 'bundleID' | 'teamID'>): {
|
|
98
|
+
method: "POST";
|
|
99
|
+
path: string;
|
|
100
|
+
payload: Record<string, unknown>;
|
|
101
|
+
};
|
|
97
102
|
export declare function registerDeviceRequest({ deviceUDID, teamID, name, }: Pick<AppleProvisioningContext, 'deviceUDID' | 'teamID'> & {
|
|
98
103
|
name?: string;
|
|
99
104
|
}): {
|
|
@@ -197,6 +202,26 @@ export declare function createAdHocProfileRequest({ bundleID, teamID, appIDID, c
|
|
|
197
202
|
subPlatform: string;
|
|
198
203
|
};
|
|
199
204
|
};
|
|
205
|
+
/**
|
|
206
|
+
* App Store distribution profiles bind no devices, and the name is required
|
|
207
|
+
* because implementors brand profiles themselves; there is no default.
|
|
208
|
+
*/
|
|
209
|
+
export declare function createAppStoreProfileRequest({ teamID, appIDID, certificateID, name, }: Pick<AppleProvisioningContext, 'teamID'> & {
|
|
210
|
+
appIDID: string;
|
|
211
|
+
certificateID: string;
|
|
212
|
+
name: string;
|
|
213
|
+
}): {
|
|
214
|
+
method: "POST";
|
|
215
|
+
path: string;
|
|
216
|
+
payload: {
|
|
217
|
+
teamId: string;
|
|
218
|
+
provisioningProfileName: string;
|
|
219
|
+
certificateIds: string[];
|
|
220
|
+
appIdId: string;
|
|
221
|
+
distributionType: string;
|
|
222
|
+
subPlatform: string;
|
|
223
|
+
};
|
|
224
|
+
};
|
|
200
225
|
export declare function downloadProfileRequest(profileID: string, teamID?: string): {
|
|
201
226
|
method: "GET";
|
|
202
227
|
path: string;
|
|
@@ -12,6 +12,18 @@ export type AppleProvisioningRequest = {
|
|
|
12
12
|
path: string;
|
|
13
13
|
payload?: unknown;
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* A session-authenticated App Store Connect request proxied by the relay.
|
|
17
|
+
* Unlike provisioning requests, payloads pass through as JSON and GET
|
|
18
|
+
* parameters go into an explicit query map because the App Store Connect
|
|
19
|
+
* API uses bracketed JSON:API keys like fields[apiKeys].
|
|
20
|
+
*/
|
|
21
|
+
export type AppStoreConnectRequest = {
|
|
22
|
+
method?: 'GET' | 'POST';
|
|
23
|
+
path: string;
|
|
24
|
+
query?: Record<string, string>;
|
|
25
|
+
payload?: unknown;
|
|
26
|
+
};
|
|
15
27
|
export declare class AppleRelayWebSocketClient {
|
|
16
28
|
private readonly apiUrl;
|
|
17
29
|
private readonly token?;
|
|
@@ -38,3 +50,4 @@ export declare function proxyTwoFactorCode(relay: AppleRelayWebSocketClient, cod
|
|
|
38
50
|
export declare function proxyPhoneTwoFactorCode(relay: AppleRelayWebSocketClient, phoneNumberId: number, code: string, mode?: string): Promise<AppleRelayResponse<unknown>>;
|
|
39
51
|
export declare function fetchAppleAccountSession(relay: AppleRelayWebSocketClient): Promise<AppleRelayResponse<unknown>>;
|
|
40
52
|
export declare function proxyProvisioningRequest<T = unknown>(relay: AppleRelayWebSocketClient, request: AppleProvisioningRequest): Promise<AppleRelayResponse<T>>;
|
|
53
|
+
export declare function proxyAppStoreConnectRequest<T = unknown>(relay: AppleRelayWebSocketClient, request: AppStoreConnectRequest): Promise<AppleRelayResponse<T>>;
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const APPLE_CERTIFICATE_SECRET_TYPE = "appleCertificate";
|
|
11
11
|
export declare const APPLE_PROVISIONING_PROFILE_SECRET_TYPE = "appleProvisioningProfile";
|
|
12
|
-
export
|
|
12
|
+
export declare const APP_STORE_CONNECT_API_KEY_SECRET_TYPE = "appStoreConnectApiKey";
|
|
13
|
+
export type SigningSecretType = typeof APPLE_CERTIFICATE_SECRET_TYPE | typeof APPLE_PROVISIONING_PROFILE_SECRET_TYPE | typeof APP_STORE_CONNECT_API_KEY_SECRET_TYPE;
|
|
13
14
|
export type SigningSecretMetadata = {
|
|
14
15
|
type: string;
|
|
15
16
|
name: string;
|
|
@@ -70,6 +71,23 @@ export type AppleProvisioningProfileSecretData = {
|
|
|
70
71
|
uuid?: string;
|
|
71
72
|
expirationDate?: string;
|
|
72
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* Data payload of an appStoreConnectApiKey secret: the private half of an
|
|
76
|
+
* App Store Connect API key plus the identifiers needed to sign JWTs with
|
|
77
|
+
* it. Apple serves the private key exactly once, so the stored copy is the
|
|
78
|
+
* only one.
|
|
79
|
+
*/
|
|
80
|
+
export type AppStoreConnectApiKeySecretData = {
|
|
81
|
+
/** Base64 of the .p8 private key PEM. */
|
|
82
|
+
privateKeyP8Base64: string;
|
|
83
|
+
/** Apple's key ID, e.g. 2X9R4HXF34. */
|
|
84
|
+
keyId: string;
|
|
85
|
+
/** Issuer ID for team keys. Absent for individual keys. */
|
|
86
|
+
issuerId?: string;
|
|
87
|
+
nickname?: string;
|
|
88
|
+
teamID?: string;
|
|
89
|
+
expirationDate?: string;
|
|
90
|
+
};
|
|
73
91
|
/** Stores an Apple certificate bundle, conventionally named `${teamID}/${certificateType}`. */
|
|
74
92
|
export declare function putAppleCertificateSecret(store: SigningSecretStore, name: string, data: AppleCertificateSecretData): Promise<SigningSecret>;
|
|
75
93
|
/**
|
|
@@ -78,6 +96,11 @@ export declare function putAppleCertificateSecret(store: SigningSecretStore, nam
|
|
|
78
96
|
* set; consumers select by the reference fields, not by name.
|
|
79
97
|
*/
|
|
80
98
|
export declare function putAppleProvisioningProfileSecret(store: SigningSecretStore, name: string, data: AppleProvisioningProfileSecretData): Promise<SigningSecret>;
|
|
99
|
+
/**
|
|
100
|
+
* Stores an App Store Connect API key, conventionally named
|
|
101
|
+
* `${teamID}/APP_STORE_CONNECT_API_KEY`: one shared key per team.
|
|
102
|
+
*/
|
|
103
|
+
export declare function putAppStoreConnectApiKeySecret(store: SigningSecretStore, name: string, data: AppStoreConnectApiKeySecretData): Promise<SigningSecret>;
|
|
81
104
|
export type LimrunSecretStoreOptions = {
|
|
82
105
|
/** Base URL of the Limrun backend API, e.g. https://api.limrun.com */
|
|
83
106
|
apiUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../limbuild-client-CVDwq54z.js");require("../gsa-srp-CCIfUz7Y.js");require("../index-ChhtuQ7e.js");const c=require("../provisioning-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../limbuild-client-CVDwq54z.js");require("../gsa-srp-CCIfUz7Y.js");require("../index-ChhtuQ7e.js");const c=require("../provisioning-CbC4h--7.js"),i=require("../browser-storage-DLxIqZk5.js");async function v({certificateFile:t,provisioningProfileFile:e,certificatePassword:n,bundleId:s,deviceUDID:o,teamId:d,signingMode:f="development",certificateId:p}){const[u,A,r]=await Promise.all([l(t),l(e),i.parseProvisioningProfile(e)]);return g({profile:r,bundleId:s,deviceUDID:o,signingMode:f}),i.putSigningAssets({bundleID:s??r.bundleID??r.applicationIdentifier??e.name,deviceUDID:o,teamID:d??r.teamID,signingMode:f,certificateID:p,certificateP12Base64:u,certificateFileName:t.name,certificatePassword:n||void 0,provisioningProfileBase64:A,profileFileName:e.name,profile:r})}function S(t,e={}){g({profile:t.profile,bundleId:e.bundleId,deviceUDID:e.deviceUDID,signingMode:e.signingMode??t.signingMode})}function g({profile:t,bundleId:e,deviceUDID:n,signingMode:s}){if(e&&!i.profileMatchesBundleID(t,e))throw new Error(`Provisioning profile does not match bundle ID ${e}.`);if(n&&!i.profileContainsDevice(t,n))throw new Error("Provisioning profile does not include the selected iPhone.");if(s==="adhoc"&&t.getTaskAllow)throw new Error("Ad Hoc mode requires an Ad Hoc provisioning profile, not a development profile.")}async function l(t){const e=await t.arrayBuffer();let n="";const s=new Uint8Array(e);for(const o of s)n+=String.fromCharCode(o);return btoa(n)}exports.fetchLimbuildInfo=a.fetchLimbuildInfo;exports.getIOSOTAInstall=a.getIOSOTAInstall;exports.startSignedDeviceBuild=a.startSignedDeviceBuild;exports.watchBuildLogEvents=a.watchBuildLogEvents;exports.getReusableAppleSigningAssets=c.getReusableAppleSigningAssets;exports.putAppleGeneratedSigningAssets=c.putAppleGeneratedSigningAssets;exports.getLatestSigningAssets=i.getLatestSigningAssets;exports.getLatestSigningAssetsWithCertificate=i.getLatestSigningAssetsWithCertificate;exports.getSigningAssets=i.getSigningAssets;exports.parseProvisioningProfile=i.parseProvisioningProfile;exports.parseProvisioningProfileBase64=i.parseProvisioningProfileBase64;exports.parseProvisioningProfileBytes=i.parseProvisioningProfileBytes;exports.profileContainsDevice=i.profileContainsDevice;exports.profileMatchesBundleID=i.profileMatchesBundleID;exports.putSigningAssets=i.putSigningAssets;exports.fileToBase64=l;exports.importSigningAssetsFromFiles=v;exports.validateProvisioningProfileForInstall=g;exports.validateSigningAssetsForInstall=S;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { f as B, g as D, s as y, w as x } from "../limbuild-client-BagK_FWE.mjs";
|
|
2
2
|
import "../gsa-srp-Bme3JLEi.mjs";
|
|
3
3
|
import "../index-YDu8K9a4.mjs";
|
|
4
|
-
import { g as E, p as L } from "../provisioning-
|
|
4
|
+
import { g as E, p as L } from "../provisioning-CDPvxd1h.mjs";
|
|
5
5
|
import { p as d, a as m, b as u, c as A } from "../browser-storage-BnO-Ma-e.mjs";
|
|
6
6
|
import { g as T, d as F, e as H, f as N, h as O } from "../browser-storage-BnO-Ma-e.mjs";
|
|
7
7
|
async function I({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("../errors-BSkqS7U-.js"),b=require("../browser-storage-DLxIqZk5.js"),E=1,d=16,s={DeviceHello:1,OpenStream:2,OpenResult:3,StreamData:4,StreamClose:5,InstallProgress:6,Error:7,Ping:8,Pong:9,StartPairing:10,StartInstall:11,PairRecordReady:12};function W(e){const t=new Uint8Array(d+e.payload.byteLength),r=new DataView(t.buffer);return r.setUint8(0,E),r.setUint8(1,e.type),r.setUint8(2,0),r.setUint8(3,0),r.setUint32(4,e.requestId),r.setUint32(8,e.streamId),r.setUint32(12,e.payload.byteLength),t.set(e.payload,d),t}function B(e){if(e.byteLength<d)throw new Error(`Relay frame too short: ${e.byteLength}`);const t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=t.getUint8(0);if(r!==E)throw new Error(`Unsupported relay protocol version ${r}`);const n=t.getUint32(12);if(e.byteLength!==d+n)throw new Error(`Relay frame length mismatch: got ${e.byteLength}, expected ${d+n}`);return{type:t.getUint8(1),requestId:t.getUint32(4),streamId:t.getUint32(8),payload:e.slice(d)}}function l(e){return new TextEncoder().encode(JSON.stringify(e))}function y(e){return JSON.parse(new TextDecoder().decode(e))}async function F(){if(!navigator.usb)throw new Error("WebUSB is not available in this browser.");return navigator.usb.requestDevice({filters:[{vendorId:1452}]})}function _(e){const t=[],r=e.configuration?.configurationValue,n=e.configurations.find(a=>a.configurationValue===r);n&&t.push(...v(n));for(const a of e.configurations)a.configurationValue!==r&&t.push(...v(a));return t}function v(e){const t=[];for(const r of e.interfaces)for(const n of r.alternates)n.interfaceClass===255&&n.interfaceSubclass===254&&n.interfaceProtocol===2&&t.push({configurationValue:e.configurationValue,interfaceNumber:r.interfaceNumber,alternateSetting:n.alternateSetting,endpoints:n.endpoints});return t}async function M(e,t){e.opened||await e.open(),(!e.configuration||e.configuration.configurationValue!==t.configurationValue)&&await e.selectConfiguration(t.configurationValue),await e.claimInterface(t.interfaceNumber),await e.selectAlternateInterface(t.interfaceNumber,t.alternateSetting)}function j(e){const t=e.endpoints.find(n=>n.direction==="out"&&n.type==="bulk"),r=e.endpoints.find(n=>n.direction==="in"&&n.type==="bulk");if(!t||!r)throw new Error("Could not find usbmux bulk endpoints.");return{outEndpoint:t,inEndpoint:r}}async function k(e,t,r){const n=await e.transferOut(t.endpointNumber,r);if(n.status!=="ok")throw new Error(`USB transferOut failed: ${n.status}`);r.byteLength%t.packetSize===0&&await e.transferOut(t.endpointNumber,new Uint8Array)}async function H(e,t,r=16384){const n=await e.transferIn(t.endpointNumber,r);if(n.status!=="ok"||!n.data)throw new Error(`USB transferIn failed: ${n.status}`);return new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength)}const I=0,J=2,P=6,z=4277009102,m=2,G=4,f=16,Q=49152;async function Y(e,t){const{inEndpoint:r,outEndpoint:n}=j(t),a=new Uint8Array(12),i=new DataView(a.buffer);i.setUint32(0,2),i.setUint32(4,0),i.setUint32(8,0),await k(e,n,D(I,a));const o=await q(e,r,1),c=new DataView(o.payload.buffer,o.payload.byteOffset).getUint32(0),u={device:e,candidate:t,inEndpoint:r,outEndpoint:n,muxVersion:c,txSeq:0,rxSeq:65535,nextSport:Q,streams:new Map,writeChain:Promise.resolve(),closed:!1};return c>=2&&await O(u,J,new Uint8Array([7])),ee(u),u}async function K(e,t){if(e.closed)throw new Error("usbmux session is closed.");let r,n;const a={session:e,sport:e.nextSport++,dport:t,seq:0,ack:0,queue:[],waiters:[],opened:new Promise((i,o)=>{r=i,n=o}),resolveOpened:r,rejectOpened:n};return e.streams.set(g(t,a.sport),a),await w(a,m,new Uint8Array),await a.opened,a}async function X(e,t){if(e.session.closed)throw new Error("usbmux session is closed.");await w(e,f,t),e.seq+=t.byteLength}async function Z(e){if(e.queue.length>0)return e.queue.shift();if(e.error)throw e.error;return new Promise(t=>{e.waiters.push(t)})}function x(e){e.closed=!0;for(const t of e.streams.values())for(t.error=new Error("usbmux session closed"),t.rejectOpened(t.error);t.waiters.length>0;)t.waiters.shift()(new Uint8Array);e.streams.clear()}async function w(e,t,r){const n=new Uint8Array(20+r.byteLength),a=new DataView(n.buffer);a.setUint16(0,e.sport),a.setUint16(2,e.dport),a.setUint32(4,e.seq),a.setUint32(8,e.ack),a.setUint8(12,80),a.setUint8(13,t),a.setUint16(14,512),n.set(r,20),await O(e.session,P,n)}async function O(e,t,r){if(e.closed)throw new Error("usbmux session is closed.");return e.writeChain=e.writeChain.then(async()=>{if(e.closed)return;const n=e.muxVersion>=2?te(t,r,e.txSeq++,e.rxSeq):D(t,r);await k(e.device,e.outEndpoint,n)}),e.writeChain}async function ee(e){try{for(;;){if(e.closed)return;const t=await q(e.device,e.inEndpoint,e.muxVersion);if(e.closed)return;if(t.rxSeq!==void 0&&(e.rxSeq=t.rxSeq),t.protocol!==P)continue;const r=ne(t.payload),n=e.streams.get(g(r.sport,r.dport));if(n){if(r.flags&G){for(n.error=new Error(`Device reset stream ${n.dport}`),n.rejectOpened(n.error);n.waiters.length>0;)n.waiters.shift()(new Uint8Array);e.streams.delete(g(n.dport,n.sport));continue}if((r.flags&(m|f))===(m|f)){n.seq+=1,n.ack=r.seq+1,await w(n,f,new Uint8Array),n.resolveOpened();continue}r.payload.byteLength!==0&&(n.ack=r.seq+r.payload.byteLength,await w(n,f,new Uint8Array),n.waiters.length>0?n.waiters.shift()(r.payload):n.queue.push(r.payload))}}}catch{e.closed||x(e)}}async function q(e,t,r){for(;;){const n=await H(e,t),a=re(n,r);if(!(r===1&&a.protocol!==I))return a}}function D(e,t){const r=new Uint8Array(8+t.byteLength),n=new DataView(r.buffer);return n.setUint32(0,e),n.setUint32(4,r.byteLength),r.set(t,8),r}function te(e,t,r,n){const a=new Uint8Array(16+t.byteLength),i=new DataView(a.buffer);return i.setUint32(0,e),i.setUint32(4,a.byteLength),i.setUint32(8,z),i.setUint16(12,r),i.setUint16(14,n),a.set(t,16),a}function re(e,t){const r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=r.getUint32(0),a=r.getUint32(4),i=t>=2?16:8;return{protocol:n,length:a,rxSeq:t>=2?r.getUint16(14):void 0,payload:e.slice(i,a)}}function ne(e){const t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=(t.getUint8(12)>>4)*4;return{sport:t.getUint16(0),dport:t.getUint16(2),seq:t.getUint32(4),ack:t.getUint32(8),flags:t.getUint8(13),payload:e.slice(r)}}function g(e,t){return`${e}:${t}`}class ${constructor(t,r,n,a){this.webSocketUrl=t,this.session=r,this.deviceHello=n,this.log=a}socket;streams=new Map;frameQueue=Promise.resolve();closed=!1;pairRecordWaiter;async connect(){const t=new WebSocket(this.webSocketUrl);t.binaryType="arraybuffer",this.socket=t,t.onclose=()=>{this.closed=!0,this.log("Relay socket closed"),this.frameQueue.finally(()=>{this.pairRecordWaiter&&(this.pairRecordWaiter.reject(new Error("Relay socket closed")),this.pairRecordWaiter=void 0)})},await new Promise((r,n)=>{t.onopen=()=>r(),t.onerror=()=>n(new Error("WebSocket connection failed"))}),t.onmessage=r=>{const n=r.data instanceof ArrayBuffer?new Uint8Array(r.data):new Uint8Array;this.enqueueFrame(n)},await this.send({type:s.DeviceHello,requestId:0,streamId:0,payload:l(this.deviceHello)}),this.log("Connected WebSocket relay")}async startPairing(){const t=new Promise((r,n)=>{this.pairRecordWaiter={resolve:r,reject:n}});return await this.send({type:s.StartPairing,requestId:0,streamId:0,payload:l({})}),this.log("Pairing requested"),t}async startInstall(t,r){await this.send({type:s.StartInstall,requestId:0,streamId:0,payload:l({...t,...r})}),this.log("Installation requested")}close(){this.closed=!0,this.socket?.close()}enqueueFrame(t){this.frameQueue=this.frameQueue.then(()=>this.handleFrame(B(t))).catch(r=>{this.log("Relay frame handling failed",r instanceof Error?r.message:String(r))})}async handleFrame(t){switch(t.type){case s.OpenStream:await this.handleOpenStream(t.requestId,t.streamId,y(t.payload).port);break;case s.StreamData:{const r=this.streams.get(t.streamId);if(!r)throw new Error(`Unknown stream ${t.streamId}`);await X(r,t.payload);break}case s.StreamClose:this.streams.delete(t.streamId);break;case s.InstallProgress:this.log(ie(y(t.payload).message));break;case s.Error:this.handleError(t.payload);break;case s.PairRecordReady:this.handlePairRecordReady(y(t.payload));break;case s.Ping:await this.send({type:s.Pong,requestId:t.requestId,streamId:0,payload:new Uint8Array});break}}handleError(t){const r=ae(t);this.log("Server error",r),this.pairRecordWaiter&&(this.pairRecordWaiter.reject(new Error(r)),this.pairRecordWaiter=void 0)}handlePairRecordReady(t){this.log("Pair record received",t.udid),this.pairRecordWaiter?.resolve(t),this.pairRecordWaiter=void 0}async handleOpenStream(t,r,n){try{const a=await K(this.session,n);this.streams.set(r,a),await this.send({type:s.OpenResult,requestId:t,streamId:r,payload:l({ok:!0})}),this.log(`Opened device stream ${r} to port ${n}`),this.pumpDeviceToServer(r,a)}catch(a){this.log(`Open device stream ${r} failed`,a instanceof Error?a.message:String(a)),await this.send({type:s.OpenResult,requestId:t,streamId:r,payload:l({ok:!1,error:a instanceof Error?a.message:String(a)})})}}async pumpDeviceToServer(t,r){try{for(;;){const n=await Z(r);if(this.closed)return;await this.send({type:s.StreamData,requestId:0,streamId:t,payload:n})}}catch(n){this.log(`Device stream ${t} closed`,n instanceof Error?n.message:String(n)),await this.send({type:s.StreamClose,requestId:0,streamId:t,payload:l({reason:n instanceof Error?n.message:String(n)})})}}async send(t){if(!this.closed){if(!this.socket||this.socket.readyState!==WebSocket.OPEN){this.closed=!0;return}this.socket.send(W(t))}}}function ae(e){const t=new TextDecoder().decode(e);try{const r=JSON.parse(t);return R(r.error??t)}catch{return R(t)}}function R(e){return e.replace(/libimobiledevice/g,"").trim()}function ie(e){const t="install status: ";if(!e.startsWith(t))return e;const r=e.slice(t.length),n=p(r,"Error");if(n){const o=p(r,"ErrorDescription");return`Install error: ${n}${o?` — ${o}`:""}`}const a=p(r,"Status")??"Unknown",i=p(r,"PercentComplete");return`Install progress: ${i?`${i}% `:""}${a}`}function p(e,t){const n=new RegExp(`<key>\\s*${oe(t)}\\s*</key>\\s*<(?:string|integer|real)>([\\s\\S]*?)</(?:string|integer|real)>`).exec(e);return n?se(n[1].trim()):void 0}function oe(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function se(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}async function ce({log:e}){e("Selecting USB device");const t=await F(),r=le(t);return e("Selected USB device",`${t.manufacturerName??""} ${t.productName??""} ${t.serialNumber??""}`.trim()),r}async function N({registryApiUrl:e,token:t,organizationId:r,log:n,target:a}){const i=U(e,t,r);let o;try{o=await C(i,a,n);const c=await o.startPairing();return{relay:o,pairRecord:c,target:a}}catch(c){throw o?.close(),c}}async function V({registryApiUrl:e,token:t,organizationId:r,log:n,target:a,pairRecord:i,installSource:o}){const c=U(e,t,r);let u;try{return u=await C(c,a,n),await u.startInstall(i,o),u}catch(T){throw u?.close(),T}}async function A(e,t){if(e){if(e.session&&(x(e.session),e.session=void 0),e.claimedInterfaceNumber!==void 0)try{await e.device.releaseInterface(e.claimedInterfaceNumber),t?.("Released usbmux interface")}catch(r){t?.("USB interface release failed",h.errorMessage(r))}finally{e.claimedInterfaceNumber=void 0}if(e.device.opened)try{await e.device.close(),t?.("Closed USB device")}catch(r){t?.("USB device close failed",h.errorMessage(r))}}}async function C(e,t,r){await ue(t,r);const n=new $(e,t.session,t.hello,r);return await n.connect(),n}async function ue(e,t){if(!e.session)try{e.candidate=await de(e,t),e.session=await Y(e.device,e.candidate),t("Created usbmux session")}catch(r){throw await A(e,t),r}}function le(e){return{device:e,candidate:fe(e),hello:{serialNumber:e.serialNumber,productName:e.productName,manufacturerName:e.manufacturerName,productId:e.productId,vendorId:e.vendorId}}}async function de(e,t){const r=L(e.device);if(r.length===0)throw new Error("No Apple usbmux interface found.");let n;for(const a of r)for(const i of[1,2])try{return e.device.opened||await e.device.open(),t("Claiming usbmux interface",`configuration ${a.configurationValue}, interface ${a.interfaceNumber}, alternate ${a.alternateSetting}, attempt ${i}`),await M(e.device,a),e.claimedInterfaceNumber=a.interfaceNumber,t("Claimed usbmux interface",`configuration ${a.configurationValue}, interface ${a.interfaceNumber}`),a}catch(o){n=o,t("USB interface claim failed",`configuration ${a.configurationValue}, interface ${a.interfaceNumber}: ${h.errorMessage(o)}`),await pe(e),await we(250)}throw n instanceof Error?n:new Error("Unable to claim any Apple usbmux interface.")}function fe(e){const t=L(e)[0];if(!t)throw new Error("No Apple usbmux interface found.");return t}function L(e){const t=_(e),r=e.configuration?.configurationValue;return[...t.filter(n=>n.configurationValue===r),...t.filter(n=>n.configurationValue!==r)]}function U(e,t,r){const n=new URL(e);return n.protocol=n.protocol==="https:"?"wss:":"ws:",n.pathname=`${n.pathname.replace(/\/$/,"")}/ios/device/ws`,t&&n.searchParams.set("token",t),r&&n.searchParams.set("organization",r),n.toString()}async function pe(e){if(e.claimedInterfaceNumber!==void 0){try{await e.device.releaseInterface(e.claimedInterfaceNumber)}catch{}e.claimedInterfaceNumber=void 0}if(e.device.opened)try{await e.device.close()}catch{}}function we(e){return new Promise(t=>setTimeout(t,e))}async function ye(e={}){return ce({log:e.log??S})}async function he(e){return N({...e,log:e.log??S})}async function me(e){return V({...e,log:e.log??S})}function S(){}exports.getPairRecord=b.getPairRecord;exports.normalizeUDID=b.normalizeUDID;exports.putPairRecord=b.putPairRecord;exports.RelayClient=$;exports.closeDeviceRelayTarget=A;exports.deviceRelayWebSocketUrl=U;exports.pairDevice=he;exports.requestUSBAccess=ye;exports.startDeviceInstall=me;exports.startDeviceInstallRelay=V;exports.startDevicePairingRelay=N;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("../errors-BSkqS7U-.js"),b=require("../browser-storage-DLxIqZk5.js"),E=1,d=16,s={DeviceHello:1,OpenStream:2,OpenResult:3,StreamData:4,StreamClose:5,InstallProgress:6,Error:7,Ping:8,Pong:9,StartPairing:10,StartInstall:11,PairRecordReady:12};function B(e){const t=new Uint8Array(d+e.payload.byteLength),r=new DataView(t.buffer);return r.setUint8(0,E),r.setUint8(1,e.type),r.setUint8(2,0),r.setUint8(3,0),r.setUint32(4,e.requestId),r.setUint32(8,e.streamId),r.setUint32(12,e.payload.byteLength),t.set(e.payload,d),t}function W(e){if(e.byteLength<d)throw new Error(`Relay frame too short: ${e.byteLength}`);const t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=t.getUint8(0);if(r!==E)throw new Error(`Unsupported relay protocol version ${r}`);const n=t.getUint32(12);if(e.byteLength!==d+n)throw new Error(`Relay frame length mismatch: got ${e.byteLength}, expected ${d+n}`);return{type:t.getUint8(1),requestId:t.getUint32(4),streamId:t.getUint32(8),payload:e.slice(d)}}function l(e){return new TextEncoder().encode(JSON.stringify(e))}function y(e){return JSON.parse(new TextDecoder().decode(e))}async function F(){if(!navigator.usb)throw new Error("WebUSB is not available in this browser.");return navigator.usb.requestDevice({filters:[{vendorId:1452}]})}function M(e){const t=[],r=e.configuration?.configurationValue,n=e.configurations.find(a=>a.configurationValue===r);n&&t.push(...v(n));for(const a of e.configurations)a.configurationValue!==r&&t.push(...v(a));return t}function v(e){const t=[];for(const r of e.interfaces)for(const n of r.alternates)n.interfaceClass===255&&n.interfaceSubclass===254&&n.interfaceProtocol===2&&t.push({configurationValue:e.configurationValue,interfaceNumber:r.interfaceNumber,alternateSetting:n.alternateSetting,endpoints:n.endpoints});return t}async function _(e,t){e.opened||await e.open(),(!e.configuration||e.configuration.configurationValue!==t.configurationValue)&&await e.selectConfiguration(t.configurationValue),await e.claimInterface(t.interfaceNumber),await e.selectAlternateInterface(t.interfaceNumber,t.alternateSetting)}function j(e){const t=e.endpoints.find(n=>n.direction==="out"&&n.type==="bulk"),r=e.endpoints.find(n=>n.direction==="in"&&n.type==="bulk");if(!t||!r)throw new Error("Could not find usbmux bulk endpoints.");return{outEndpoint:t,inEndpoint:r}}async function P(e,t,r){const n=await e.transferOut(t.endpointNumber,r);if(n.status!=="ok")throw new Error(`USB transferOut failed: ${n.status}`);r.byteLength%t.packetSize===0&&await e.transferOut(t.endpointNumber,new Uint8Array)}async function H(e,t,r=16384){const n=await e.transferIn(t.endpointNumber,r);if(n.status!=="ok"||!n.data)throw new Error(`USB transferIn failed: ${n.status}`);return new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength)}const k=0,J=2,I=6,z=4277009102,g=2,G=4,f=16,Q=49152;async function Y(e,t){const{inEndpoint:r,outEndpoint:n}=j(t),a=new Uint8Array(12),i=new DataView(a.buffer);i.setUint32(0,2),i.setUint32(4,0),i.setUint32(8,0),await P(e,n,D(k,a));const o=await O(e,r,1),c=new DataView(o.payload.buffer,o.payload.byteOffset).getUint32(0),u={device:e,candidate:t,inEndpoint:r,outEndpoint:n,muxVersion:c,txSeq:0,rxSeq:65535,nextSport:Q,streams:new Map,writeChain:Promise.resolve(),closed:!1};return c>=2&&await q(u,J,new Uint8Array([7])),ee(u),u}async function K(e,t){if(e.closed)throw new Error("usbmux session is closed.");let r,n;const a={session:e,sport:e.nextSport++,dport:t,seq:0,ack:0,queue:[],waiters:[],opened:new Promise((i,o)=>{r=i,n=o}),resolveOpened:r,rejectOpened:n};return e.streams.set(m(t,a.sport),a),await h(a,g,new Uint8Array),await a.opened,a}async function X(e,t){if(e.session.closed)throw new Error("usbmux session is closed.");await h(e,f,t),e.seq+=t.byteLength}async function Z(e){if(e.queue.length>0)return e.queue.shift();if(e.error)throw e.error;return new Promise(t=>{e.waiters.push(t)})}function x(e){e.closed=!0;for(const t of e.streams.values())for(t.error=new Error("usbmux session closed"),t.rejectOpened(t.error);t.waiters.length>0;)t.waiters.shift()(new Uint8Array);e.streams.clear()}async function h(e,t,r){const n=new Uint8Array(20+r.byteLength),a=new DataView(n.buffer);a.setUint16(0,e.sport),a.setUint16(2,e.dport),a.setUint32(4,e.seq),a.setUint32(8,e.ack),a.setUint8(12,80),a.setUint8(13,t),a.setUint16(14,512),n.set(r,20),await q(e.session,I,n)}async function q(e,t,r){if(e.closed)throw new Error("usbmux session is closed.");return e.writeChain=e.writeChain.then(async()=>{if(e.closed)return;const n=e.muxVersion>=2?te(t,r,e.txSeq++,e.rxSeq):D(t,r);await P(e.device,e.outEndpoint,n)}),e.writeChain}async function ee(e){try{for(;;){if(e.closed)return;const t=await O(e.device,e.inEndpoint,e.muxVersion);if(e.closed)return;if(t.rxSeq!==void 0&&(e.rxSeq=t.rxSeq),t.protocol!==I)continue;const r=ne(t.payload),n=e.streams.get(m(r.sport,r.dport));if(n){if(r.flags&G){for(n.error=new Error(`Device reset stream ${n.dport}`),n.rejectOpened(n.error);n.waiters.length>0;)n.waiters.shift()(new Uint8Array);e.streams.delete(m(n.dport,n.sport));continue}if((r.flags&(g|f))===(g|f)){n.seq+=1,n.ack=r.seq+1,await h(n,f,new Uint8Array),n.resolveOpened();continue}r.payload.byteLength!==0&&(n.ack=r.seq+r.payload.byteLength,await h(n,f,new Uint8Array),n.waiters.length>0?n.waiters.shift()(r.payload):n.queue.push(r.payload))}}}catch{e.closed||x(e)}}async function O(e,t,r){for(;;){const n=await H(e,t),a=re(n,r);if(!(r===1&&a.protocol!==k))return a}}function D(e,t){const r=new Uint8Array(8+t.byteLength),n=new DataView(r.buffer);return n.setUint32(0,e),n.setUint32(4,r.byteLength),r.set(t,8),r}function te(e,t,r,n){const a=new Uint8Array(16+t.byteLength),i=new DataView(a.buffer);return i.setUint32(0,e),i.setUint32(4,a.byteLength),i.setUint32(8,z),i.setUint16(12,r),i.setUint16(14,n),a.set(t,16),a}function re(e,t){const r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=r.getUint32(0),a=r.getUint32(4),i=t>=2?16:8;return{protocol:n,length:a,rxSeq:t>=2?r.getUint16(14):void 0,payload:e.slice(i,a)}}function ne(e){const t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=(t.getUint8(12)>>4)*4;return{sport:t.getUint16(0),dport:t.getUint16(2),seq:t.getUint32(4),ack:t.getUint32(8),flags:t.getUint8(13),payload:e.slice(r)}}function m(e,t){return`${e}:${t}`}class ${constructor(t,r,n,a){this.webSocketUrl=t,this.session=r,this.deviceHello=n,this.log=a}socket;streams=new Map;frameQueue=Promise.resolve();closed=!1;pairRecordWaiter;async connect(){const t=new WebSocket(this.webSocketUrl);t.binaryType="arraybuffer",this.socket=t,t.onclose=()=>{this.closed=!0,this.log("Relay socket closed"),this.frameQueue.finally(()=>{this.pairRecordWaiter&&(this.pairRecordWaiter.reject(new Error("Relay socket closed")),this.pairRecordWaiter=void 0)})},await new Promise((r,n)=>{t.onopen=()=>r(),t.onerror=()=>n(new Error("WebSocket connection failed"))}),t.onmessage=r=>{const n=r.data instanceof ArrayBuffer?new Uint8Array(r.data):new Uint8Array;this.enqueueFrame(n)},await this.send({type:s.DeviceHello,requestId:0,streamId:0,payload:l(this.deviceHello)}),this.log("Connected WebSocket relay")}async startPairing(){const t=new Promise((r,n)=>{this.pairRecordWaiter={resolve:r,reject:n}});return await this.send({type:s.StartPairing,requestId:0,streamId:0,payload:l({})}),this.log("Pairing requested"),t}async startInstall(t,r){await this.send({type:s.StartInstall,requestId:0,streamId:0,payload:l({...t,...r})}),this.log("Installation requested")}close(){this.closed=!0,this.socket?.close()}enqueueFrame(t){this.frameQueue=this.frameQueue.then(()=>this.handleFrame(W(t))).catch(r=>{this.log("Relay frame handling failed",r instanceof Error?r.message:String(r))})}async handleFrame(t){switch(t.type){case s.OpenStream:await this.handleOpenStream(t.requestId,t.streamId,y(t.payload).port);break;case s.StreamData:{const r=this.streams.get(t.streamId);if(!r)throw new Error(`Unknown stream ${t.streamId}`);await X(r,t.payload);break}case s.StreamClose:this.streams.delete(t.streamId);break;case s.InstallProgress:this.log(ie(y(t.payload).message));break;case s.Error:this.handleError(t.payload);break;case s.PairRecordReady:this.handlePairRecordReady(y(t.payload));break;case s.Ping:await this.send({type:s.Pong,requestId:t.requestId,streamId:0,payload:new Uint8Array});break}}handleError(t){const r=ae(t);this.log("Server error",r),this.pairRecordWaiter&&(this.pairRecordWaiter.reject(new Error(r)),this.pairRecordWaiter=void 0)}handlePairRecordReady(t){this.log("Pair record received",t.udid),this.pairRecordWaiter?.resolve(t),this.pairRecordWaiter=void 0}async handleOpenStream(t,r,n){try{const a=await K(this.session,n);this.streams.set(r,a),await this.send({type:s.OpenResult,requestId:t,streamId:r,payload:l({ok:!0})}),this.log(`Opened device stream ${r} to port ${n}`),this.pumpDeviceToServer(r,a)}catch(a){this.log(`Open device stream ${r} failed`,a instanceof Error?a.message:String(a)),await this.send({type:s.OpenResult,requestId:t,streamId:r,payload:l({ok:!1,error:a instanceof Error?a.message:String(a)})})}}async pumpDeviceToServer(t,r){try{for(;;){const n=await Z(r);if(this.closed)return;await this.send({type:s.StreamData,requestId:0,streamId:t,payload:n})}}catch(n){this.log(`Device stream ${t} closed`,n instanceof Error?n.message:String(n)),await this.send({type:s.StreamClose,requestId:0,streamId:t,payload:l({reason:n instanceof Error?n.message:String(n)})})}}async send(t){if(!this.closed){if(!this.socket||this.socket.readyState!==WebSocket.OPEN){this.closed=!0;return}this.socket.send(B(t))}}}function ae(e){const t=new TextDecoder().decode(e);try{const r=JSON.parse(t);return R(r.error??t)}catch{return R(t)}}function R(e){return e.replace(/libimobiledevice/g,"").trim()}function ie(e){const t="install status: ";if(!e.startsWith(t))return e;const r=e.slice(t.length),n=p(r,"Error");if(n){const o=p(r,"ErrorDescription");return`Install error: ${n}${o?` — ${o}`:""}`}const a=p(r,"Status")??"Unknown",i=p(r,"PercentComplete");return`Install progress: ${i?`${i}% `:""}${a}`}function p(e,t){const n=new RegExp(`<key>\\s*${oe(t)}\\s*</key>\\s*<(?:string|integer|real)>([\\s\\S]*?)</(?:string|integer|real)>`).exec(e);return n?se(n[1].trim()):void 0}function oe(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function se(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}async function ce({log:e}){e("Selecting USB device");const t=await F(),r=le(t);return e("Selected USB device",`${t.manufacturerName??""} ${t.productName??""} ${t.serialNumber??""}`.trim()),r}async function N({registryApiUrl:e,token:t,organizationId:r,log:n,target:a}){const i=U(e,t,r);let o;try{o=await C(i,a,n);const c=await o.startPairing();return{relay:o,pairRecord:c,target:a}}catch(c){throw o?.close(),c}}async function V({registryApiUrl:e,token:t,organizationId:r,log:n,target:a,pairRecord:i,installSource:o}){const c=U(e,t,r);let u;try{return u=await C(c,a,n),await u.startInstall(i,o),u}catch(T){throw u?.close(),T}}async function A(e,t){if(e){if(e.session&&(x(e.session),e.session=void 0),e.claimedInterfaceNumber!==void 0)try{await e.device.releaseInterface(e.claimedInterfaceNumber),t?.("Released usbmux interface")}catch(r){t?.("USB interface release failed",w.errorMessage(r))}finally{e.claimedInterfaceNumber=void 0}if(e.device.opened)try{await e.device.close(),t?.("Closed USB device")}catch(r){t?.("USB device close failed",w.errorMessage(r))}}}async function C(e,t,r){await ue(t,r);const n=new $(e,t.session,t.hello,r);return await n.connect(),n}async function ue(e,t){if(!e.session)try{e.candidate=await de(e,t),e.session=await Y(e.device,e.candidate),t("Created usbmux session")}catch(r){throw await A(e,t),r}}function le(e){return{device:e,candidate:fe(e),hello:{serialNumber:e.serialNumber,productName:e.productName,manufacturerName:e.manufacturerName,productId:e.productId,vendorId:e.vendorId}}}async function de(e,t){const r=L(e.device);if(r.length===0)throw new Error("No Apple usbmux interface found.");let n;for(const i of r)for(const o of[1,2])try{return e.device.opened||await e.device.open(),t("Claiming usbmux interface",`configuration ${i.configurationValue}, interface ${i.interfaceNumber}, alternate ${i.alternateSetting}, attempt ${o}`),await _(e.device,i),e.claimedInterfaceNumber=i.interfaceNumber,t("Claimed usbmux interface",`configuration ${i.configurationValue}, interface ${i.interfaceNumber}`),i}catch(c){n=c,t("USB interface claim failed",`configuration ${i.configurationValue}, interface ${i.interfaceNumber}: ${w.errorMessage(c)}`),await pe(e),await we(250)}const a=n?` (${w.errorMessage(n)})`:"";throw new Error(`Could not get exclusive USB access to the iPhone${a}. Another app on this computer is likely connected to it. Close other browser tabs that use this device, quit iPhone Mirroring, Xcode, eject iPhone in Finder windows showing the phone and try again.`)}function fe(e){const t=L(e)[0];if(!t)throw new Error("No Apple usbmux interface found.");return t}function L(e){const t=M(e),r=e.configuration?.configurationValue;return[...t.filter(n=>n.configurationValue===r),...t.filter(n=>n.configurationValue!==r)]}function U(e,t,r){const n=new URL(e);return n.protocol=n.protocol==="https:"?"wss:":"ws:",n.pathname=`${n.pathname.replace(/\/$/,"")}/ios/device/ws`,t&&n.searchParams.set("token",t),r&&n.searchParams.set("organization",r),n.toString()}async function pe(e){if(e.claimedInterfaceNumber!==void 0){try{await e.device.releaseInterface(e.claimedInterfaceNumber)}catch{}e.claimedInterfaceNumber=void 0}if(e.device.opened)try{await e.device.close()}catch{}}function we(e){return new Promise(t=>setTimeout(t,e))}async function he(e={}){return ce({log:e.log??S})}async function ye(e){return N({...e,log:e.log??S})}async function ge(e){return V({...e,log:e.log??S})}function S(){}exports.getPairRecord=b.getPairRecord;exports.normalizeUDID=b.normalizeUDID;exports.putPairRecord=b.putPairRecord;exports.RelayClient=$;exports.closeDeviceRelayTarget=A;exports.deviceRelayWebSocketUrl=U;exports.pairDevice=ye;exports.requestUSBAccess=he;exports.startDeviceInstall=ge;exports.startDeviceInstallRelay=V;exports.startDevicePairingRelay=N;
|