@limrun/ui 0.8.0 → 0.9.0-rc.2

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 +43 -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 +77 -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-CSwQgbBm.js +2 -0
  28. package/dist/device-install-dialog-nThj775b.mjs +395 -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 +70 -0
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.js +401 -408
  35. package/dist/use-device-install-C1uVac59.mjs +13541 -0
  36. package/dist/use-device-install-Ca4jcVKU.js +31 -0
  37. package/package.json +15 -2
  38. package/src/components/device-install/device-install-dialog.css +244 -0
  39. package/src/components/device-install/device-install-dialog.tsx +432 -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 +251 -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 +1067 -0
  63. package/src/index.ts +2 -0
  64. package/vite.config.ts +6 -2
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../use-device-install-Ca4jcVKU.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-C1uVac59.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"),u=require("react"),y=require("./use-device-install-Ca4jcVKU.js");function x(s){var n,r,a="";if(typeof s=="string"||typeof s=="number")a+=s;else if(typeof s=="object")if(Array.isArray(s)){var d=s.length;for(n=0;n<d;n++)s[n]&&(r=x(s[n]))&&(a&&(a+=" "),a+=r)}else for(r in s)s[r]&&(a&&(a+=" "),a+=r);return a}function m(){for(var s,n,r=0,a="",d=arguments.length;r<d;r++)(s=arguments[r])&&(n=x(s))&&(a&&(a+=" "),a+=n);return a}const N=[{id:"build",title:"Start a device build",description:"Upload signing assets if needed, then follow the live build logs until the device build succeeds."},{id:"usb",title:"Access USB procedures",description:"Allow WebUSB access to the connected iPhone from a Chromium browser on a secure origin."},{id:"pair",title:"Pair with this browser",description:"Pair once and store the pair record locally so future installs can reuse it."},{id:"install",title:"Start installation",description:"Relay the last successful device build to the paired iPhone."}];function S({disabled:s,...n}){const[r,a]=u.useState(!1),[d,_]=u.useState(""),[h,j]=u.useState(""),[v,f]=u.useState(""),g=u.useId(),l=y.useDeviceInstall(n),b=(t,o)=>{l.setSigningFiles({[t]:o.currentTarget.files?.[0]})};return e.jsxs("div",{className:"lr-device-install",children:[e.jsx("button",{type:"button",className:"lr-device-install__trigger",disabled:s||!n.apiUrl,onClick:()=>a(!0),children:"Install to iPhone"}),r&&e.jsx("div",{className:"lr-device-install__backdrop",role:"presentation",children:e.jsxs("section",{"aria-labelledby":g,"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:g,children:"Install to a real iPhone"}),e.jsx("p",{children:"Follow each step to build, authorize USB, pair, and install from this browser."})]}),e.jsx("button",{type:"button",className:"lr-device-install__icon-button",onClick:()=>a(!1),children:"Close"})]}),l.error&&e.jsx("div",{className:"lr-device-install__error",children:l.error}),e.jsx("div",{className:"lr-device-install__steps",children:N.map((t,o)=>e.jsxs(A,{index:o+1,step:t,active:l.currentStep===t.id,status:l.stepStatuses[t.id],children:[t.id==="build"&&e.jsxs("div",{className:"lr-device-install__step-body",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:d,onChange:i=>_(i.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:h,onChange:i=>j(i.currentTarget.value)})]}),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:i=>l.setSigningFiles({certificatePassword:i.currentTarget.value})})]})]}),e.jsxs("div",{className:"lr-device-install__actions",children:[e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:s||!n.apiUrl||!d||!h||l.busyAction==="build",onClick:()=>void l.startAppleIDLogin({accountName:d,password:h}),children:l.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: ",l.appleSigningStatus]})]}),l.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:v,onChange:i=>f(i.currentTarget.value)})]}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:!v||l.busyAction==="build",onClick:()=>void l.submitAppleTwoFactorCode(v),children:"Submit Apple ID code"})]}),l.appleTeams.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Apple Developer team"}),e.jsx("select",{value:l.selectedAppleTeamID??"",onChange:i=>l.setSelectedAppleTeamID(i.currentTarget.value||void 0),children:l.appleTeams.map((i,p)=>{const c=i.teamId??(i.providerId===void 0?void 0:String(i.providerId))??i.publicProviderId??"";return e.jsxs("option",{value:c,children:[i.name??"Apple Developer Team"," ",c?`(${c})`:""]},`${c}-${p}`)})})]}),l.applePortalSummary&&e.jsxs("p",{className:"lr-device-install__hint",children:["Found ",l.applePortalSummary.certificateCount," certificates and"," ",l.applePortalSummary.profileCount," provisioning profiles."]})]}),l.appleAppIDs.length>0&&e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Bundle ID"}),e.jsx("select",{value:l.appleBundleID,onChange:i=>l.setAppleBundleID(i.currentTarget.value),children:l.appleAppIDs.map((i,p)=>{const c=i.identifier??i.bundleId??"";return e.jsxs("option",{value:c,children:[i.name??c," ",c?`(${c})`:""]},`${c}-${p}`)})})]}),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:i=>b("certificateFile",i)})]}),e.jsxs("label",{className:"lr-device-install__field",children:[e.jsx("span",{children:"Provisioning profile"}),e.jsx("input",{type:"file",accept:".mobileprovision",onChange:i=>b("provisioningProfileFile",i)})]}),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:i=>l.setSigningFiles({certificatePassword:i.currentTarget.value})})]})]}),e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:s||!l.canBuild,onClick:()=>void l.startDeviceBuild(),children:l.busyAction==="build"?"Starting build...":"Start device build"}),e.jsxs("details",{className:"lr-device-install__build-logs",open:l.buildLogPanelOpen,onToggle:i=>l.setBuildLogPanelOpen(i.currentTarget.open),children:[e.jsxs("summary",{children:["Build logs (",l.buildStatus,")"]}),e.jsx("pre",{children:l.buildLogs.length>0?l.buildLogs.filter(i=>i.type!=="meta").map(i=>i.data).join(`
2
+ `):"Build logs will appear here while the device build is running."})]})]}),t.id==="usb"&&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 and approve the browser permission prompt."}),e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:s||!l.canRequestUSBAccess,onClick:()=>void l.requestUSBAccess(),children:l.busyAction==="usb"?"Selecting iPhone...":"Allow USB access"}),l.device&&e.jsx("div",{className:"lr-device-install__device",children:`${l.device.productName??"iPhone"} ${l.device.serialNumber??""}`.trim()}),l.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:l.selectedAppleDeviceIDs,onChange:i=>l.setSelectedAppleDeviceIDs(Array.from(i.currentTarget.selectedOptions).map(p=>p.value)),children:l.appleDevices.map(i=>e.jsxs("option",{value:i.deviceId??"",children:[i.name??i.model??"Apple device"," ",i.deviceNumber??""]},i.deviceId??i.deviceNumber))})]}),l.device&&!l.connectedAppleDeviceRegistered&&e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:s||!!l.busyAction,onClick:()=>void l.registerConnectedAppleDevice(),children:"Register connected iPhone"}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",disabled:s||!l.canPrepareAppleSigningAssets,onClick:()=>void l.prepareAppleSigningAssets(),children:l.appleSigningStatus==="preparing-assets"?"Preparing signing assets...":"Generate certificate and profile"}),l.hasSigningAssets&&e.jsx("p",{children:"Signing assets are stored in this browser for the selected bundle and device."})]}),t.id==="pair"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[l.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("button",{type:"button",className:"lr-device-install__primary",disabled:s||!l.canPairBrowser,onClick:()=>void l.pairBrowser(),children:l.busyAction==="pair"?"Pairing...":l.pairConfirmationRequired?"Confirm pair record":"Pair browser"}),e.jsx("p",{children:l.hasPairRecord?"Pair record is stored locally. Installation is available.":"Pair this browser once before installing."})]}),t.id==="install"&&e.jsxs("div",{className:"lr-device-install__step-body",children:[e.jsx("button",{type:"button",className:"lr-device-install__primary",disabled:s||!l.canInstall,onClick:()=>void l.startInstallation(),children:l.busyAction==="install"?"Installing...":"Install last build"}),e.jsx("button",{type:"button",className:"lr-device-install__secondary",onClick:l.stopRelay,children:"Stop relay"})]})]},t.id))}),e.jsxs("footer",{className:"lr-device-install__logs",children:[e.jsx("h3",{children:"Progress"}),e.jsx("ol",{children:l.logs.map((t,o)=>e.jsx("li",{children:t},`${o}-${t.slice(0,24)}`))})]})]})})]})}function A({index:s,step:n,active:r,status:a,children:d}){return e.jsxs("article",{className:m("lr-device-install__step",r&&"lr-device-install__step--active"),children:[e.jsxs("div",{className:"lr-device-install__step-header",children:[e.jsx("div",{className:"lr-device-install__step-number",children:s}),e.jsxs("div",{children:[e.jsx("h3",{children:n.title}),e.jsx("p",{children:n.description})]}),e.jsx("span",{className:m("lr-device-install__status",`lr-device-install__status--${a}`),children:a})]}),d]})}exports.DeviceInstallDialog=S;exports.clsx=m;
@@ -0,0 +1,395 @@
1
+ import { jsxs as a, jsx as l, Fragment as S } from "react/jsx-runtime";
2
+ import { useState as h, useId as w } from "react";
3
+ import { u as C } from "./use-device-install-C1uVac59.mjs";
4
+ import './device-install-dialog.css';function f(n) {
5
+ var t, s, r = "";
6
+ if (typeof n == "string" || typeof n == "number") r += n;
7
+ else if (typeof n == "object") if (Array.isArray(n)) {
8
+ var o = n.length;
9
+ for (t = 0; t < o; t++) n[t] && (s = f(n[t])) && (r && (r += " "), r += s);
10
+ } else for (s in n) n[s] && (r && (r += " "), r += s);
11
+ return r;
12
+ }
13
+ function _() {
14
+ for (var n, t, s = 0, r = "", o = arguments.length; s < o; s++) (n = arguments[s]) && (t = f(n)) && (r && (r += " "), r += t);
15
+ return r;
16
+ }
17
+ const P = [
18
+ {
19
+ id: "build",
20
+ title: "Start a device build",
21
+ description: "Upload signing assets if needed, then follow the live build logs until the device build succeeds."
22
+ },
23
+ {
24
+ id: "usb",
25
+ title: "Access USB procedures",
26
+ description: "Allow WebUSB access to the connected iPhone from a Chromium browser on a secure origin."
27
+ },
28
+ {
29
+ id: "pair",
30
+ title: "Pair with this browser",
31
+ description: "Pair once and store the pair record locally so future installs can reuse it."
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 U({
40
+ disabled: n,
41
+ ...t
42
+ }) {
43
+ const [s, r] = h(!1), [o, y] = h(""), [v, N] = h(""), [m, A] = h(""), g = w(), e = C(t), b = (c, p) => {
44
+ e.setSigningFiles({
45
+ [c]: p.currentTarget.files?.[0]
46
+ });
47
+ };
48
+ return /* @__PURE__ */ a("div", { className: "lr-device-install", children: [
49
+ /* @__PURE__ */ l(
50
+ "button",
51
+ {
52
+ type: "button",
53
+ className: "lr-device-install__trigger",
54
+ disabled: n || !t.apiUrl,
55
+ onClick: () => r(!0),
56
+ children: "Install to iPhone"
57
+ }
58
+ ),
59
+ s && /* @__PURE__ */ l("div", { className: "lr-device-install__backdrop", role: "presentation", children: /* @__PURE__ */ a(
60
+ "section",
61
+ {
62
+ "aria-labelledby": g,
63
+ "aria-modal": "true",
64
+ className: "lr-device-install__dialog",
65
+ role: "dialog",
66
+ children: [
67
+ /* @__PURE__ */ a("header", { className: "lr-device-install__header", children: [
68
+ /* @__PURE__ */ a("div", { children: [
69
+ /* @__PURE__ */ l("h2", { id: g, children: "Install to a real iPhone" }),
70
+ /* @__PURE__ */ l("p", { children: "Follow each step to build, authorize USB, pair, and install from this browser." })
71
+ ] }),
72
+ /* @__PURE__ */ l("button", { type: "button", className: "lr-device-install__icon-button", onClick: () => r(!1), children: "Close" })
73
+ ] }),
74
+ e.error && /* @__PURE__ */ l("div", { className: "lr-device-install__error", children: e.error }),
75
+ /* @__PURE__ */ l("div", { className: "lr-device-install__steps", children: P.map((c, p) => /* @__PURE__ */ a(
76
+ I,
77
+ {
78
+ index: p + 1,
79
+ step: c,
80
+ active: e.currentStep === c.id,
81
+ status: e.stepStatuses[c.id],
82
+ children: [
83
+ c.id === "build" && /* @__PURE__ */ a("div", { className: "lr-device-install__step-body", children: [
84
+ /* @__PURE__ */ a("div", { className: "lr-device-install__grid", children: [
85
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
86
+ /* @__PURE__ */ l("span", { children: "Apple ID" }),
87
+ /* @__PURE__ */ l(
88
+ "input",
89
+ {
90
+ type: "email",
91
+ autoComplete: "username",
92
+ placeholder: "name@example.com",
93
+ value: o,
94
+ onChange: (i) => y(i.currentTarget.value)
95
+ }
96
+ )
97
+ ] }),
98
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
99
+ /* @__PURE__ */ l("span", { children: "Apple ID password" }),
100
+ /* @__PURE__ */ l(
101
+ "input",
102
+ {
103
+ type: "password",
104
+ autoComplete: "current-password",
105
+ placeholder: "Password stays in this browser",
106
+ value: v,
107
+ onChange: (i) => N(i.currentTarget.value)
108
+ }
109
+ )
110
+ ] }),
111
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
112
+ /* @__PURE__ */ l("span", { children: "Generated .p12 password" }),
113
+ /* @__PURE__ */ l(
114
+ "input",
115
+ {
116
+ type: "password",
117
+ placeholder: "Used when exporting Apple certificate",
118
+ onChange: (i) => e.setSigningFiles({ certificatePassword: i.currentTarget.value })
119
+ }
120
+ )
121
+ ] })
122
+ ] }),
123
+ /* @__PURE__ */ a("div", { className: "lr-device-install__actions", children: [
124
+ /* @__PURE__ */ l(
125
+ "button",
126
+ {
127
+ type: "button",
128
+ className: "lr-device-install__secondary",
129
+ disabled: n || !t.apiUrl || !o || !v || e.busyAction === "build",
130
+ onClick: () => void e.startAppleIDLogin({
131
+ accountName: o,
132
+ password: v
133
+ }),
134
+ children: e.appleSigningStatus === "authenticating" ? "Signing in..." : "Sign in with Apple ID"
135
+ }
136
+ ),
137
+ /* @__PURE__ */ a("span", { className: "lr-device-install__hint", children: [
138
+ "Apple password is used only by browser-side SRP. Status: ",
139
+ e.appleSigningStatus
140
+ ] })
141
+ ] }),
142
+ e.appleSigningStatus === "two-factor-required" && /* @__PURE__ */ a("div", { className: "lr-device-install__grid", children: [
143
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
144
+ /* @__PURE__ */ l("span", { children: "Two-factor code" }),
145
+ /* @__PURE__ */ l(
146
+ "input",
147
+ {
148
+ type: "text",
149
+ inputMode: "numeric",
150
+ autoComplete: "one-time-code",
151
+ value: m,
152
+ onChange: (i) => A(i.currentTarget.value)
153
+ }
154
+ )
155
+ ] }),
156
+ /* @__PURE__ */ l(
157
+ "button",
158
+ {
159
+ type: "button",
160
+ className: "lr-device-install__secondary",
161
+ disabled: !m || e.busyAction === "build",
162
+ onClick: () => void e.submitAppleTwoFactorCode(m),
163
+ children: "Submit Apple ID code"
164
+ }
165
+ )
166
+ ] }),
167
+ e.appleTeams.length > 0 && /* @__PURE__ */ a(S, { children: [
168
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
169
+ /* @__PURE__ */ l("span", { children: "Apple Developer team" }),
170
+ /* @__PURE__ */ l(
171
+ "select",
172
+ {
173
+ value: e.selectedAppleTeamID ?? "",
174
+ onChange: (i) => e.setSelectedAppleTeamID(i.currentTarget.value || void 0),
175
+ children: e.appleTeams.map((i, u) => {
176
+ const d = i.teamId ?? (i.providerId === void 0 ? void 0 : String(i.providerId)) ?? i.publicProviderId ?? "";
177
+ return /* @__PURE__ */ a("option", { value: d, children: [
178
+ i.name ?? "Apple Developer Team",
179
+ " ",
180
+ d ? `(${d})` : ""
181
+ ] }, `${d}-${u}`);
182
+ })
183
+ }
184
+ )
185
+ ] }),
186
+ e.applePortalSummary && /* @__PURE__ */ a("p", { className: "lr-device-install__hint", children: [
187
+ "Found ",
188
+ e.applePortalSummary.certificateCount,
189
+ " certificates and",
190
+ " ",
191
+ e.applePortalSummary.profileCount,
192
+ " provisioning profiles."
193
+ ] })
194
+ ] }),
195
+ e.appleAppIDs.length > 0 && /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
196
+ /* @__PURE__ */ l("span", { children: "Bundle ID" }),
197
+ /* @__PURE__ */ l(
198
+ "select",
199
+ {
200
+ value: e.appleBundleID,
201
+ onChange: (i) => e.setAppleBundleID(i.currentTarget.value),
202
+ children: e.appleAppIDs.map((i, u) => {
203
+ const d = i.identifier ?? i.bundleId ?? "";
204
+ return /* @__PURE__ */ a("option", { value: d, children: [
205
+ i.name ?? d,
206
+ " ",
207
+ d ? `(${d})` : ""
208
+ ] }, `${d}-${u}`);
209
+ })
210
+ }
211
+ )
212
+ ] }),
213
+ /* @__PURE__ */ a("div", { className: "lr-device-install__grid", children: [
214
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
215
+ /* @__PURE__ */ l("span", { children: "Certificate (.p12)" }),
216
+ /* @__PURE__ */ l(
217
+ "input",
218
+ {
219
+ type: "file",
220
+ accept: ".p12,application/x-pkcs12",
221
+ onChange: (i) => b("certificateFile", i)
222
+ }
223
+ )
224
+ ] }),
225
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
226
+ /* @__PURE__ */ l("span", { children: "Provisioning profile" }),
227
+ /* @__PURE__ */ l(
228
+ "input",
229
+ {
230
+ type: "file",
231
+ accept: ".mobileprovision",
232
+ onChange: (i) => b("provisioningProfileFile", i)
233
+ }
234
+ )
235
+ ] }),
236
+ /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
237
+ /* @__PURE__ */ l("span", { children: "Uploaded .p12 password" }),
238
+ /* @__PURE__ */ l(
239
+ "input",
240
+ {
241
+ type: "password",
242
+ placeholder: "Export password",
243
+ onChange: (i) => e.setSigningFiles({ certificatePassword: i.currentTarget.value })
244
+ }
245
+ )
246
+ ] })
247
+ ] }),
248
+ /* @__PURE__ */ l(
249
+ "button",
250
+ {
251
+ type: "button",
252
+ className: "lr-device-install__primary",
253
+ disabled: n || !e.canBuild,
254
+ onClick: () => void e.startDeviceBuild(),
255
+ children: e.busyAction === "build" ? "Starting build..." : "Start device build"
256
+ }
257
+ ),
258
+ /* @__PURE__ */ a(
259
+ "details",
260
+ {
261
+ className: "lr-device-install__build-logs",
262
+ open: e.buildLogPanelOpen,
263
+ onToggle: (i) => e.setBuildLogPanelOpen(i.currentTarget.open),
264
+ children: [
265
+ /* @__PURE__ */ a("summary", { children: [
266
+ "Build logs (",
267
+ e.buildStatus,
268
+ ")"
269
+ ] }),
270
+ /* @__PURE__ */ l("pre", { children: e.buildLogs.length > 0 ? e.buildLogs.filter((i) => i.type !== "meta").map((i) => i.data).join(`
271
+ `) : "Build logs will appear here while the device build is running." })
272
+ ]
273
+ }
274
+ )
275
+ ] }),
276
+ c.id === "usb" && /* @__PURE__ */ a("div", { className: "lr-device-install__step-body", children: [
277
+ /* @__PURE__ */ l("p", { children: "WebUSB works in Chromium browsers on secure origins. Connect the iPhone over USB and approve the browser permission prompt." }),
278
+ /* @__PURE__ */ l(
279
+ "button",
280
+ {
281
+ type: "button",
282
+ className: "lr-device-install__primary",
283
+ disabled: n || !e.canRequestUSBAccess,
284
+ onClick: () => void e.requestUSBAccess(),
285
+ children: e.busyAction === "usb" ? "Selecting iPhone..." : "Allow USB access"
286
+ }
287
+ ),
288
+ e.device && /* @__PURE__ */ l("div", { className: "lr-device-install__device", children: `${e.device.productName ?? "iPhone"} ${e.device.serialNumber ?? ""}`.trim() }),
289
+ e.appleDevices.length > 0 && /* @__PURE__ */ a("label", { className: "lr-device-install__field", children: [
290
+ /* @__PURE__ */ l("span", { children: "Apple Developer devices" }),
291
+ /* @__PURE__ */ l(
292
+ "select",
293
+ {
294
+ multiple: !0,
295
+ value: e.selectedAppleDeviceIDs,
296
+ onChange: (i) => e.setSelectedAppleDeviceIDs(
297
+ Array.from(i.currentTarget.selectedOptions).map((u) => u.value)
298
+ ),
299
+ children: e.appleDevices.map((i) => /* @__PURE__ */ a("option", { value: i.deviceId ?? "", children: [
300
+ i.name ?? i.model ?? "Apple device",
301
+ " ",
302
+ i.deviceNumber ?? ""
303
+ ] }, i.deviceId ?? i.deviceNumber))
304
+ }
305
+ )
306
+ ] }),
307
+ e.device && !e.connectedAppleDeviceRegistered && /* @__PURE__ */ l(
308
+ "button",
309
+ {
310
+ type: "button",
311
+ className: "lr-device-install__secondary",
312
+ disabled: n || !!e.busyAction,
313
+ onClick: () => void e.registerConnectedAppleDevice(),
314
+ children: "Register connected iPhone"
315
+ }
316
+ ),
317
+ /* @__PURE__ */ l(
318
+ "button",
319
+ {
320
+ type: "button",
321
+ className: "lr-device-install__secondary",
322
+ disabled: n || !e.canPrepareAppleSigningAssets,
323
+ onClick: () => void e.prepareAppleSigningAssets(),
324
+ children: e.appleSigningStatus === "preparing-assets" ? "Preparing signing assets..." : "Generate certificate and profile"
325
+ }
326
+ ),
327
+ e.hasSigningAssets && /* @__PURE__ */ l("p", { children: "Signing assets are stored in this browser for the selected bundle and device." })
328
+ ] }),
329
+ c.id === "pair" && /* @__PURE__ */ a("div", { className: "lr-device-install__step-body", children: [
330
+ e.pairConfirmationRequired && /* @__PURE__ */ a("p", { children: [
331
+ "Unlock the iPhone and tap ",
332
+ /* @__PURE__ */ l("strong", { children: "Trust" }),
333
+ " in the system dialog, then confirm the pair record."
334
+ ] }),
335
+ /* @__PURE__ */ l(
336
+ "button",
337
+ {
338
+ type: "button",
339
+ className: "lr-device-install__primary",
340
+ disabled: n || !e.canPairBrowser,
341
+ onClick: () => void e.pairBrowser(),
342
+ children: e.busyAction === "pair" ? "Pairing..." : e.pairConfirmationRequired ? "Confirm pair record" : "Pair browser"
343
+ }
344
+ ),
345
+ /* @__PURE__ */ l("p", { children: e.hasPairRecord ? "Pair record is stored locally. Installation is available." : "Pair this browser once before installing." })
346
+ ] }),
347
+ c.id === "install" && /* @__PURE__ */ a("div", { className: "lr-device-install__step-body", children: [
348
+ /* @__PURE__ */ l(
349
+ "button",
350
+ {
351
+ type: "button",
352
+ className: "lr-device-install__primary",
353
+ disabled: n || !e.canInstall,
354
+ onClick: () => void e.startInstallation(),
355
+ children: e.busyAction === "install" ? "Installing..." : "Install last build"
356
+ }
357
+ ),
358
+ /* @__PURE__ */ l("button", { type: "button", className: "lr-device-install__secondary", onClick: e.stopRelay, children: "Stop relay" })
359
+ ] })
360
+ ]
361
+ },
362
+ c.id
363
+ )) }),
364
+ /* @__PURE__ */ a("footer", { className: "lr-device-install__logs", children: [
365
+ /* @__PURE__ */ l("h3", { children: "Progress" }),
366
+ /* @__PURE__ */ l("ol", { children: e.logs.map((c, p) => /* @__PURE__ */ l("li", { children: c }, `${p}-${c.slice(0, 24)}`)) })
367
+ ] })
368
+ ]
369
+ }
370
+ ) })
371
+ ] });
372
+ }
373
+ function I({
374
+ index: n,
375
+ step: t,
376
+ active: s,
377
+ status: r,
378
+ children: o
379
+ }) {
380
+ return /* @__PURE__ */ a("article", { className: _("lr-device-install__step", s && "lr-device-install__step--active"), children: [
381
+ /* @__PURE__ */ a("div", { className: "lr-device-install__step-header", children: [
382
+ /* @__PURE__ */ l("div", { className: "lr-device-install__step-number", children: n }),
383
+ /* @__PURE__ */ a("div", { children: [
384
+ /* @__PURE__ */ l("h3", { children: t.title }),
385
+ /* @__PURE__ */ l("p", { children: t.description })
386
+ ] }),
387
+ /* @__PURE__ */ l("span", { className: _("lr-device-install__status", `lr-device-install__status--${r}`), children: r })
388
+ ] }),
389
+ o
390
+ ] });
391
+ }
392
+ export {
393
+ U as D,
394
+ _ as c
395
+ };
@@ -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;display:grid;gap:12px;grid-template-columns:auto 1fr auto}.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__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{border:1px solid #d1d5db;border-radius:8px;font:inherit;padding:8px 10px}.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__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';
@@ -0,0 +1,70 @@
1
+ import { AppleDeveloperPortalDevice, AppleDeveloperPortalAppID, AppleDeveloperPortalTeam, BuildLogLine, DeviceInstallBuildStatus, DeviceInstallBusyAction, DeviceInstallStep, DeviceInstallStepStatus } from '../core/device-install';
2
+ type DeviceInstallStepStatuses = Record<DeviceInstallStep, DeviceInstallStepStatus>;
3
+ export type UseDeviceInstallOptions = {
4
+ apiUrl?: string;
5
+ token?: string;
6
+ };
7
+ export type UseDeviceInstallResult = {
8
+ currentStep: DeviceInstallStep;
9
+ stepStatuses: DeviceInstallStepStatuses;
10
+ device?: DeviceInstallDevice;
11
+ hasPairRecord: boolean;
12
+ hasSigningAssets: boolean;
13
+ pairConfirmationRequired: boolean;
14
+ logs: string[];
15
+ buildLogs: BuildLogLine[];
16
+ buildStatus: DeviceInstallBuildStatus;
17
+ appleSigningStatus: DeviceInstallAppleSigningStatus;
18
+ appleTeams: AppleDeveloperPortalTeam[];
19
+ appleDevices: AppleDeveloperPortalDevice[];
20
+ appleAppIDs: AppleDeveloperPortalAppID[];
21
+ applePortalSummary?: ApplePortalSummary;
22
+ selectedAppleTeamID?: string;
23
+ selectedAppleDeviceIDs: string[];
24
+ connectedAppleDeviceRegistered: boolean;
25
+ appleBundleID: string;
26
+ buildLogPanelOpen: boolean;
27
+ busyAction?: DeviceInstallBusyAction;
28
+ error?: string;
29
+ canBuild: boolean;
30
+ canPrepareAppleSigningAssets: boolean;
31
+ canRequestUSBAccess: boolean;
32
+ canPairBrowser: boolean;
33
+ canInstall: boolean;
34
+ setSigningFiles: (files: DeviceInstallSigningFiles) => void;
35
+ setAppleBundleID: (bundleID: string) => void;
36
+ setSelectedAppleDeviceIDs: (deviceIDs: string[]) => void;
37
+ setBuildLogPanelOpen: (open: boolean) => void;
38
+ startAppleIDLogin: (input: DeviceInstallAppleIDLoginInput) => Promise<void>;
39
+ submitAppleTwoFactorCode: (code: string) => Promise<void>;
40
+ setSelectedAppleTeamID: (teamID: string | undefined) => void;
41
+ clearAppleIDLogin: () => void;
42
+ registerConnectedAppleDevice: () => Promise<void>;
43
+ prepareAppleSigningAssets: () => Promise<void>;
44
+ startDeviceBuild: () => Promise<void>;
45
+ requestUSBAccess: () => Promise<void>;
46
+ pairBrowser: () => Promise<void>;
47
+ startInstallation: () => Promise<void>;
48
+ stopRelay: () => void;
49
+ };
50
+ export type DeviceInstallAppleSigningStatus = 'idle' | 'authenticating' | 'two-factor-required' | 'authenticated' | 'preparing-assets' | 'assets-ready' | 'using-cached-profile' | 'error';
51
+ export type DeviceInstallDevice = {
52
+ serialNumber?: string;
53
+ productName?: string;
54
+ manufacturerName?: string;
55
+ };
56
+ export type DeviceInstallSigningFiles = {
57
+ certificateFile?: File;
58
+ provisioningProfileFile?: File;
59
+ certificatePassword?: string;
60
+ };
61
+ export type DeviceInstallAppleIDLoginInput = {
62
+ accountName: string;
63
+ password: string;
64
+ };
65
+ export type ApplePortalSummary = {
66
+ certificateCount: number;
67
+ profileCount: number;
68
+ };
69
+ export declare function useDeviceInstall({ apiUrl, token, }: UseDeviceInstallOptions): UseDeviceInstallResult;
70
+ export {};