@limrun/ui 0.13.7 → 0.14.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-store-relay/index.cjs +3 -3
- package/dist/app-store-relay/index.d.ts +3 -5
- package/dist/app-store-relay/index.js +56 -58
- package/dist/app-store-relay/react.cjs +1 -1
- package/dist/app-store-relay/react.d.ts +2 -2
- package/dist/app-store-relay/react.js +35 -34
- package/dist/client-BtC4n_qf.js +1 -0
- package/dist/client-CBX-hLnL.mjs +189 -0
- package/dist/core/device-install/apple/client.d.ts +5 -4
- package/dist/core/device-install/apple/relay.d.ts +24 -13
- package/dist/core/device-install/operations/limbuild-client.d.ts +2 -1
- package/dist/core/device-install/operations/operations.d.ts +19 -4
- package/dist/core/device-install/operations/relay-client.d.ts +2 -1
- package/dist/device-build/index.cjs +1 -1
- package/dist/device-build/index.js +1 -1
- package/dist/device-build/react.cjs +1 -1
- package/dist/device-build/react.d.ts +1 -0
- package/dist/device-build/react.js +34 -33
- package/dist/device-install/index.cjs +1 -1
- package/dist/device-install/index.d.ts +1 -1
- package/dist/device-install/index.js +121 -119
- package/dist/device-install/react.cjs +1 -1
- package/dist/device-install/react.d.ts +4 -3
- package/dist/device-install/react.js +58 -54
- package/dist/index.cjs +1 -1
- package/dist/index.js +519 -531
- package/dist/limbuild-client-BagK_FWE.mjs +83 -0
- package/dist/limbuild-client-CVDwq54z.js +1 -0
- package/package.json +1 -1
- package/src/app-store-relay/index.test.ts +19 -29
- package/src/app-store-relay/index.ts +6 -9
- package/src/app-store-relay/react.ts +5 -4
- package/src/components/remote-control.tsx +1 -28
- package/src/core/device-install/apple/client.ts +22 -33
- package/src/core/device-install/apple/relay.ts +108 -148
- package/src/core/device-install/operations/limbuild-client.ts +3 -0
- package/src/core/device-install/operations/operations.ts +21 -9
- package/src/core/device-install/operations/relay-client.ts +3 -2
- package/src/device-build/react.ts +2 -0
- package/src/device-install/README.md +5 -5
- package/src/device-install/demo/demo.tsx +26 -28
- package/src/device-install/index.ts +1 -0
- package/src/device-install/react.ts +12 -6
- package/dist/client-ASLtHFLh.js +0 -1
- package/dist/client-CGdh8yoJ.mjs +0 -234
- package/dist/limbuild-client-CgEncrgx.js +0 -1
- package/dist/limbuild-client-D7U7w342.mjs +0 -81
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { A as m } from "./index-DFdCvi2_.mjs";
|
|
2
|
+
class g {
|
|
3
|
+
constructor(t, r, o) {
|
|
4
|
+
this.apiUrl = t, this.token = r, this.organizationId = o;
|
|
5
|
+
}
|
|
6
|
+
socket;
|
|
7
|
+
nextId = 1;
|
|
8
|
+
pending = /* @__PURE__ */ new Map();
|
|
9
|
+
async connect() {
|
|
10
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) return;
|
|
11
|
+
const t = new WebSocket(R(this.apiUrl, this.token, this.organizationId));
|
|
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
|
+
t.onopen = () => r(), t.onerror = () => o(new Error("Apple relay WebSocket connection failed"));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
request(t, r) {
|
|
17
|
+
const o = this.socket;
|
|
18
|
+
if (!o || o.readyState !== WebSocket.OPEN)
|
|
19
|
+
throw new Error("Apple relay WebSocket is not connected.");
|
|
20
|
+
const c = String(this.nextId++), n = new Promise((p, i) => {
|
|
21
|
+
this.pending.set(c, {
|
|
22
|
+
resolve: (h) => p(N(h)),
|
|
23
|
+
reject: i
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return o.send(JSON.stringify({ id: c, type: t, ...r === void 0 ? {} : { payload: r } })), n;
|
|
27
|
+
}
|
|
28
|
+
close() {
|
|
29
|
+
this.rejectPending(new Error("Apple relay WebSocket closed")), this.socket?.close(), this.socket = void 0;
|
|
30
|
+
}
|
|
31
|
+
handleMessage(t) {
|
|
32
|
+
const r = JSON.parse(String(t.data)), o = this.pending.get(r.id);
|
|
33
|
+
if (o) {
|
|
34
|
+
if (this.pending.delete(r.id), !r.ok) {
|
|
35
|
+
o.reject(new Error(r.error || "Apple relay request failed"));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!r.response) {
|
|
39
|
+
o.reject(new Error("Apple relay response was empty."));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
o.resolve(r.response);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
rejectPending(t) {
|
|
46
|
+
for (const r of this.pending.values())
|
|
47
|
+
r.reject(t);
|
|
48
|
+
this.pending.clear();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function b(e, t, r) {
|
|
52
|
+
const o = new g(e, t, r);
|
|
53
|
+
return await o.connect(), o;
|
|
54
|
+
}
|
|
55
|
+
async function A(e, t) {
|
|
56
|
+
return e.request("srpInit", t);
|
|
57
|
+
}
|
|
58
|
+
async function P(e, t) {
|
|
59
|
+
return e.request("srpComplete", t);
|
|
60
|
+
}
|
|
61
|
+
async function S(e) {
|
|
62
|
+
return e.request("triggerTrustedDevice2FA");
|
|
63
|
+
}
|
|
64
|
+
async function k(e, t, r = "sms") {
|
|
65
|
+
return e.request("triggerPhone2FA", { phoneNumberId: t, mode: r });
|
|
66
|
+
}
|
|
67
|
+
async function T(e, t) {
|
|
68
|
+
return e.request("submitTrustedDevice2FA", { code: t });
|
|
69
|
+
}
|
|
70
|
+
async function v(e, t, r, o = "sms") {
|
|
71
|
+
return e.request("submitPhone2FA", { phoneNumberId: t, mode: o, code: r });
|
|
72
|
+
}
|
|
73
|
+
async function E(e) {
|
|
74
|
+
return e.request("finalize");
|
|
75
|
+
}
|
|
76
|
+
async function W(e, t) {
|
|
77
|
+
return e.request("provisioning", t);
|
|
78
|
+
}
|
|
79
|
+
function N(e) {
|
|
80
|
+
if (e.body !== void 0 || !e.rawBody)
|
|
81
|
+
return e;
|
|
82
|
+
try {
|
|
83
|
+
return {
|
|
84
|
+
...e,
|
|
85
|
+
body: JSON.parse(e.rawBody)
|
|
86
|
+
};
|
|
87
|
+
} catch {
|
|
88
|
+
return e;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function R(e, t, r) {
|
|
92
|
+
const o = new URL(e);
|
|
93
|
+
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
|
+
}
|
|
95
|
+
async function M({
|
|
96
|
+
registryApiUrl: e,
|
|
97
|
+
accountName: t,
|
|
98
|
+
password: r,
|
|
99
|
+
token: o,
|
|
100
|
+
organizationId: c
|
|
101
|
+
}) {
|
|
102
|
+
const n = await b(e, o, c);
|
|
103
|
+
try {
|
|
104
|
+
const p = new m(t), i = await A(n, await p.init());
|
|
105
|
+
if (i.status < 200 || i.status >= 300)
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Apple SRP init failed: HTTP ${i.status} ${i.rawBody ?? ""}`.trim()
|
|
108
|
+
);
|
|
109
|
+
if (!i.body)
|
|
110
|
+
throw new Error("Apple SRP init response did not include a body.");
|
|
111
|
+
const h = await p.complete(r, i.body), u = await P(n, {
|
|
112
|
+
...h,
|
|
113
|
+
rememberMe: !1,
|
|
114
|
+
trustTokens: []
|
|
115
|
+
}), y = u.status === 409;
|
|
116
|
+
let s, l = { type: "trustedDevice" };
|
|
117
|
+
if (y) {
|
|
118
|
+
s = await S(n);
|
|
119
|
+
const a = q(s.body);
|
|
120
|
+
if (s.status === 412) {
|
|
121
|
+
if (!a)
|
|
122
|
+
throw new Error("Apple requested phone verification but did not include a trusted phone number.");
|
|
123
|
+
l = {
|
|
124
|
+
type: "phone",
|
|
125
|
+
phoneNumberId: a.id,
|
|
126
|
+
mode: a.pushMode ?? "sms"
|
|
127
|
+
}, s = await k(n, a.id, a.pushMode ?? "sms");
|
|
128
|
+
}
|
|
129
|
+
if (s.status < 200 || s.status >= 300)
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Apple two-factor challenge failed: HTTP ${s.status} ${s.rawBody ?? ""}`.trim()
|
|
132
|
+
);
|
|
133
|
+
} else if (u.status < 200 || u.status >= 300)
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Apple SRP complete failed: HTTP ${u.status} ${u.rawBody ?? ""}`.trim()
|
|
136
|
+
);
|
|
137
|
+
return {
|
|
138
|
+
relay: n,
|
|
139
|
+
completeResponse: u,
|
|
140
|
+
twoFactorChallengeResponse: s,
|
|
141
|
+
requiresTwoFactor: y,
|
|
142
|
+
finishTwoFactor: async (a) => {
|
|
143
|
+
const d = l.type === "phone" ? await v(
|
|
144
|
+
n,
|
|
145
|
+
l.phoneNumberId,
|
|
146
|
+
a,
|
|
147
|
+
l.mode
|
|
148
|
+
) : await T(n, a);
|
|
149
|
+
if (d.status < 200 || d.status >= 300)
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Apple two-factor code failed: HTTP ${d.status} ${d.rawBody ?? ""}`.trim()
|
|
152
|
+
);
|
|
153
|
+
return d;
|
|
154
|
+
},
|
|
155
|
+
finalize: async () => E(n),
|
|
156
|
+
close: async () => n.close()
|
|
157
|
+
};
|
|
158
|
+
} catch (p) {
|
|
159
|
+
throw n.close(), p;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function q(e) {
|
|
163
|
+
if (!f(e)) return;
|
|
164
|
+
const t = f(e.phoneNumberVerification) ? e.phoneNumberVerification : void 0, r = w(t?.trustedPhoneNumber) ?? w(e.trustedPhoneNumber) ?? w(e.phoneNumber);
|
|
165
|
+
if (!r) return;
|
|
166
|
+
const o = r.id;
|
|
167
|
+
if (typeof o != "number") return;
|
|
168
|
+
const c = typeof r.pushMode == "string" ? r.pushMode : typeof e.mode == "string" ? e.mode : void 0;
|
|
169
|
+
return { id: o, pushMode: c };
|
|
170
|
+
}
|
|
171
|
+
function w(e) {
|
|
172
|
+
return f(e) ? e : void 0;
|
|
173
|
+
}
|
|
174
|
+
function f(e) {
|
|
175
|
+
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
g as A,
|
|
179
|
+
v as a,
|
|
180
|
+
P as b,
|
|
181
|
+
A as c,
|
|
182
|
+
T as d,
|
|
183
|
+
S as e,
|
|
184
|
+
E as f,
|
|
185
|
+
b as o,
|
|
186
|
+
W as p,
|
|
187
|
+
M as s,
|
|
188
|
+
k as t
|
|
189
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { AppleRelayResponse } from './relay';
|
|
1
|
+
import { AppleRelayWebSocketClient, AppleRelayResponse } from './relay';
|
|
2
2
|
export type AppleIDLoginInput = {
|
|
3
|
-
|
|
3
|
+
registryApiUrl: string;
|
|
4
4
|
accountName: string;
|
|
5
5
|
password: string;
|
|
6
6
|
token?: string;
|
|
7
|
+
organizationId?: string;
|
|
7
8
|
};
|
|
8
9
|
export type AppleIDLoginResult = {
|
|
9
|
-
|
|
10
|
+
relay: AppleRelayWebSocketClient;
|
|
10
11
|
completeResponse: AppleRelayResponse;
|
|
11
12
|
twoFactorChallengeResponse?: AppleRelayResponse;
|
|
12
13
|
requiresTwoFactor: boolean;
|
|
@@ -14,4 +15,4 @@ export type AppleIDLoginResult = {
|
|
|
14
15
|
finalize: () => Promise<AppleRelayResponse>;
|
|
15
16
|
close: () => Promise<void>;
|
|
16
17
|
};
|
|
17
|
-
export declare function startBrowserOwnedAppleIDLogin({
|
|
18
|
+
export declare function startBrowserOwnedAppleIDLogin({ registryApiUrl, accountName, password, token, organizationId, }: AppleIDLoginInput): Promise<AppleIDLoginResult>;
|
|
@@ -12,18 +12,29 @@ export type AppleProvisioningRequest = {
|
|
|
12
12
|
path: string;
|
|
13
13
|
payload?: unknown;
|
|
14
14
|
};
|
|
15
|
-
export declare
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
export declare class AppleRelayWebSocketClient {
|
|
16
|
+
private readonly apiUrl;
|
|
17
|
+
private readonly token?;
|
|
18
|
+
private readonly organizationId?;
|
|
19
|
+
private socket?;
|
|
20
|
+
private nextId;
|
|
21
|
+
private readonly pending;
|
|
22
|
+
constructor(apiUrl: string, token?: string | undefined, organizationId?: string | undefined);
|
|
23
|
+
connect(): Promise<void>;
|
|
24
|
+
request<T = unknown>(type: string, payload?: unknown): Promise<AppleRelayResponse<T>>;
|
|
25
|
+
close(): void;
|
|
26
|
+
private handleMessage;
|
|
27
|
+
private rejectPending;
|
|
28
|
+
}
|
|
29
|
+
export declare function openAppleRelayWebSocket(apiUrl: string, token?: string, organizationId?: string): Promise<AppleRelayWebSocketClient>;
|
|
30
|
+
export declare function proxySrpInit(relay: AppleRelayWebSocketClient, payload: AppleSRPInitRequest): Promise<AppleRelayResponse<AppleSRPInitResponse>>;
|
|
31
|
+
export declare function proxySrpComplete(relay: AppleRelayWebSocketClient, payload: AppleSRPCompleteProof & {
|
|
21
32
|
rememberMe: boolean;
|
|
22
33
|
trustTokens: string[];
|
|
23
|
-
}
|
|
24
|
-
export declare function triggerTrustedDeviceTwoFactor(
|
|
25
|
-
export declare function triggerPhoneTwoFactor(
|
|
26
|
-
export declare function proxyTwoFactorCode(
|
|
27
|
-
export declare function proxyPhoneTwoFactorCode(
|
|
28
|
-
export declare function fetchAppleAccountSession(
|
|
29
|
-
export declare function proxyProvisioningRequest<T = unknown>(
|
|
34
|
+
}): Promise<AppleRelayResponse<unknown>>;
|
|
35
|
+
export declare function triggerTrustedDeviceTwoFactor(relay: AppleRelayWebSocketClient): Promise<AppleRelayResponse<unknown>>;
|
|
36
|
+
export declare function triggerPhoneTwoFactor(relay: AppleRelayWebSocketClient, phoneNumberId: number, mode?: string): Promise<AppleRelayResponse<unknown>>;
|
|
37
|
+
export declare function proxyTwoFactorCode(relay: AppleRelayWebSocketClient, code: string): Promise<AppleRelayResponse<unknown>>;
|
|
38
|
+
export declare function proxyPhoneTwoFactorCode(relay: AppleRelayWebSocketClient, phoneNumberId: number, code: string, mode?: string): Promise<AppleRelayResponse<unknown>>;
|
|
39
|
+
export declare function fetchAppleAccountSession(relay: AppleRelayWebSocketClient): Promise<AppleRelayResponse<unknown>>;
|
|
40
|
+
export declare function proxyProvisioningRequest<T = unknown>(relay: AppleRelayWebSocketClient, request: AppleProvisioningRequest): Promise<AppleRelayResponse<T>>;
|
|
@@ -12,6 +12,7 @@ export type StartSignedDeviceBuildOptions = {
|
|
|
12
12
|
certificateP12Base64: string;
|
|
13
13
|
certificatePassword?: string;
|
|
14
14
|
provisioningProfileBase64: string;
|
|
15
|
+
signedUploadUrl?: string;
|
|
15
16
|
};
|
|
16
17
|
export type BuildLogEventsOptions = {
|
|
17
18
|
limbuildApiUrl: string;
|
|
@@ -35,7 +36,7 @@ export type GetIOSOTAInstallOptions = {
|
|
|
35
36
|
token?: string;
|
|
36
37
|
};
|
|
37
38
|
export declare function fetchLimbuildInfo(limbuildApiUrl: string, token?: string): Promise<LimbuildInfo>;
|
|
38
|
-
export declare function startSignedDeviceBuild({ limbuildApiUrl, token, certificateP12Base64, certificatePassword, provisioningProfileBase64, }: StartSignedDeviceBuildOptions): Promise<{
|
|
39
|
+
export declare function startSignedDeviceBuild({ limbuildApiUrl, token, certificateP12Base64, certificatePassword, provisioningProfileBase64, signedUploadUrl, }: StartSignedDeviceBuildOptions): Promise<{
|
|
39
40
|
execId?: string;
|
|
40
41
|
}>;
|
|
41
42
|
export declare function getIOSOTAInstall({ limbuildApiUrl, execId, token }: GetIOSOTAInstallOptions): Promise<IOSOTAInstall>;
|
|
@@ -13,20 +13,35 @@ export type RequestUSBAccessOptions = {
|
|
|
13
13
|
log: DeviceInstallLog;
|
|
14
14
|
};
|
|
15
15
|
export type StartPairingRelayOptions = {
|
|
16
|
-
|
|
16
|
+
registryApiUrl: string;
|
|
17
17
|
token?: string;
|
|
18
|
+
organizationId?: string;
|
|
18
19
|
log: DeviceInstallLog;
|
|
19
20
|
target: DeviceRelayTarget;
|
|
20
21
|
};
|
|
22
|
+
export type InstallSource = {
|
|
23
|
+
assetId: string;
|
|
24
|
+
assetName?: never;
|
|
25
|
+
downloadUrl?: never;
|
|
26
|
+
} | {
|
|
27
|
+
assetId?: never;
|
|
28
|
+
assetName: string;
|
|
29
|
+
downloadUrl?: never;
|
|
30
|
+
} | {
|
|
31
|
+
assetId?: never;
|
|
32
|
+
assetName?: never;
|
|
33
|
+
downloadUrl: string;
|
|
34
|
+
};
|
|
21
35
|
export type StartInstallRelayOptions = StartPairingRelayOptions & {
|
|
22
36
|
pairRecord: PairRecordPayload;
|
|
37
|
+
installSource: InstallSource;
|
|
23
38
|
};
|
|
24
39
|
export declare function requestUSBAccess({ log }: RequestUSBAccessOptions): Promise<DeviceRelayTarget>;
|
|
25
|
-
export declare function startPairingRelay({
|
|
40
|
+
export declare function startPairingRelay({ registryApiUrl, token, organizationId, log, target }: StartPairingRelayOptions): Promise<{
|
|
26
41
|
relay: RelayClient;
|
|
27
42
|
pairRecord: PairRecordPayload;
|
|
28
43
|
target: DeviceRelayTarget;
|
|
29
44
|
}>;
|
|
30
|
-
export declare function startInstallRelay({
|
|
45
|
+
export declare function startInstallRelay({ registryApiUrl, token, organizationId, log, target, pairRecord, installSource, }: StartInstallRelayOptions): Promise<RelayClient>;
|
|
31
46
|
export declare function closeDeviceRelayTarget(target: DeviceRelayTarget | undefined, log?: DeviceInstallLog): Promise<void>;
|
|
32
|
-
export declare function deviceRelayWebSocketUrl(
|
|
47
|
+
export declare function deviceRelayWebSocketUrl(registryApiUrl: string, token?: string, organizationId?: string): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DeviceHello, DeviceInstallLog, PairRecordPayload } from '../types';
|
|
2
|
+
import { InstallSource } from './operations';
|
|
2
3
|
import { UsbmuxSession } from './usbmux';
|
|
3
4
|
export declare class RelayClient {
|
|
4
5
|
private readonly webSocketUrl;
|
|
@@ -13,7 +14,7 @@ export declare class RelayClient {
|
|
|
13
14
|
constructor(webSocketUrl: string, session: UsbmuxSession, deviceHello: DeviceHello, log: DeviceInstallLog);
|
|
14
15
|
connect(): Promise<void>;
|
|
15
16
|
startPairing(): Promise<PairRecordPayload>;
|
|
16
|
-
startInstall(pairRecord: PairRecordPayload): Promise<void>;
|
|
17
|
+
startInstall(pairRecord: PairRecordPayload, installSource: InstallSource): Promise<void>;
|
|
17
18
|
close(): void;
|
|
18
19
|
private enqueueFrame;
|
|
19
20
|
private handleFrame;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../limbuild-client-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../limbuild-client-CVDwq54z.js");require("../index-CMeQfhYy.js");const c=require("../provisioning-Va0PH4Kk.js"),i=require("../browser-storage-jJaIht4K.js");async function v({certificateFile:t,provisioningProfileFile:e,certificatePassword:n,bundleId:s,deviceUDID:r,teamId:d,signingMode:f="development",certificateId:p}){const[u,A,o]=await Promise.all([l(t),l(e),i.parseProvisioningProfile(e)]);return g({profile:o,bundleId:s,deviceUDID:r,signingMode:f}),i.putSigningAssets({bundleID:s??o.bundleID??o.applicationIdentifier??e.name,deviceUDID:r,teamID:d??o.teamID,signingMode:f,certificateID:p,certificateP12Base64:u,certificateFileName:t.name,certificatePassword:n||void 0,provisioningProfileBase64:A,profileFileName:e.name,profile:o})}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 r of s)n+=String.fromCharCode(r);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,4 +1,4 @@
|
|
|
1
|
-
import { f as b, g as B, s as D, w as y } from "../limbuild-client-
|
|
1
|
+
import { f as b, g as B, s as D, w as y } from "../limbuild-client-BagK_FWE.mjs";
|
|
2
2
|
import "../index-DFdCvi2_.mjs";
|
|
3
3
|
import { o as C, p as E } from "../provisioning-DKbkBO-p.mjs";
|
|
4
4
|
import { p as d, a as m, b as u, c as A } from "../browser-storage-Cx9eW-bm.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),v=require("../limbuild-client-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),v=require("../limbuild-client-CVDwq54z.js");require("../index-CMeQfhYy.js");function P({apiUrl:e,token:n,signingAssets:g,loadOTAInstall:I=!1}){const[w,c]=t.useState("idle"),[B,u]=t.useState([]),[h,a]=t.useState(),[x,l]=t.useState(),[E,o]=t.useState(),i=t.useRef(void 0);t.useEffect(()=>()=>{i.current?.(),i.current=void 0},[]);const m=t.useCallback(()=>{i.current?.(),i.current=void 0,c("idle"),u([]),a(void 0),l(void 0),o(void 0)},[]),q=t.useCallback(async(S={})=>{if(!e)throw new Error("apiUrl is required to start a device build.");const d=S.signingAssets??g;if(!d)throw new Error("Signing assets are required to start a device build.");i.current?.(),c("queued"),u([]),a(void 0),l(void 0),o(void 0);try{const r=await v.startSignedDeviceBuild({limbuildApiUrl:e,token:n,certificateP12Base64:d.certificateP12Base64,certificatePassword:d.certificatePassword,provisioningProfileBase64:d.provisioningProfileBase64,signedUploadUrl:S.signedUploadUrl});if(!r.execId)throw new Error("Build request did not return an exec ID.");return a(r.execId),i.current=v.watchBuildLogEvents({limbuildApiUrl:e,token:n,execId:r.execId,onLine:s=>u(f=>[...f,s]),onStatus:s=>{c(s),s==="succeeded"&&I&&v.getIOSOTAInstall({limbuildApiUrl:e,token:n,execId:r.execId}).then(l).catch(f=>o(b(f)))},onError:s=>{c("failed"),o(s.message)}}),r.execId}catch(r){c("failed"),o(b(r));return}},[e,I,g,n]);return{status:w,logs:B,execId:h,otaInstall:x,error:E,startBuild:q,reset:m}}function b(e){return e instanceof Error?e.message:String(e)}exports.useDeviceBuild=P;
|
|
@@ -1,68 +1,69 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
import { s as q, w as
|
|
1
|
+
import { useState as c, useRef as P, useEffect as A, useCallback as w } from "react";
|
|
2
|
+
import { s as q, w as U, g as D } from "../limbuild-client-BagK_FWE.mjs";
|
|
3
3
|
import "../index-DFdCvi2_.mjs";
|
|
4
|
-
function
|
|
4
|
+
function R({
|
|
5
5
|
apiUrl: e,
|
|
6
|
-
token:
|
|
7
|
-
signingAssets:
|
|
8
|
-
loadOTAInstall:
|
|
6
|
+
token: d,
|
|
7
|
+
signingAssets: g,
|
|
8
|
+
loadOTAInstall: v = !1
|
|
9
9
|
}) {
|
|
10
|
-
const [
|
|
10
|
+
const [x, s] = c("idle"), [h, a] = c([]), [B, u] = c(), [E, l] = c(), [p, o] = c(), r = P(void 0);
|
|
11
11
|
A(() => () => {
|
|
12
12
|
r.current?.(), r.current = void 0;
|
|
13
13
|
}, []);
|
|
14
|
-
const
|
|
15
|
-
r.current?.(), r.current = void 0, s("idle"), a([]), u(void 0), l(void 0),
|
|
16
|
-
}, []),
|
|
17
|
-
async (
|
|
14
|
+
const S = w(() => {
|
|
15
|
+
r.current?.(), r.current = void 0, s("idle"), a([]), u(void 0), l(void 0), o(void 0);
|
|
16
|
+
}, []), b = w(
|
|
17
|
+
async (I = {}) => {
|
|
18
18
|
if (!e)
|
|
19
19
|
throw new Error("apiUrl is required to start a device build.");
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
20
|
+
const n = I.signingAssets ?? g;
|
|
21
|
+
if (!n)
|
|
22
22
|
throw new Error("Signing assets are required to start a device build.");
|
|
23
|
-
r.current?.(), s("queued"), a([]), u(void 0), l(void 0),
|
|
23
|
+
r.current?.(), s("queued"), a([]), u(void 0), l(void 0), o(void 0);
|
|
24
24
|
try {
|
|
25
25
|
const t = await q({
|
|
26
26
|
limbuildApiUrl: e,
|
|
27
|
-
token:
|
|
28
|
-
certificateP12Base64:
|
|
29
|
-
certificatePassword:
|
|
30
|
-
provisioningProfileBase64:
|
|
27
|
+
token: d,
|
|
28
|
+
certificateP12Base64: n.certificateP12Base64,
|
|
29
|
+
certificatePassword: n.certificatePassword,
|
|
30
|
+
provisioningProfileBase64: n.provisioningProfileBase64,
|
|
31
|
+
signedUploadUrl: I.signedUploadUrl
|
|
31
32
|
});
|
|
32
33
|
if (!t.execId)
|
|
33
34
|
throw new Error("Build request did not return an exec ID.");
|
|
34
|
-
return u(t.execId), r.current =
|
|
35
|
+
return u(t.execId), r.current = U({
|
|
35
36
|
limbuildApiUrl: e,
|
|
36
|
-
token:
|
|
37
|
+
token: d,
|
|
37
38
|
execId: t.execId,
|
|
38
39
|
onLine: (i) => a((f) => [...f, i]),
|
|
39
40
|
onStatus: (i) => {
|
|
40
|
-
s(i), i === "succeeded" &&
|
|
41
|
+
s(i), i === "succeeded" && v && D({ limbuildApiUrl: e, token: d, execId: t.execId }).then(l).catch((f) => o(m(f)));
|
|
41
42
|
},
|
|
42
43
|
onError: (i) => {
|
|
43
|
-
s("failed"),
|
|
44
|
+
s("failed"), o(i.message);
|
|
44
45
|
}
|
|
45
46
|
}), t.execId;
|
|
46
47
|
} catch (t) {
|
|
47
|
-
s("failed"),
|
|
48
|
+
s("failed"), o(m(t));
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
50
51
|
},
|
|
51
|
-
[e,
|
|
52
|
+
[e, v, g, d]
|
|
52
53
|
);
|
|
53
54
|
return {
|
|
54
|
-
status:
|
|
55
|
-
logs:
|
|
56
|
-
execId:
|
|
57
|
-
otaInstall:
|
|
58
|
-
error:
|
|
59
|
-
startBuild:
|
|
60
|
-
reset:
|
|
55
|
+
status: x,
|
|
56
|
+
logs: h,
|
|
57
|
+
execId: B,
|
|
58
|
+
otaInstall: E,
|
|
59
|
+
error: p,
|
|
60
|
+
startBuild: b,
|
|
61
|
+
reset: S
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
|
-
function
|
|
64
|
+
function m(e) {
|
|
64
65
|
return e instanceof Error ? e.message : String(e);
|
|
65
66
|
}
|
|
66
67
|
export {
|
|
67
|
-
|
|
68
|
+
R as useDeviceBuild
|
|
68
69
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("../browser-storage-jJaIht4K.js"),E=1,u=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 T(e){const t=new Uint8Array(u+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,u),t}function W(e){if(e.byteLength<u)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!==u+n)throw new Error(`Relay frame length mismatch: got ${e.byteLength}, expected ${u+n}`);return{type:t.getUint8(1),requestId:t.getUint32(4),streamId:t.getUint32(8),payload:e.slice(u)}}function c(e){return new TextEncoder().encode(JSON.stringify(e))}function y(e){return JSON.parse(new TextDecoder().decode(e))}async function B(){if(!navigator.usb)throw new Error("WebUSB is not available in this browser.");return navigator.usb.requestDevice({filters:[{vendorId:1452}]})}function F(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 M(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 I(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 j(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,H=2,P=6,J=4277009102,h=2,z=4,l=16,G=49152;async function Q(e,t){const{inEndpoint:r,outEndpoint:n}=M(t),a=new Uint8Array(12),i=new DataView(a.buffer);i.setUint32(0,2),i.setUint32(4,0),i.setUint32(8,0),await I(e,n,q(k,a));const o=await D(e,r,1),d=new DataView(o.payload.buffer,o.payload.byteOffset).getUint32(0),w={device:e,candidate:t,inEndpoint:r,outEndpoint:n,muxVersion:d,txSeq:0,rxSeq:65535,nextSport:G,streams:new Map,writeChain:Promise.resolve(),closed:!1};return d>=2&&await O(w,H,new Uint8Array([7])),Z(w),w}async function Y(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 p(a,h,new Uint8Array),await a.opened,a}async function K(e,t){if(e.session.closed)throw new Error("usbmux session is closed.");await p(e,l,t),e.seq+=t.byteLength}async function X(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 p(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?ee(t,r,e.txSeq++,e.rxSeq):q(t,r);await I(e.device,e.outEndpoint,n)}),e.writeChain}async function Z(e){try{for(;;){if(e.closed)return;const t=await D(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=re(t.payload),n=e.streams.get(m(r.sport,r.dport));if(n){if(r.flags&z){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&(h|l))===(h|l)){n.seq+=1,n.ack=r.seq+1,await p(n,l,new Uint8Array),n.resolveOpened();continue}r.payload.byteLength!==0&&(n.ack=r.seq+r.payload.byteLength,await p(n,l,new Uint8Array),n.waiters.length>0?n.waiters.shift()(r.payload):n.queue.push(r.payload))}}}catch{e.closed||x(e)}}async function D(e,t,r){for(;;){const n=await j(e,t),a=te(n,r);if(!(r===1&&a.protocol!==k))return a}}function q(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 ee(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,J),i.setUint16(12,r),i.setUint16(14,n),a.set(t,16),a}function te(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 re(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:c(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:c({})}),this.log("Pairing requested"),t}async startInstall(t){await this.send({type:s.StartInstall,requestId:0,streamId:0,payload:c(t)}),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 K(r,t.payload);break}case s.StreamClose:this.streams.delete(t.streamId);break;case s.InstallProgress:this.log(ae(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=ne(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 Y(this.session,n);this.streams.set(r,a),await this.send({type:s.OpenResult,requestId:t,streamId:r,payload:c({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:c({ok:!1,error:a instanceof Error?a.message:String(a)})})}}async pumpDeviceToServer(t,r){try{for(;;){const n=await X(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:c({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(T(t))}}}function ne(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 ae(e){const t="install status: ";if(!e.startsWith(t))return e;const r=e.slice(t.length),n=f(r,"Error");if(n){const o=f(r,"ErrorDescription");return`Install error: ${n}${o?` — ${o}`:""}`}const a=f(r,"Status")??"Unknown",i=f(r,"PercentComplete");return`Install progress: ${i?`${i}% `:""}${a}`}function f(e,t){const n=new RegExp(`<key>\\s*${ie(t)}\\s*</key>\\s*<(?:string|integer|real)>([\\s\\S]*?)</(?:string|integer|real)>`).exec(e);return n?oe(n[1].trim()):void 0}function ie(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function oe(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}async function se({log:e}){e("Selecting USB device");const t=await B(),r=ue(t);return e("Selected USB device",`${t.manufacturerName??""} ${t.productName??""} ${t.serialNumber??""}`.trim()),r}async function N({limbuildApiUrl:e,token:t,log:r,target:n}){const a=U(e,t);let i;try{i=await C(a,n,r);const o=await i.startPairing();return{relay:i,pairRecord:o,target:n}}catch(o){throw i?.close(),o}}async function V({limbuildApiUrl:e,token:t,log:r,target:n,pairRecord:a}){const i=U(e,t);let o;try{return o=await C(i,n,r),await o.startInstall(a),o}catch(d){throw o?.close(),d}}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",g(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",g(r))}}}async function C(e,t,r){await ce(t,r);const n=new $(e,t.session,t.hello,r);return await n.connect(),n}async function ce(e,t){if(!e.session)try{e.candidate=await le(e,t),e.session=await Q(e.device,e.candidate),t("Created usbmux session")}catch(r){throw await A(e,t),r}}function ue(e){return{device:e,candidate:de(e),hello:{serialNumber:e.serialNumber,productName:e.productName,manufacturerName:e.manufacturerName,productId:e.productId,vendorId:e.vendorId}}}async function le(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 _(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}: ${g(o)}`),await fe(e),await pe(250)}throw n instanceof Error?n:new Error("Unable to claim any Apple usbmux interface.")}function de(e){const t=L(e)[0];if(!t)throw new Error("No Apple usbmux interface found.");return t}function L(e){const t=F(e),r=e.configuration?.configurationValue;return[...t.filter(n=>n.configurationValue===r),...t.filter(n=>n.configurationValue!==r)]}function U(e,t){const r=new URL(e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",r.pathname=`${r.pathname.replace(/\/$/,"")}/device/ws`,t&&r.searchParams.set("token",t),r.toString()}function g(e){return e instanceof Error?e.message:String(e)}async function fe(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 pe(e){return new Promise(t=>setTimeout(t,e))}async function we(e={}){return se({log:e.log??S})}async function ye(e){return N({...e,log:e.log??S})}async function he(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=we;exports.startDeviceInstall=he;exports.startDeviceInstallRelay=V;exports.startDevicePairingRelay=N;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("../browser-storage-jJaIht4K.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,h=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,q(I,a));const o=await D(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(m(t,a.sport),a),await w(a,h,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):q(t,r);await k(e.device,e.outEndpoint,n)}),e.writeChain}async function ee(e){try{for(;;){if(e.closed)return;const t=await D(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(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&(h|f))===(h|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 D(e,t,r){for(;;){const n=await H(e,t),a=re(n,r);if(!(r===1&&a.protocol!==I))return a}}function q(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(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",g(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",g(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}: ${g(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()}function g(e){return e instanceof Error?e.message:String(e)}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,6 +1,6 @@
|
|
|
1
1
|
import { RequestUSBAccessOptions as CoreRequestUSBAccessOptions, StartInstallRelayOptions, StartPairingRelayOptions } from '../core/device-install/operations';
|
|
2
2
|
import { DeviceInstallLog } from '../core/device-install/types';
|
|
3
|
-
export { closeDeviceRelayTarget, deviceRelayWebSocketUrl, startInstallRelay as startDeviceInstallRelay, startPairingRelay as startDevicePairingRelay, type DeviceRelayTarget, type StartInstallRelayOptions, type StartPairingRelayOptions, } from '../core/device-install/operations';
|
|
3
|
+
export { closeDeviceRelayTarget, deviceRelayWebSocketUrl, startInstallRelay as startDeviceInstallRelay, startPairingRelay as startDevicePairingRelay, type DeviceRelayTarget, type InstallSource, type StartInstallRelayOptions, type StartPairingRelayOptions, } from '../core/device-install/operations';
|
|
4
4
|
export { getPairRecord, normalizeUDID, putPairRecord } from '../core/device-install/storage';
|
|
5
5
|
export type { DeviceHello, DeviceInstallLog, PairRecordPayload, StoredPairRecord, } from '../core/device-install/types';
|
|
6
6
|
export { RelayClient } from '../core/device-install/operations';
|