@limrun/ui 0.9.0-rc.5 → 0.9.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +9 -0
  2. package/dist/components/device-install/device-install-dialog.d.ts +5 -0
  3. package/dist/components/device-install/index.d.ts +2 -0
  4. package/dist/core/device-install/apple/client.d.ts +17 -0
  5. package/dist/core/device-install/apple/crypto.d.ts +20 -0
  6. package/dist/core/device-install/apple/gsa-srp.d.ts +26 -0
  7. package/dist/core/device-install/apple/index.d.ts +5 -0
  8. package/dist/core/device-install/apple/provisioning.d.ts +161 -0
  9. package/dist/core/device-install/apple/relay.d.ts +29 -0
  10. package/dist/core/device-install/index.d.ts +4 -0
  11. package/dist/core/device-install/operations/index.d.ts +6 -0
  12. package/dist/core/device-install/operations/limbuild-client.d.ts +28 -0
  13. package/dist/core/device-install/operations/operations.d.ts +32 -0
  14. package/dist/core/device-install/operations/relay-client.d.ts +25 -0
  15. package/dist/core/device-install/operations/relay-protocol.d.ts +27 -0
  16. package/dist/core/device-install/operations/usbmux.d.ts +32 -0
  17. package/dist/core/device-install/operations/webusb.d.ts +21 -0
  18. package/dist/core/device-install/storage/browser-storage.d.ts +44 -0
  19. package/dist/core/device-install/storage/index.d.ts +1 -0
  20. package/dist/core/device-install/types.d.ts +48 -0
  21. package/dist/device-install/index.cjs +1 -0
  22. package/dist/device-install/index.d.ts +3 -0
  23. package/dist/device-install/index.js +78 -0
  24. package/dist/device-install/react.cjs +1 -0
  25. package/dist/device-install/react.d.ts +1 -0
  26. package/dist/device-install/react.js +4 -0
  27. package/dist/device-install-dialog-86RDdoK9.js +2 -0
  28. package/dist/device-install-dialog-CnyDWf0q.mjs +462 -0
  29. package/dist/device-install-dialog.css +1 -0
  30. package/dist/hooks/index.d.ts +1 -0
  31. package/dist/hooks/use-device-install.d.ts +73 -0
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.js +495 -502
  35. package/dist/use-device-install-CbGVvwPp.js +31 -0
  36. package/dist/use-device-install-j1Gekpl4.mjs +13623 -0
  37. package/package.json +15 -2
  38. package/src/components/device-install/device-install-dialog.css +325 -0
  39. package/src/components/device-install/device-install-dialog.tsx +513 -0
  40. package/src/components/device-install/index.ts +2 -0
  41. package/src/core/device-install/apple/client.ts +152 -0
  42. package/src/core/device-install/apple/crypto.ts +202 -0
  43. package/src/core/device-install/apple/gsa-srp.ts +127 -0
  44. package/src/core/device-install/apple/index.ts +5 -0
  45. package/src/core/device-install/apple/provisioning.ts +298 -0
  46. package/src/core/device-install/apple/relay.ts +221 -0
  47. package/src/core/device-install/index.ts +4 -0
  48. package/src/core/device-install/operations/index.ts +6 -0
  49. package/src/core/device-install/operations/limbuild-client.ts +104 -0
  50. package/src/core/device-install/operations/operations.ts +217 -0
  51. package/src/core/device-install/operations/relay-client.ts +255 -0
  52. package/src/core/device-install/operations/relay-protocol.ts +71 -0
  53. package/src/core/device-install/operations/usbmux.ts +270 -0
  54. package/src/core/device-install/operations/webusb-dom.d.ts +54 -0
  55. package/src/core/device-install/operations/webusb.ts +105 -0
  56. package/src/core/device-install/storage/browser-storage.ts +263 -0
  57. package/src/core/device-install/storage/index.ts +1 -0
  58. package/src/core/device-install/types.ts +65 -0
  59. package/src/device-install/index.ts +3 -0
  60. package/src/device-install/react.ts +1 -0
  61. package/src/hooks/index.ts +1 -0
  62. package/src/hooks/use-device-install.ts +1210 -0
  63. package/src/index.ts +2 -0
  64. package/vite.config.ts +6 -2
@@ -0,0 +1,78 @@
1
+ import { A as a, O as t, N as i, R as n, P as r, a0 as o, L as l, Z as p, q as c, d, j as g, V as u, S as R, U as D, v as S, M as f, i as m, k as A, Q as v, T as P, e as y, D as C, F as I, f as q, b as B, c as x, a as T, ac as b, $ as h, g as w, a1 as E, a9 as L, aa as F, a6 as U, m as O, a8 as _, l as W, a5 as Y, a4 as k, W as z, af as G, ag as J, ah as M, ad as H, ae as K, C as N, E as V, x as Z, w as j, B as Q, p as X, a7 as $, ab as ee, Y as se, r as ae, _ as te, I as ie, o as ne, X as re, s as oe, K as le, J as pe, G as ce, n as de, h as ge, t as ue, a3 as Re, a2 as De, z as Se, y as fe, u as me, H as Ae } from "../use-device-install-j1Gekpl4.mjs";
2
+ import { D as Pe, D as ye } from "../device-install-dialog-CnyDWf0q.mjs";
3
+ export {
4
+ a as AppleGsaSrpClient,
5
+ Pe as DeviceInstallDialog,
6
+ ye as DeviceInstallRelay,
7
+ t as RELAY_HEADER_BYTES,
8
+ i as RELAY_PROTOCOL_VERSION,
9
+ n as RelayClient,
10
+ r as RelayMessageType,
11
+ o as claimUsbmux,
12
+ l as closeDeviceRelayTarget,
13
+ p as closeUsbmuxSession,
14
+ c as createAppleRelaySession,
15
+ d as createBundleIDRequest,
16
+ g as createDevelopmentProfileRequest,
17
+ u as createUsbmuxSession,
18
+ R as decodeFrame,
19
+ D as decodeJson,
20
+ S as deleteAppleRelaySession,
21
+ f as deviceRelayWebSocketUrl,
22
+ m as downloadCertificateRequest,
23
+ A as downloadProfileRequest,
24
+ v as encodeFrame,
25
+ P as encodeJson,
26
+ y as exportAppleCertificateP12,
27
+ C as fetchAppleAccountSession,
28
+ I as fetchLimbuildInfo,
29
+ q as findBundleIDRequest,
30
+ B as findDevelopmentCertificatesRequest,
31
+ x as findDevelopmentProfilesRequest,
32
+ T as findDeviceRequest,
33
+ b as findSigningAssetsForBundle,
34
+ h as findUsbmuxCandidates,
35
+ w as generateAppleSigningKeyAndCSR,
36
+ E as getBulkEndpoints,
37
+ L as getLatestSigningAssets,
38
+ F as getLatestSigningAssetsWithCertificate,
39
+ U as getPairRecord,
40
+ O as getReusableAppleSigningAssets,
41
+ _ as getSigningAssets,
42
+ W as listTeamsRequest,
43
+ Y as normalizeBundleID,
44
+ k as normalizeUDID,
45
+ z as openStream,
46
+ G as parseProvisioningProfile,
47
+ J as parseProvisioningProfileBase64,
48
+ M as parseProvisioningProfileBytes,
49
+ H as profileContainsDevice,
50
+ K as profileMatchesBundleID,
51
+ N as proxyPhoneTwoFactorCode,
52
+ V as proxyProvisioningRequest,
53
+ Z as proxySrpComplete,
54
+ j as proxySrpInit,
55
+ Q as proxyTwoFactorCode,
56
+ X as putAppleGeneratedSigningAssets,
57
+ $ as putPairRecord,
58
+ ee as putSigningAssets,
59
+ se as receiveStreamData,
60
+ ae as registerDeviceRequest,
61
+ te as requestAppleDevice,
62
+ ie as requestUSBAccess,
63
+ ne as selectDeveloperPortalTeam,
64
+ re as sendStreamData,
65
+ oe as startBrowserOwnedAppleIDLogin,
66
+ le as startInstallRelay,
67
+ pe as startPairingRelay,
68
+ ce as startSignedDeviceBuild,
69
+ de as storedSigningAssetsReusable,
70
+ ge as submitDevelopmentCSRRequest,
71
+ ue as teamIDCandidates,
72
+ Re as transferIn,
73
+ De as transferOutWithZlp,
74
+ Se as triggerPhoneTwoFactor,
75
+ fe as triggerTrustedDeviceTwoFactor,
76
+ me as useDeviceInstall,
77
+ Ae as watchBuildLogEvents
78
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../use-device-install-CbGVvwPp.js");exports.useDeviceInstall=e.useDeviceInstall;
@@ -0,0 +1 @@
1
+ export { useDeviceInstall } from '../hooks/use-device-install';
@@ -0,0 +1,4 @@
1
+ import { u as a } from "../use-device-install-j1Gekpl4.mjs";
2
+ export {
3
+ a as useDeviceInstall
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";require('./device-install-dialog.css');const e=require("react/jsx-runtime"),d=require("react"),w=require("./use-device-install-CbGVvwPp.js");function N(l){var t,a,n="";if(typeof l=="string"||typeof l=="number")n+=l;else if(typeof l=="object")if(Array.isArray(l)){var c=l.length;for(t=0;t<c;t++)l[t]&&(a=N(l[t]))&&(n&&(n+=" "),n+=a)}else for(a in l)l[a]&&(n&&(n+=" "),n+=a);return n}function u(){for(var l,t,a=0,n="",c=arguments.length;a<c;a++)(l=arguments[a])&&(t=N(l))&&(n&&(n+=" "),n+=t);return n}const P=[{id:"signing",title:"Prepare signing",description:"Choose Apple ID login or upload certificates, then confirm the target developer device."},{id:"connect",title:"Connect and pair",description:"Connect the iPhone with WebUSB, then pair this browser so installs can use the device."},{id:"build",title:"Check and build",description:"Verify the device and provisioning profile are ready, then start the signed build."},{id:"install",title:"Start installation",description:"Relay the last successful device build to the paired iPhone."}];function I({disabled:l,...t}){const[a,n]=d.useState(!1),[c,h]=d.useState("signing"),[o,j]=d.useState(),[m,S]=d.useState(""),[x,C]=d.useState(""),[_,A]=d.useState(""),f=d.useId(),i=w.useDeviceInstall(t);d.useEffect(()=>{h(i.currentStep)},[i.currentStep]);const y=(r,p)=>{i.setSigningFiles({[r]:p.currentTarget.files?.[0]})};return e.jsxs("div",{className:"lr-device-install",children:[e.jsx("button",{type:"button",className:"lr-device-install__trigger",disabled:l||!t.apiUrl,onClick:()=>n(!0),children:"Install to iPhone"}),a&&e.jsx("div",{className:"lr-device-install__backdrop",role:"presentation",children:e.jsxs("section",{"aria-labelledby":f,"aria-modal":"true",className:"lr-device-install__dialog",role:"dialog",children:[e.jsxs("header",{className:"lr-device-install__header",children:[e.jsxs("div",{children:[e.jsx("h2",{id:f,children:"Install to a real iPhone"}),e.jsx("p",{children:"Prepare signing, connect and pair the device, build, then install from this browser."})]}),e.jsx("button",{type:"button",className:"lr-device-install__icon-button",onClick:()=>n(!1),children:"Close"})]}),i.error&&e.jsx("div",{className:"lr-device-install__error",children:i.error}),e.jsx("div",{className:"lr-device-install__steps",children:P.map((r,p)=>e.jsxs(T,{index:p+1,step:r,active:i.currentStep===r.id,open:c===r.id,status:i.stepStatuses[r.id],onToggle:()=>h(r.id),children:[r.id==="signing"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[e.jsxs("div",{className:"lr-device-install__choice-grid",children:[e.jsxs("button",{type:"button",className:u("lr-device-install__choice",o==="apple-id"&&"lr-device-install__choice--active"),onClick:()=>j("apple-id"),children:[e.jsx("strong",{children:"Apple ID login"}),e.jsx("span",{children:"Sign in, choose team, bundle ID, devices, then generate signing assets."})]}),e.jsxs("button",{type:"button",className:u("lr-device-install__choice",o==="upload"&&"lr-device-install__choice--active"),onClick:()=>j("upload"),children:[e.jsx("strong",{children:"Upload certificates"}),e.jsx("span",{children:"Use an existing .p12 certificate and provisioning profile."})]})]}),o==="apple-id"&&e.jsxs("div",{className:"lr-device-install__section-panel",children:[e.jsxs("div",{className:"lr-device-install__grid",children:[e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Apple ID"}),e.jsx("input",{type:"email",autoComplete:"username",placeholder:"name@example.com",value:m,onChange:s=>S(s.currentTarget.value)})]}),e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Apple ID password"}),e.jsx("input",{type:"password",autoComplete:"current-password",placeholder:"Password stays in this browser",value:x,onChange:s=>C(s.currentTarget.value)})]}),!i.hasReusableAppleCertificate&&e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Generated .p12 password"}),e.jsx("input",{type:"password",placeholder:"Used when exporting Apple certificate",onChange:s=>i.setSigningFiles({certificatePassword:s.currentTarget.value})})]})]}),e.jsxs("div",{className:"lr-device-install__actions",children:[e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:l||!t.apiUrl||!m||!x||i.busyAction==="signing",onClick:()=>void i.startAppleIDLogin({accountName:m,password:x}),children:i.appleSigningStatus==="authenticating"?"Signing in...":"Sign in with Apple ID"}),e.jsxs("span",{className:"lr-device-install__hint",children:["Apple password is used only by browser-side SRP. Status: ",i.appleSigningStatus]})]}),i.appleSigningStatus==="two-factor-required"&&e.jsxs("div",{className:"lr-device-install__grid",children:[e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Two-factor code"}),e.jsx("input",{type:"text",inputMode:"numeric",autoComplete:"one-time-code",value:_,onChange:s=>A(s.currentTarget.value)})]}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:!_||i.busyAction==="signing",onClick:()=>void i.submitAppleTwoFactorCode(_),children:"Submit Apple ID code"})]}),i.appleTeams.length>0&&e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Apple Developer team"}),e.jsx("select",{value:i.selectedAppleTeamID??"",onChange:s=>i.setSelectedAppleTeamID(s.currentTarget.value||void 0),children:i.appleTeams.map((s,b)=>{const v=s.teamId??(s.providerId===void 0?void 0:String(s.providerId))??s.publicProviderId??"";return e.jsxs("option",{value:v,children:[s.name??"Apple Developer Team"," ",v?`(${v})`:""]},`${v}-${b}`)})})]}),i.appleDevices.length>0&&e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Apple Developer devices"}),e.jsx("select",{multiple:!0,value:i.selectedAppleDeviceIDs,onChange:s=>i.setSelectedAppleDeviceIDs(Array.from(s.currentTarget.selectedOptions).map(b=>b.value)),children:i.appleDevices.map(s=>e.jsxs("option",{value:s.deviceId??"",children:[s.name??s.model??"Apple device"," ",s.deviceNumber??""]},s.deviceId??s.deviceNumber))})]}),i.applePortalSummary&&e.jsxs("p",{className:"lr-device-install__hint",children:["Found ",i.applePortalSummary.certificateCount," certificates and"," ",i.applePortalSummary.profileCount," provisioning profiles."]}),i.hasReusableAppleCertificate&&e.jsx("p",{className:"lr-device-install__hint",children:"Reusing the certificate and private key stored in this browser."}),e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:l||!i.canPrepareAppleSigningAssets,onClick:()=>void i.prepareAppleSigningAssets(),children:i.appleSigningStatus==="preparing-assets"?"Preparing signing assets...":"Generate certificate and profile"})]}),o==="upload"&&e.jsxs("div",{className:"lr-device-install__section-panel",children:[e.jsxs("div",{className:"lr-device-install__grid",children:[e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Certificate (.p12)"}),e.jsx("input",{type:"file",accept:".p12,application/x-pkcs12",onChange:s=>y("certificateFile",s)})]}),e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Provisioning profile"}),e.jsx("input",{type:"file",accept:".mobileprovision",onChange:s=>y("provisioningProfileFile",s)})]}),e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Uploaded .p12 password"}),e.jsx("input",{type:"password",placeholder:"Export password",onChange:s=>i.setSigningFiles({certificatePassword:s.currentTarget.value})})]})]}),e.jsx("p",{className:"lr-device-install__hint",children:"The provisioning profile will be checked against the connected iPhone before the build starts."})]}),i.hasSigningAssets&&e.jsx("p",{children:"Signing assets are stored in this browser for the selected bundle and device."})]}),r.id==="connect"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[e.jsx("p",{children:"WebUSB works in Chromium browsers on secure origins. Connect the iPhone over USB, approve the browser permission prompt, then pair this browser."}),e.jsxs("div",{className:"lr-device-install__actions",children:[e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:l||!i.canRequestUSBAccess,onClick:()=>void i.requestUSBAccess(),children:i.busyAction==="usb"?"Selecting iPhone...":"Allow USB access"}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:l||!i.canPairBrowser,onClick:()=>void i.pairBrowser(),children:i.busyAction==="pair"?"Pairing...":i.pairConfirmationRequired?"Confirm pair record":"Pair browser"})]}),i.device&&e.jsx("div",{className:"lr-device-install__device",children:`${i.device.productName??"iPhone"} ${i.device.serialNumber??""}`.trim()}),i.pairConfirmationRequired&&e.jsxs("p",{children:["Unlock the iPhone and tap ",e.jsx("strong",{children:"Trust"})," in the system dialog, then confirm the pair record."]}),e.jsx("p",{children:i.hasPairRecord?"Pair record is stored locally. Continue to the build check.":"Pair this browser once before building and installing."})]}),r.id==="build"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[e.jsxs("div",{className:"lr-device-install__checklist",children:[e.jsx(g,{label:"Signing assets",ready:i.hasSigningInputs,pendingText:"Ready to verify"}),e.jsx(g,{label:"USB device",ready:!!i.device}),e.jsx(g,{label:"Pair record",ready:i.hasPairRecord}),e.jsx(g,{label:"Profile includes connected device",ready:i.connectedDeviceInProfile,pendingText:"Checked when the build starts"})]}),i.device&&i.appleTeams.length>0&&!i.connectedAppleDeviceRegistered&&e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:l||!!i.busyAction,onClick:()=>void i.registerConnectedAppleDevice(),children:"Register connected iPhone"}),e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:l||!i.canBuild,onClick:()=>void i.startDeviceBuild(),children:i.busyAction==="build"?"Starting build...":"Start device build"}),e.jsxs("details",{className:"lr-device-install__build-logs",open:i.buildLogPanelOpen,onToggle:s=>i.setBuildLogPanelOpen(s.currentTarget.open),children:[e.jsxs("summary",{children:["Build logs (",i.buildStatus,")"]}),e.jsx("pre",{children:i.buildLogs.length>0?i.buildLogs.filter(s=>s.type!=="meta").map(s=>s.data).join(`
2
+ `):"Build logs will appear here while the device build is running."})]})]}),r.id==="install"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:l||!i.canInstall,onClick:()=>void i.startInstallation(),children:i.busyAction==="install"?"Installing...":"Install last build"}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",onClick:i.stopRelay,children:"Stop relay"})]})]},r.id))}),e.jsxs("footer",{className:"lr-device-install__logs",children:[e.jsx("h3",{children:"Progress"}),e.jsx("ol",{children:i.logs.map((r,p)=>e.jsx("li",{children:r},`${p}-${r.slice(0,24)}`))})]})]})})]})}function T({index:l,step:t,active:a,open:n,status:c,onToggle:h,children:o}){return e.jsxs("article",{className:u("lr-device-install__step",a&&"lr-device-install__step--active"),children:[e.jsxs("button",{type:"button",className:"lr-device-install__step-header","aria-expanded":n,onClick:h,children:[e.jsx("div",{className:"lr-device-install__step-number",children:l}),e.jsxs("div",{children:[e.jsx("h3",{children:t.title}),e.jsx("p",{children:t.description})]}),e.jsx("span",{className:u("lr-device-install__status",`lr-device-install__status--${c}`),children:c==="complete"?"✓ Completed":c})]}),n&&o]})}function g({label:l,ready:t,pendingText:a="Not ready"}){const n=t===void 0?a:t?"Ready":"Needs attention";return e.jsxs("div",{className:"lr-device-install__check-row",children:[e.jsx("span",{children:l}),e.jsx("strong",{children:n})]})}exports.DeviceInstallDialog=I;exports.clsx=u;
@@ -0,0 +1,462 @@
1
+ import { jsxs as l, jsx as i } from "react/jsx-runtime";
2
+ import { useState as p, useId as T, useEffect as k } from "react";
3
+ import { u as D } from "./use-device-install-j1Gekpl4.mjs";
4
+ import './device-install-dialog.css';function A(t) {
5
+ var r, s, a = "";
6
+ if (typeof t == "string" || typeof t == "number") a += t;
7
+ else if (typeof t == "object") if (Array.isArray(t)) {
8
+ var d = t.length;
9
+ for (r = 0; r < d; r++) t[r] && (s = A(t[r])) && (a && (a += " "), a += s);
10
+ } else for (s in t) t[s] && (a && (a += " "), a += s);
11
+ return a;
12
+ }
13
+ function m() {
14
+ for (var t, r, s = 0, a = "", d = arguments.length; s < d; s++) (t = arguments[s]) && (r = A(t)) && (a && (a += " "), a += r);
15
+ return a;
16
+ }
17
+ const x = [
18
+ {
19
+ id: "signing",
20
+ title: "Prepare signing",
21
+ description: "Choose Apple ID login or upload certificates, then confirm the target developer device."
22
+ },
23
+ {
24
+ id: "connect",
25
+ title: "Connect and pair",
26
+ description: "Connect the iPhone with WebUSB, then pair this browser so installs can use the device."
27
+ },
28
+ {
29
+ id: "build",
30
+ title: "Check and build",
31
+ description: "Verify the device and provisioning profile are ready, then start the signed build."
32
+ },
33
+ {
34
+ id: "install",
35
+ title: "Start installation",
36
+ description: "Relay the last successful device build to the paired iPhone."
37
+ }
38
+ ];
39
+ function $({
40
+ disabled: t,
41
+ ...r
42
+ }) {
43
+ const [s, a] = p(!1), [d, u] = p("signing"), [o, N] = p(), [_, w] = p(""), [b, P] = p(""), [f, I] = p(""), S = T(), e = D(r);
44
+ k(() => {
45
+ u(e.currentStep);
46
+ }, [e.currentStep]);
47
+ const C = (c, h) => {
48
+ e.setSigningFiles({
49
+ [c]: h.currentTarget.files?.[0]
50
+ });
51
+ };
52
+ return /* @__PURE__ */ l("div", { className: "lr-device-install", children: [
53
+ /* @__PURE__ */ i(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ className: "lr-device-install__trigger",
58
+ disabled: t || !r.apiUrl,
59
+ onClick: () => a(!0),
60
+ children: "Install to iPhone"
61
+ }
62
+ ),
63
+ s && /* @__PURE__ */ i("div", { className: "lr-device-install__backdrop", role: "presentation", children: /* @__PURE__ */ l(
64
+ "section",
65
+ {
66
+ "aria-labelledby": S,
67
+ "aria-modal": "true",
68
+ className: "lr-device-install__dialog",
69
+ role: "dialog",
70
+ children: [
71
+ /* @__PURE__ */ l("header", { className: "lr-device-install__header", children: [
72
+ /* @__PURE__ */ l("div", { children: [
73
+ /* @__PURE__ */ i("h2", { id: S, children: "Install to a real iPhone" }),
74
+ /* @__PURE__ */ i("p", { children: "Prepare signing, connect and pair the device, build, then install from this browser." })
75
+ ] }),
76
+ /* @__PURE__ */ i("button", { type: "button", className: "lr-device-install__icon-button", onClick: () => a(!1), children: "Close" })
77
+ ] }),
78
+ e.error && /* @__PURE__ */ i("div", { className: "lr-device-install__error", children: e.error }),
79
+ /* @__PURE__ */ i("div", { className: "lr-device-install__steps", children: x.map((c, h) => /* @__PURE__ */ l(
80
+ R,
81
+ {
82
+ index: h + 1,
83
+ step: c,
84
+ active: e.currentStep === c.id,
85
+ open: d === c.id,
86
+ status: e.stepStatuses[c.id],
87
+ onToggle: () => u(c.id),
88
+ children: [
89
+ c.id === "signing" && /* @__PURE__ */ l("div", { className: "lr-device-install__step-body", children: [
90
+ /* @__PURE__ */ l("div", { className: "lr-device-install__choice-grid", children: [
91
+ /* @__PURE__ */ l(
92
+ "button",
93
+ {
94
+ type: "button",
95
+ className: m(
96
+ "lr-device-install__choice",
97
+ o === "apple-id" && "lr-device-install__choice--active"
98
+ ),
99
+ onClick: () => N("apple-id"),
100
+ children: [
101
+ /* @__PURE__ */ i("strong", { children: "Apple ID login" }),
102
+ /* @__PURE__ */ i("span", { children: "Sign in, choose team, bundle ID, devices, then generate signing assets." })
103
+ ]
104
+ }
105
+ ),
106
+ /* @__PURE__ */ l(
107
+ "button",
108
+ {
109
+ type: "button",
110
+ className: m(
111
+ "lr-device-install__choice",
112
+ o === "upload" && "lr-device-install__choice--active"
113
+ ),
114
+ onClick: () => N("upload"),
115
+ children: [
116
+ /* @__PURE__ */ i("strong", { children: "Upload certificates" }),
117
+ /* @__PURE__ */ i("span", { children: "Use an existing .p12 certificate and provisioning profile." })
118
+ ]
119
+ }
120
+ )
121
+ ] }),
122
+ o === "apple-id" && /* @__PURE__ */ l("div", { className: "lr-device-install__section-panel", children: [
123
+ /* @__PURE__ */ l("div", { className: "lr-device-install__grid", children: [
124
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
125
+ /* @__PURE__ */ i("span", { children: "Apple ID" }),
126
+ /* @__PURE__ */ i(
127
+ "input",
128
+ {
129
+ type: "email",
130
+ autoComplete: "username",
131
+ placeholder: "name@example.com",
132
+ value: _,
133
+ onChange: (n) => w(n.currentTarget.value)
134
+ }
135
+ )
136
+ ] }),
137
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
138
+ /* @__PURE__ */ i("span", { children: "Apple ID password" }),
139
+ /* @__PURE__ */ i(
140
+ "input",
141
+ {
142
+ type: "password",
143
+ autoComplete: "current-password",
144
+ placeholder: "Password stays in this browser",
145
+ value: b,
146
+ onChange: (n) => P(n.currentTarget.value)
147
+ }
148
+ )
149
+ ] }),
150
+ !e.hasReusableAppleCertificate && /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
151
+ /* @__PURE__ */ i("span", { children: "Generated .p12 password" }),
152
+ /* @__PURE__ */ i(
153
+ "input",
154
+ {
155
+ type: "password",
156
+ placeholder: "Used when exporting Apple certificate",
157
+ onChange: (n) => e.setSigningFiles({ certificatePassword: n.currentTarget.value })
158
+ }
159
+ )
160
+ ] })
161
+ ] }),
162
+ /* @__PURE__ */ l("div", { className: "lr-device-install__actions", children: [
163
+ /* @__PURE__ */ i(
164
+ "button",
165
+ {
166
+ type: "button",
167
+ className: "lr-device-install__secondary",
168
+ disabled: t || !r.apiUrl || !_ || !b || e.busyAction === "signing",
169
+ onClick: () => void e.startAppleIDLogin({
170
+ accountName: _,
171
+ password: b
172
+ }),
173
+ children: e.appleSigningStatus === "authenticating" ? "Signing in..." : "Sign in with Apple ID"
174
+ }
175
+ ),
176
+ /* @__PURE__ */ l("span", { className: "lr-device-install__hint", children: [
177
+ "Apple password is used only by browser-side SRP. Status: ",
178
+ e.appleSigningStatus
179
+ ] })
180
+ ] }),
181
+ e.appleSigningStatus === "two-factor-required" && /* @__PURE__ */ l("div", { className: "lr-device-install__grid", children: [
182
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
183
+ /* @__PURE__ */ i("span", { children: "Two-factor code" }),
184
+ /* @__PURE__ */ i(
185
+ "input",
186
+ {
187
+ type: "text",
188
+ inputMode: "numeric",
189
+ autoComplete: "one-time-code",
190
+ value: f,
191
+ onChange: (n) => I(n.currentTarget.value)
192
+ }
193
+ )
194
+ ] }),
195
+ /* @__PURE__ */ i(
196
+ "button",
197
+ {
198
+ type: "button",
199
+ className: "lr-device-install__secondary",
200
+ disabled: !f || e.busyAction === "signing",
201
+ onClick: () => void e.submitAppleTwoFactorCode(f),
202
+ children: "Submit Apple ID code"
203
+ }
204
+ )
205
+ ] }),
206
+ e.appleTeams.length > 0 && /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
207
+ /* @__PURE__ */ i("span", { children: "Apple Developer team" }),
208
+ /* @__PURE__ */ i(
209
+ "select",
210
+ {
211
+ value: e.selectedAppleTeamID ?? "",
212
+ onChange: (n) => e.setSelectedAppleTeamID(n.currentTarget.value || void 0),
213
+ children: e.appleTeams.map((n, y) => {
214
+ const v = n.teamId ?? (n.providerId === void 0 ? void 0 : String(n.providerId)) ?? n.publicProviderId ?? "";
215
+ return /* @__PURE__ */ l("option", { value: v, children: [
216
+ n.name ?? "Apple Developer Team",
217
+ " ",
218
+ v ? `(${v})` : ""
219
+ ] }, `${v}-${y}`);
220
+ })
221
+ }
222
+ )
223
+ ] }),
224
+ e.appleDevices.length > 0 && /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
225
+ /* @__PURE__ */ i("span", { children: "Apple Developer devices" }),
226
+ /* @__PURE__ */ i(
227
+ "select",
228
+ {
229
+ multiple: !0,
230
+ value: e.selectedAppleDeviceIDs,
231
+ onChange: (n) => e.setSelectedAppleDeviceIDs(
232
+ Array.from(n.currentTarget.selectedOptions).map((y) => y.value)
233
+ ),
234
+ children: e.appleDevices.map((n) => /* @__PURE__ */ l(
235
+ "option",
236
+ {
237
+ value: n.deviceId ?? "",
238
+ children: [
239
+ n.name ?? n.model ?? "Apple device",
240
+ " ",
241
+ n.deviceNumber ?? ""
242
+ ]
243
+ },
244
+ n.deviceId ?? n.deviceNumber
245
+ ))
246
+ }
247
+ )
248
+ ] }),
249
+ e.applePortalSummary && /* @__PURE__ */ l("p", { className: "lr-device-install__hint", children: [
250
+ "Found ",
251
+ e.applePortalSummary.certificateCount,
252
+ " certificates and",
253
+ " ",
254
+ e.applePortalSummary.profileCount,
255
+ " provisioning profiles."
256
+ ] }),
257
+ e.hasReusableAppleCertificate && /* @__PURE__ */ i("p", { className: "lr-device-install__hint", children: "Reusing the certificate and private key stored in this browser." }),
258
+ /* @__PURE__ */ i(
259
+ "button",
260
+ {
261
+ type: "button",
262
+ className: "lr-device-install__primary",
263
+ disabled: t || !e.canPrepareAppleSigningAssets,
264
+ onClick: () => void e.prepareAppleSigningAssets(),
265
+ children: e.appleSigningStatus === "preparing-assets" ? "Preparing signing assets..." : "Generate certificate and profile"
266
+ }
267
+ )
268
+ ] }),
269
+ o === "upload" && /* @__PURE__ */ l("div", { className: "lr-device-install__section-panel", children: [
270
+ /* @__PURE__ */ l("div", { className: "lr-device-install__grid", children: [
271
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
272
+ /* @__PURE__ */ i("span", { children: "Certificate (.p12)" }),
273
+ /* @__PURE__ */ i(
274
+ "input",
275
+ {
276
+ type: "file",
277
+ accept: ".p12,application/x-pkcs12",
278
+ onChange: (n) => C("certificateFile", n)
279
+ }
280
+ )
281
+ ] }),
282
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
283
+ /* @__PURE__ */ i("span", { children: "Provisioning profile" }),
284
+ /* @__PURE__ */ i(
285
+ "input",
286
+ {
287
+ type: "file",
288
+ accept: ".mobileprovision",
289
+ onChange: (n) => C("provisioningProfileFile", n)
290
+ }
291
+ )
292
+ ] }),
293
+ /* @__PURE__ */ l("label", { className: "lr-device-install__field", children: [
294
+ /* @__PURE__ */ i("span", { children: "Uploaded .p12 password" }),
295
+ /* @__PURE__ */ i(
296
+ "input",
297
+ {
298
+ type: "password",
299
+ placeholder: "Export password",
300
+ onChange: (n) => e.setSigningFiles({ certificatePassword: n.currentTarget.value })
301
+ }
302
+ )
303
+ ] })
304
+ ] }),
305
+ /* @__PURE__ */ i("p", { className: "lr-device-install__hint", children: "The provisioning profile will be checked against the connected iPhone before the build starts." })
306
+ ] }),
307
+ e.hasSigningAssets && /* @__PURE__ */ i("p", { children: "Signing assets are stored in this browser for the selected bundle and device." })
308
+ ] }),
309
+ c.id === "connect" && /* @__PURE__ */ l("div", { className: "lr-device-install__step-body", children: [
310
+ /* @__PURE__ */ i("p", { children: "WebUSB works in Chromium browsers on secure origins. Connect the iPhone over USB, approve the browser permission prompt, then pair this browser." }),
311
+ /* @__PURE__ */ l("div", { className: "lr-device-install__actions", children: [
312
+ /* @__PURE__ */ i(
313
+ "button",
314
+ {
315
+ type: "button",
316
+ className: "lr-device-install__primary",
317
+ disabled: t || !e.canRequestUSBAccess,
318
+ onClick: () => void e.requestUSBAccess(),
319
+ children: e.busyAction === "usb" ? "Selecting iPhone..." : "Allow USB access"
320
+ }
321
+ ),
322
+ /* @__PURE__ */ i(
323
+ "button",
324
+ {
325
+ type: "button",
326
+ className: "lr-device-install__secondary",
327
+ disabled: t || !e.canPairBrowser,
328
+ onClick: () => void e.pairBrowser(),
329
+ children: e.busyAction === "pair" ? "Pairing..." : e.pairConfirmationRequired ? "Confirm pair record" : "Pair browser"
330
+ }
331
+ )
332
+ ] }),
333
+ e.device && /* @__PURE__ */ i("div", { className: "lr-device-install__device", children: `${e.device.productName ?? "iPhone"} ${e.device.serialNumber ?? ""}`.trim() }),
334
+ e.pairConfirmationRequired && /* @__PURE__ */ l("p", { children: [
335
+ "Unlock the iPhone and tap ",
336
+ /* @__PURE__ */ i("strong", { children: "Trust" }),
337
+ " in the system dialog, then confirm the pair record."
338
+ ] }),
339
+ /* @__PURE__ */ i("p", { children: e.hasPairRecord ? "Pair record is stored locally. Continue to the build check." : "Pair this browser once before building and installing." })
340
+ ] }),
341
+ c.id === "build" && /* @__PURE__ */ l("div", { className: "lr-device-install__step-body", children: [
342
+ /* @__PURE__ */ l("div", { className: "lr-device-install__checklist", children: [
343
+ /* @__PURE__ */ i(g, { label: "Signing assets", ready: e.hasSigningInputs, pendingText: "Ready to verify" }),
344
+ /* @__PURE__ */ i(g, { label: "USB device", ready: !!e.device }),
345
+ /* @__PURE__ */ i(g, { label: "Pair record", ready: e.hasPairRecord }),
346
+ /* @__PURE__ */ i(
347
+ g,
348
+ {
349
+ label: "Profile includes connected device",
350
+ ready: e.connectedDeviceInProfile,
351
+ pendingText: "Checked when the build starts"
352
+ }
353
+ )
354
+ ] }),
355
+ e.device && e.appleTeams.length > 0 && !e.connectedAppleDeviceRegistered && /* @__PURE__ */ i(
356
+ "button",
357
+ {
358
+ type: "button",
359
+ className: "lr-device-install__secondary",
360
+ disabled: t || !!e.busyAction,
361
+ onClick: () => void e.registerConnectedAppleDevice(),
362
+ children: "Register connected iPhone"
363
+ }
364
+ ),
365
+ /* @__PURE__ */ i(
366
+ "button",
367
+ {
368
+ type: "button",
369
+ className: "lr-device-install__primary",
370
+ disabled: t || !e.canBuild,
371
+ onClick: () => void e.startDeviceBuild(),
372
+ children: e.busyAction === "build" ? "Starting build..." : "Start device build"
373
+ }
374
+ ),
375
+ /* @__PURE__ */ l(
376
+ "details",
377
+ {
378
+ className: "lr-device-install__build-logs",
379
+ open: e.buildLogPanelOpen,
380
+ onToggle: (n) => e.setBuildLogPanelOpen(n.currentTarget.open),
381
+ children: [
382
+ /* @__PURE__ */ l("summary", { children: [
383
+ "Build logs (",
384
+ e.buildStatus,
385
+ ")"
386
+ ] }),
387
+ /* @__PURE__ */ i("pre", { children: e.buildLogs.length > 0 ? e.buildLogs.filter((n) => n.type !== "meta").map((n) => n.data).join(`
388
+ `) : "Build logs will appear here while the device build is running." })
389
+ ]
390
+ }
391
+ )
392
+ ] }),
393
+ c.id === "install" && /* @__PURE__ */ l("div", { className: "lr-device-install__step-body", children: [
394
+ /* @__PURE__ */ i(
395
+ "button",
396
+ {
397
+ type: "button",
398
+ className: "lr-device-install__primary",
399
+ disabled: t || !e.canInstall,
400
+ onClick: () => void e.startInstallation(),
401
+ children: e.busyAction === "install" ? "Installing..." : "Install last build"
402
+ }
403
+ ),
404
+ /* @__PURE__ */ i("button", { type: "button", className: "lr-device-install__secondary", onClick: e.stopRelay, children: "Stop relay" })
405
+ ] })
406
+ ]
407
+ },
408
+ c.id
409
+ )) }),
410
+ /* @__PURE__ */ l("footer", { className: "lr-device-install__logs", children: [
411
+ /* @__PURE__ */ i("h3", { children: "Progress" }),
412
+ /* @__PURE__ */ i("ol", { children: e.logs.map((c, h) => /* @__PURE__ */ i("li", { children: c }, `${h}-${c.slice(0, 24)}`)) })
413
+ ] })
414
+ ]
415
+ }
416
+ ) })
417
+ ] });
418
+ }
419
+ function R({
420
+ index: t,
421
+ step: r,
422
+ active: s,
423
+ open: a,
424
+ status: d,
425
+ onToggle: u,
426
+ children: o
427
+ }) {
428
+ return /* @__PURE__ */ l("article", { className: m("lr-device-install__step", s && "lr-device-install__step--active"), children: [
429
+ /* @__PURE__ */ l(
430
+ "button",
431
+ {
432
+ type: "button",
433
+ className: "lr-device-install__step-header",
434
+ "aria-expanded": a,
435
+ onClick: u,
436
+ children: [
437
+ /* @__PURE__ */ i("div", { className: "lr-device-install__step-number", children: t }),
438
+ /* @__PURE__ */ l("div", { children: [
439
+ /* @__PURE__ */ i("h3", { children: r.title }),
440
+ /* @__PURE__ */ i("p", { children: r.description })
441
+ ] }),
442
+ /* @__PURE__ */ i("span", { className: m("lr-device-install__status", `lr-device-install__status--${d}`), children: d === "complete" ? "✓ Completed" : d })
443
+ ]
444
+ }
445
+ ),
446
+ a && o
447
+ ] });
448
+ }
449
+ function g({
450
+ label: t,
451
+ ready: r,
452
+ pendingText: s = "Not ready"
453
+ }) {
454
+ return /* @__PURE__ */ l("div", { className: "lr-device-install__check-row", children: [
455
+ /* @__PURE__ */ i("span", { children: t }),
456
+ /* @__PURE__ */ i("strong", { children: r === void 0 ? s : r ? "Ready" : "Needs attention" })
457
+ ] });
458
+ }
459
+ export {
460
+ $ as D,
461
+ m as c
462
+ };
@@ -0,0 +1 @@
1
+ .lr-device-install{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.lr-device-install__trigger,.lr-device-install__primary,.lr-device-install__secondary,.lr-device-install__icon-button{border:1px solid #d1d5db;border-radius:8px;cursor:pointer;font:inherit}.lr-device-install__trigger,.lr-device-install__primary{background:#111827;color:#fff;padding:8px 12px}.lr-device-install__secondary,.lr-device-install__icon-button{background:#fff;color:#111827;padding:8px 12px}.lr-device-install__trigger:disabled,.lr-device-install__primary:disabled,.lr-device-install__secondary:disabled{cursor:not-allowed;opacity:.55}.lr-device-install__backdrop{align-items:center;background:#1118278c;display:flex;inset:0;justify-content:center;padding:24px;position:fixed;z-index:50}.lr-device-install__dialog{background:#fff;border-radius:16px;box-shadow:0 24px 80px #0f172a47;color:#111827;max-height:min(90vh,900px);max-width:880px;overflow:auto;padding:24px;width:100%}.lr-device-install__header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between;margin-bottom:18px}.lr-device-install__header h2,.lr-device-install__step h3,.lr-device-install__logs h3{margin:0}.lr-device-install__header p,.lr-device-install__step p,.lr-device-install__logs{color:#4b5563}.lr-device-install__error{background:#fef2f2;border:1px solid #fecaca;border-radius:10px;color:#991b1b;margin-bottom:14px;padding:10px 12px}.lr-device-install__steps{display:grid;gap:12px}.lr-device-install__step{border:1px solid #e5e7eb;border-radius:12px;padding:14px}.lr-device-install__step--active{border-color:#111827}.lr-device-install__step-header{align-items:flex-start;background:transparent;border:0;color:inherit;cursor:pointer;display:grid;gap:12px;grid-template-columns:auto 1fr auto;padding:0;text-align:left;width:100%}.lr-device-install__step-number{align-items:center;background:#111827;border-radius:999px;color:#fff;display:flex;font-size:13px;font-weight:700;height:28px;justify-content:center;width:28px}.lr-device-install__status{border-radius:999px;font-size:12px;padding:3px 8px;text-transform:capitalize}.lr-device-install__status--idle{background:#f3f4f6;color:#4b5563}.lr-device-install__status--active{background:#dbeafe;color:#1d4ed8}.lr-device-install__status--complete{background:#dcfce7;color:#166534}.lr-device-install__status--error{background:#fee2e2;color:#991b1b}.lr-device-install__step-body{display:grid;gap:12px;margin-top:12px}.lr-device-install__choice-grid{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr))}.lr-device-install__choice{background:#fff;border:1px solid #d1d5db;border-radius:10px;color:inherit;cursor:pointer;display:grid;gap:6px;padding:12px;text-align:left}.lr-device-install__choice span{color:#4b5563;font-size:13px}.lr-device-install__choice--active{border-color:#111827;box-shadow:0 0 0 1px #111827}.lr-device-install__section-panel{border:1px solid #e5e7eb;border-radius:12px;display:grid;gap:12px;padding:12px}.lr-device-install__grid{display:grid;gap:10px;grid-template-columns:repeat(3,minmax(0,1fr))}.lr-device-install__field{display:grid;gap:6px}.lr-device-install__field span{color:#374151;font-size:13px;font-weight:600}.lr-device-install__field input,.lr-device-install__field select{border:1px solid #d1d5db;border-radius:8px;font:inherit;padding:8px 10px}.lr-device-install__actions{align-items:center;display:flex;flex-wrap:wrap;gap:10px}.lr-device-install__hint{color:#6b7280;font-size:13px}.lr-device-install__checklist{border:1px solid #e5e7eb;border-radius:10px;display:grid;overflow:hidden}.lr-device-install__check-row{align-items:center;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.lr-device-install__check-row+.lr-device-install__check-row{border-top:1px solid #e5e7eb}.lr-device-install__check-row strong{color:#111827;font-size:13px}.lr-device-install__build-logs{border:1px solid #e5e7eb;border-radius:10px;overflow:hidden}.lr-device-install__build-logs summary{cursor:pointer;font-weight:600;padding:10px 12px}.lr-device-install__build-logs pre{background:#0f172a;color:#e5e7eb;margin:0;max-height:240px;overflow:auto;padding:12px;white-space:pre-wrap}.lr-device-install__device{background:#f9fafb;border:1px solid #e5e7eb;border-radius:10px;padding:10px}.lr-device-install__logs{border-top:1px solid #e5e7eb;margin-top:18px;padding-top:14px}.lr-device-install__logs ol{display:grid;gap:6px;list-style:none;margin:8px 0 0;max-height:160px;overflow:auto;padding:0}.lr-device-install__logs li{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:12px;white-space:pre-wrap}@media (max-width: 760px){.lr-device-install__choice-grid,.lr-device-install__grid{grid-template-columns:1fr}.lr-device-install__step-header{grid-template-columns:auto 1fr}.lr-device-install__status{grid-column:2}}
@@ -0,0 +1 @@
1
+ export * from './use-device-install';