@limrun/ui 0.14.0-rc.4 → 0.14.0
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/README.md +9 -26
- package/dist/components/remote-control.d.ts +36 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1189 -1089
- package/package.json +10 -51
- package/src/components/remote-control.tsx +267 -0
- package/src/index.ts +1 -1
- package/vite.config.ts +0 -9
- package/dist/app-store-relay/index.cjs +0 -9
- package/dist/app-store-relay/index.d.ts +0 -100
- package/dist/app-store-relay/index.js +0 -484
- package/dist/app-store-relay/react.cjs +0 -1
- package/dist/app-store-relay/react.d.ts +0 -15
- package/dist/app-store-relay/react.js +0 -69
- package/dist/apple-credentials/index.cjs +0 -1
- package/dist/apple-credentials/index.d.ts +0 -59
- package/dist/apple-credentials/index.js +0 -227
- package/dist/browser-storage-BnO-Ma-e.mjs +0 -219
- package/dist/browser-storage-DLxIqZk5.js +0 -1
- package/dist/client-D1drDXxE.js +0 -1
- package/dist/client-DSuNtWDv.mjs +0 -184
- package/dist/core/device-install/apple/client.d.ts +0 -18
- package/dist/core/device-install/apple/crypto.d.ts +0 -20
- package/dist/core/device-install/apple/gsa-srp.d.ts +0 -26
- package/dist/core/device-install/apple/index.d.ts +0 -5
- package/dist/core/device-install/apple/provisioning.d.ts +0 -212
- package/dist/core/device-install/apple/relay.d.ts +0 -40
- package/dist/core/device-install/index.d.ts +0 -4
- package/dist/core/device-install/operations/index.d.ts +0 -6
- package/dist/core/device-install/operations/limbuild-client.d.ts +0 -43
- package/dist/core/device-install/operations/operations.d.ts +0 -47
- package/dist/core/device-install/operations/relay-client.d.ts +0 -26
- package/dist/core/device-install/operations/relay-protocol.d.ts +0 -27
- package/dist/core/device-install/operations/usbmux.d.ts +0 -32
- package/dist/core/device-install/operations/webusb.d.ts +0 -21
- package/dist/core/device-install/storage/browser-storage.d.ts +0 -56
- package/dist/core/device-install/storage/index.d.ts +0 -2
- package/dist/core/device-install/storage/secret-store.d.ts +0 -101
- package/dist/core/device-install/types.d.ts +0 -57
- package/dist/core/errors.d.ts +0 -1
- package/dist/core/play-publish/google.d.ts +0 -13
- package/dist/core/play-publish/publish.d.ts +0 -34
- package/dist/device-build/index.cjs +0 -1
- package/dist/device-build/index.d.ts +0 -4
- package/dist/device-build/index.js +0 -85
- package/dist/device-build/react.cjs +0 -1
- package/dist/device-build/react.d.ts +0 -21
- package/dist/device-build/react.js +0 -68
- package/dist/device-build/signing.d.ts +0 -20
- package/dist/device-install/demo/demo.d.ts +0 -0
- package/dist/device-install/index.cjs +0 -1
- package/dist/device-install/index.d.ts +0 -18
- package/dist/device-install/index.js +0 -591
- package/dist/device-install/react.cjs +0 -1
- package/dist/device-install/react.d.ts +0 -24
- package/dist/device-install/react.js +0 -105
- package/dist/errors-BSkqS7U-.js +0 -1
- package/dist/errors-gy8yQJos.mjs +0 -6
- package/dist/gsa-srp-Bme3JLEi.mjs +0 -266
- package/dist/gsa-srp-CCIfUz7Y.js +0 -1
- package/dist/index-ChhtuQ7e.js +0 -22
- package/dist/index-YDu8K9a4.mjs +0 -11279
- package/dist/limbuild-client-BagK_FWE.mjs +0 -83
- package/dist/limbuild-client-CVDwq54z.js +0 -1
- package/dist/play-publish/index.cjs +0 -1
- package/dist/play-publish/index.d.ts +0 -2
- package/dist/play-publish/index.js +0 -109
- package/dist/play-publish/react.cjs +0 -1
- package/dist/play-publish/react.d.ts +0 -31
- package/dist/play-publish/react.js +0 -91
- package/dist/provisioning-B_DefBEp.mjs +0 -239
- package/dist/provisioning-BlQMccX_.js +0 -1
- package/src/app-store-relay/index.test.ts +0 -60
- package/src/app-store-relay/index.ts +0 -511
- package/src/app-store-relay/react.ts +0 -131
- package/src/apple-credentials/index.test.ts +0 -158
- package/src/apple-credentials/index.ts +0 -241
- package/src/core/device-install/apple/client.ts +0 -143
- package/src/core/device-install/apple/crypto.ts +0 -205
- package/src/core/device-install/apple/gsa-srp.ts +0 -123
- package/src/core/device-install/apple/index.ts +0 -5
- package/src/core/device-install/apple/provisioning.test.ts +0 -84
- package/src/core/device-install/apple/provisioning.ts +0 -380
- package/src/core/device-install/apple/relay.ts +0 -182
- package/src/core/device-install/index.ts +0 -4
- package/src/core/device-install/operations/index.ts +0 -6
- package/src/core/device-install/operations/limbuild-client.ts +0 -144
- package/src/core/device-install/operations/operations.ts +0 -234
- package/src/core/device-install/operations/relay-client.ts +0 -286
- package/src/core/device-install/operations/relay-protocol.ts +0 -71
- package/src/core/device-install/operations/usbmux.ts +0 -270
- package/src/core/device-install/operations/webusb-dom.d.ts +0 -54
- package/src/core/device-install/operations/webusb.ts +0 -110
- package/src/core/device-install/storage/browser-storage.test.ts +0 -65
- package/src/core/device-install/storage/browser-storage.ts +0 -325
- package/src/core/device-install/storage/index.ts +0 -2
- package/src/core/device-install/storage/secret-store.ts +0 -298
- package/src/core/device-install/types.ts +0 -69
- package/src/core/errors.ts +0 -3
- package/src/core/play-publish/google.ts +0 -113
- package/src/core/play-publish/publish.test.ts +0 -68
- package/src/core/play-publish/publish.ts +0 -89
- package/src/device-build/index.ts +0 -42
- package/src/device-build/react.ts +0 -130
- package/src/device-build/signing.ts +0 -94
- package/src/device-install/README.md +0 -423
- package/src/device-install/demo/demo.css +0 -493
- package/src/device-install/demo/demo.tsx +0 -1061
- package/src/device-install/demo/index.html +0 -12
- package/src/device-install/index.ts +0 -50
- package/src/device-install/react.ts +0 -195
- package/src/play-publish/README.md +0 -66
- package/src/play-publish/index.ts +0 -12
- package/src/play-publish/react.ts +0 -208
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@limrun/ui",
|
|
3
|
-
"version": "0.14.0
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"tag": "next"
|
|
@@ -14,51 +14,6 @@
|
|
|
14
14
|
"import": "./dist/index.js",
|
|
15
15
|
"require": "./dist/index.cjs"
|
|
16
16
|
},
|
|
17
|
-
"./app-store-relay": {
|
|
18
|
-
"types": "./dist/app-store-relay/index.d.ts",
|
|
19
|
-
"import": "./dist/app-store-relay/index.js",
|
|
20
|
-
"require": "./dist/app-store-relay/index.cjs"
|
|
21
|
-
},
|
|
22
|
-
"./app-store-relay/react": {
|
|
23
|
-
"types": "./dist/app-store-relay/react.d.ts",
|
|
24
|
-
"import": "./dist/app-store-relay/react.js",
|
|
25
|
-
"require": "./dist/app-store-relay/react.cjs"
|
|
26
|
-
},
|
|
27
|
-
"./apple-credentials": {
|
|
28
|
-
"types": "./dist/apple-credentials/index.d.ts",
|
|
29
|
-
"import": "./dist/apple-credentials/index.js",
|
|
30
|
-
"require": "./dist/apple-credentials/index.cjs"
|
|
31
|
-
},
|
|
32
|
-
"./device-build": {
|
|
33
|
-
"types": "./dist/device-build/index.d.ts",
|
|
34
|
-
"import": "./dist/device-build/index.js",
|
|
35
|
-
"require": "./dist/device-build/index.cjs"
|
|
36
|
-
},
|
|
37
|
-
"./device-build/react": {
|
|
38
|
-
"types": "./dist/device-build/react.d.ts",
|
|
39
|
-
"import": "./dist/device-build/react.js",
|
|
40
|
-
"require": "./dist/device-build/react.cjs"
|
|
41
|
-
},
|
|
42
|
-
"./device-install": {
|
|
43
|
-
"types": "./dist/device-install/index.d.ts",
|
|
44
|
-
"import": "./dist/device-install/index.js",
|
|
45
|
-
"require": "./dist/device-install/index.cjs"
|
|
46
|
-
},
|
|
47
|
-
"./device-install/react": {
|
|
48
|
-
"types": "./dist/device-install/react.d.ts",
|
|
49
|
-
"import": "./dist/device-install/react.js",
|
|
50
|
-
"require": "./dist/device-install/react.cjs"
|
|
51
|
-
},
|
|
52
|
-
"./play-publish": {
|
|
53
|
-
"types": "./dist/play-publish/index.d.ts",
|
|
54
|
-
"import": "./dist/play-publish/index.js",
|
|
55
|
-
"require": "./dist/play-publish/index.cjs"
|
|
56
|
-
},
|
|
57
|
-
"./play-publish/react": {
|
|
58
|
-
"types": "./dist/play-publish/react.d.ts",
|
|
59
|
-
"import": "./dist/play-publish/react.js",
|
|
60
|
-
"require": "./dist/play-publish/react.cjs"
|
|
61
|
-
},
|
|
62
17
|
"./package.json": "./package.json"
|
|
63
18
|
},
|
|
64
19
|
"scripts": {
|
|
@@ -76,23 +31,27 @@
|
|
|
76
31
|
"directory": "packages/ui"
|
|
77
32
|
},
|
|
78
33
|
"license": "MIT",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
36
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
37
|
+
},
|
|
79
38
|
"devDependencies": {
|
|
80
|
-
"@types/node-forge": "^1.3.14",
|
|
81
39
|
"@types/react": "^19.1.12",
|
|
82
40
|
"@types/react-dom": "^19.1.9",
|
|
83
41
|
"@vitejs/plugin-react-swc": "^4.0.1",
|
|
42
|
+
"eslint": "^9.39.1",
|
|
84
43
|
"jsdom": "^26.0.0",
|
|
85
44
|
"path": "^0.12.7",
|
|
86
45
|
"react": "^19.1.1",
|
|
87
46
|
"react-dom": "^19.1.1",
|
|
47
|
+
"typescript": "5.8.3",
|
|
48
|
+
"typescript-eslint": "8.31.1",
|
|
88
49
|
"vite": "^7.1.4",
|
|
89
50
|
"vite-plugin-dts": "^4.5.4",
|
|
90
51
|
"vite-plugin-lib-inject-css": "^2.2.2",
|
|
91
|
-
"vitest": "^2.
|
|
52
|
+
"vitest": "^3.2.6"
|
|
92
53
|
},
|
|
93
54
|
"dependencies": {
|
|
94
|
-
"
|
|
95
|
-
"clsx": "^2.1.1",
|
|
96
|
-
"node-forge": "^1.4.0"
|
|
55
|
+
"clsx": "^2.1.1"
|
|
97
56
|
}
|
|
98
57
|
}
|
|
@@ -233,6 +233,45 @@ interface RemoteControlProps {
|
|
|
233
233
|
* 16:9 / 1920×1080 — applies).
|
|
234
234
|
*/
|
|
235
235
|
cameraAspect?: CameraAspect;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* iOS only: when true, capture the user's microphone via
|
|
239
|
+
* `getUserMedia({ audio: true })` and stream it live into the
|
|
240
|
+
* simulator's mock microphone. Unlike the camera (which is
|
|
241
|
+
* demand-driven by apps inside the sim), the microphone is
|
|
242
|
+
* user-driven: flip this prop from a button in your UI. The
|
|
243
|
+
* component handles the browser permission prompt, the WebRTC
|
|
244
|
+
* track attach (no SDP renegotiation — the audio slot is
|
|
245
|
+
* pre-allocated) and the `microphoneStart`/`microphoneStop`
|
|
246
|
+
* signaling to the host. Progress and failures are reported via
|
|
247
|
+
* `onMicrophoneStateChange`. Ignored on Android instances.
|
|
248
|
+
*/
|
|
249
|
+
microphoneEnabled?: boolean;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Fires whenever the live-microphone pipeline changes state:
|
|
253
|
+
* after an enable attempt resolves (granted or denied), when the
|
|
254
|
+
* host acknowledges or rejects the stream, when the browser
|
|
255
|
+
* revokes the track mid-stream, and on disable. Use it to render
|
|
256
|
+
* the mic button's on/off/error state.
|
|
257
|
+
*/
|
|
258
|
+
onMicrophoneStateChange?: (state: MicrophoneState) => void;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Snapshot of the live-microphone pipeline, reported through
|
|
263
|
+
* `onMicrophoneStateChange`.
|
|
264
|
+
*/
|
|
265
|
+
export interface MicrophoneState {
|
|
266
|
+
/** True while the browser mic is captured and streaming to the sim. */
|
|
267
|
+
active: boolean;
|
|
268
|
+
/**
|
|
269
|
+
* Human-readable failure from the last attempt, if any (permission
|
|
270
|
+
* denied, no device, host rejection, ...).
|
|
271
|
+
*/
|
|
272
|
+
error?: string;
|
|
273
|
+
/** Device label of the captured microphone, when available. */
|
|
274
|
+
label?: string;
|
|
236
275
|
}
|
|
237
276
|
|
|
238
277
|
/**
|
|
@@ -510,6 +549,8 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
510
549
|
onCameraStats,
|
|
511
550
|
cameraResolutionCap = 'auto',
|
|
512
551
|
cameraAspect,
|
|
552
|
+
microphoneEnabled = false,
|
|
553
|
+
onMicrophoneStateChange,
|
|
513
554
|
}: RemoteControlProps,
|
|
514
555
|
ref,
|
|
515
556
|
) => {
|
|
@@ -594,6 +635,28 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
594
635
|
packetsSent?: number;
|
|
595
636
|
packetsLost?: number;
|
|
596
637
|
} | null>(null);
|
|
638
|
+
// User-driven outbound microphone state (iOS only). Unlike the
|
|
639
|
+
// camera, the mic is toggled by the `microphoneEnabled` prop; the
|
|
640
|
+
// track rides a pre-allocated sendonly audio transceiver so
|
|
641
|
+
// enabling/disabling is just a `replaceTrack`, plus a
|
|
642
|
+
// `microphoneStart`/`microphoneStop` WS signal so the host's
|
|
643
|
+
// audio state machine switches its source.
|
|
644
|
+
const microphoneEnabledRef = useRef(microphoneEnabled);
|
|
645
|
+
microphoneEnabledRef.current = microphoneEnabled;
|
|
646
|
+
const onMicrophoneStateChangeRef = useRef(onMicrophoneStateChange);
|
|
647
|
+
onMicrophoneStateChangeRef.current = onMicrophoneStateChange;
|
|
648
|
+
const outboundMicSenderRef = useRef<RTCRtpSender | null>(null);
|
|
649
|
+
const outboundMicStreamRef = useRef<MediaStream | null>(null);
|
|
650
|
+
// Bumped by detach and teardown so an attach suspended on an await
|
|
651
|
+
// (the getUserMedia prompt) detects it was superseded and bails.
|
|
652
|
+
const micGenerationRef = useRef(0);
|
|
653
|
+
// Serializes attach/detach work so their awaits (replaceTrack on the
|
|
654
|
+
// shared sender) can never interleave and undo each other's effects.
|
|
655
|
+
const micOpQueueRef = useRef<Promise<void>>(Promise.resolve());
|
|
656
|
+
// Correlates the in-flight `microphoneStart` with its result so a
|
|
657
|
+
// host-side rejection (e.g. no loopback device on the node) can
|
|
658
|
+
// tear the capture back down and surface the error.
|
|
659
|
+
const micStartPendingIdRef = useRef<string | null>(null);
|
|
597
660
|
const firstFrameShownRef = useRef(false);
|
|
598
661
|
const pendingScreenshotResolversRef = useRef<
|
|
599
662
|
Map<string, (value: ScreenshotData | PromiseLike<ScreenshotData>) => void>
|
|
@@ -1694,6 +1757,149 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
1694
1757
|
stopMediaStream(stream);
|
|
1695
1758
|
};
|
|
1696
1759
|
|
|
1760
|
+
// Runs one attach/detach operation after all previously queued ones,
|
|
1761
|
+
// so two operations' awaits never interleave on the shared sender (a
|
|
1762
|
+
// stale detach could otherwise clear a fresh attach's track, or send
|
|
1763
|
+
// `microphoneStop` after its `microphoneStart`).
|
|
1764
|
+
const runMicOp = (op: () => Promise<void>): Promise<void> => {
|
|
1765
|
+
const next = micOpQueueRef.current.then(op).catch((err) => {
|
|
1766
|
+
debugWarn('microphone operation failed:', err);
|
|
1767
|
+
});
|
|
1768
|
+
micOpQueueRef.current = next;
|
|
1769
|
+
return next;
|
|
1770
|
+
};
|
|
1771
|
+
|
|
1772
|
+
// Capture the user's microphone and stream it to the simulator's
|
|
1773
|
+
// mock microphone. Safe to call redundantly: bails when already
|
|
1774
|
+
// attached, when the connection isn't up yet (the ICE-connected
|
|
1775
|
+
// handler re-invokes it), or when the prop flipped off mid-prompt.
|
|
1776
|
+
// Does NOT bump the generation: a redundant call (e.g. the ICE
|
|
1777
|
+
// handler firing on both `connected` and `completed`) must not
|
|
1778
|
+
// cancel an attach already in flight; only detach/teardown cancel.
|
|
1779
|
+
const attachMicrophone = (): Promise<void> => {
|
|
1780
|
+
if (platform !== 'ios') return Promise.resolve();
|
|
1781
|
+
return runMicOp(() => attachMicrophoneOp());
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
const attachMicrophoneOp = async () => {
|
|
1785
|
+
const generation = micGenerationRef.current;
|
|
1786
|
+
const isCurrent = () => generation === micGenerationRef.current && microphoneEnabledRef.current;
|
|
1787
|
+
const reportMicError = (error: string) => {
|
|
1788
|
+
safeInvoke('onMicrophoneStateChange', onMicrophoneStateChangeRef.current, {
|
|
1789
|
+
active: false,
|
|
1790
|
+
error,
|
|
1791
|
+
});
|
|
1792
|
+
};
|
|
1793
|
+
if (!isCurrent()) return;
|
|
1794
|
+
const ws = wsRef.current;
|
|
1795
|
+
const sender = outboundMicSenderRef.current;
|
|
1796
|
+
if (!ws || ws.readyState !== WebSocket.OPEN || !sender) {
|
|
1797
|
+
// Not connected yet — the post-connect hook retries while the
|
|
1798
|
+
// prop is still on.
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
if (outboundMicStreamRef.current) return;
|
|
1802
|
+
if (!navigator.mediaDevices || typeof navigator.mediaDevices.getUserMedia !== 'function') {
|
|
1803
|
+
// eslint-disable-next-line no-console
|
|
1804
|
+
console.warn(
|
|
1805
|
+
'[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. ' +
|
|
1806
|
+
'getUserMedia requires a secure context (https or http://localhost).',
|
|
1807
|
+
);
|
|
1808
|
+
reportMicError('Microphone capture requires a secure context (https)');
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
let stream: MediaStream | null = null;
|
|
1812
|
+
try {
|
|
1813
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
|
|
1814
|
+
} catch (err) {
|
|
1815
|
+
// eslint-disable-next-line no-console
|
|
1816
|
+
console.warn('[RemoteControl] microphone getUserMedia denied/failed:', err);
|
|
1817
|
+
}
|
|
1818
|
+
if (!isCurrent()) {
|
|
1819
|
+
if (stream) stopMediaStream(stream);
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
if (!stream) {
|
|
1823
|
+
reportMicError('Microphone permission denied or no device available');
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
const audioTrack = stream.getAudioTracks()[0] ?? null;
|
|
1827
|
+
if (!audioTrack) {
|
|
1828
|
+
stopMediaStream(stream);
|
|
1829
|
+
reportMicError('Captured stream has no audio track');
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
try {
|
|
1833
|
+
await sender.replaceTrack(audioTrack);
|
|
1834
|
+
} catch (err) {
|
|
1835
|
+
debugWarn('replaceTrack(audioTrack) failed:', err);
|
|
1836
|
+
stopMediaStream(stream);
|
|
1837
|
+
reportMicError('Failed to attach the microphone track to the connection');
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
if (!isCurrent()) {
|
|
1841
|
+
try {
|
|
1842
|
+
await sender.replaceTrack(null);
|
|
1843
|
+
} catch (err) {
|
|
1844
|
+
debugWarn('replaceTrack(null) on stale mic attach failed:', err);
|
|
1845
|
+
}
|
|
1846
|
+
stopMediaStream(stream);
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
outboundMicStreamRef.current = stream;
|
|
1850
|
+
// If the browser revokes the track later (user clicks Stop in
|
|
1851
|
+
// the tab's mic indicator, device unplugged, ...) tear down and
|
|
1852
|
+
// tell the host, so the sim's mic goes back to silence instead
|
|
1853
|
+
// of freezing on the last buffer.
|
|
1854
|
+
audioTrack.onended = () => {
|
|
1855
|
+
if (outboundMicStreamRef.current !== stream) return;
|
|
1856
|
+
void detachMicrophone('microphone capture ended by the browser');
|
|
1857
|
+
};
|
|
1858
|
+
const id = `ui-mic-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1859
|
+
micStartPendingIdRef.current = id;
|
|
1860
|
+
ws.send(JSON.stringify({ type: 'microphoneStart', id }));
|
|
1861
|
+
safeInvoke('onMicrophoneStateChange', onMicrophoneStateChangeRef.current, {
|
|
1862
|
+
active: true,
|
|
1863
|
+
label: audioTrack.label || undefined,
|
|
1864
|
+
});
|
|
1865
|
+
};
|
|
1866
|
+
|
|
1867
|
+
// Stop the live microphone: drop the track from the sender, stop
|
|
1868
|
+
// the capture (turning the browser's mic indicator off) and tell
|
|
1869
|
+
// the host to switch its audio source back to silence. Safe to
|
|
1870
|
+
// call when nothing is attached.
|
|
1871
|
+
const detachMicrophone = (error?: string): Promise<void> => {
|
|
1872
|
+
// Bump synchronously (not on the queue) so an attach that is
|
|
1873
|
+
// suspended on an await bails at its next checkpoint even while
|
|
1874
|
+
// it still owns the queue.
|
|
1875
|
+
++micGenerationRef.current;
|
|
1876
|
+
micStartPendingIdRef.current = null;
|
|
1877
|
+
return runMicOp(async () => {
|
|
1878
|
+
const sender = outboundMicSenderRef.current;
|
|
1879
|
+
const stream = outboundMicStreamRef.current;
|
|
1880
|
+
outboundMicStreamRef.current = null;
|
|
1881
|
+
if (sender && stream) {
|
|
1882
|
+
try {
|
|
1883
|
+
await sender.replaceTrack(null);
|
|
1884
|
+
} catch (err) {
|
|
1885
|
+
debugWarn('replaceTrack(null) on mic detach failed:', err);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
if (stream) stopMediaStream(stream);
|
|
1889
|
+
const ws = wsRef.current;
|
|
1890
|
+
if (stream && ws && ws.readyState === WebSocket.OPEN) {
|
|
1891
|
+
const id = `ui-mic-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1892
|
+
ws.send(JSON.stringify({ type: 'microphoneStop', id }));
|
|
1893
|
+
}
|
|
1894
|
+
if (stream || error) {
|
|
1895
|
+
safeInvoke('onMicrophoneStateChange', onMicrophoneStateChangeRef.current, {
|
|
1896
|
+
active: false,
|
|
1897
|
+
...(error !== undefined && { error }),
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
});
|
|
1901
|
+
};
|
|
1902
|
+
|
|
1697
1903
|
// Translate the user-facing resolution cap into a
|
|
1698
1904
|
// MediaTrackConstraints fragment we can feed `getUserMedia`
|
|
1699
1905
|
// or `applyConstraints`. Always returns a 30 fps ceiling so
|
|
@@ -1845,6 +2051,22 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
1845
2051
|
stopCameraStatsPoller();
|
|
1846
2052
|
stopOutboundLocalStream();
|
|
1847
2053
|
outboundCameraSenderRef.current = null;
|
|
2054
|
+
// Same for the live microphone. No `microphoneStop` signal here —
|
|
2055
|
+
// the WS is going away with the connection; if `microphoneEnabled`
|
|
2056
|
+
// is still on, the post-reconnect hook re-attaches.
|
|
2057
|
+
++micGenerationRef.current;
|
|
2058
|
+
micStartPendingIdRef.current = null;
|
|
2059
|
+
if (outboundMicStreamRef.current) {
|
|
2060
|
+
stopMediaStream(outboundMicStreamRef.current);
|
|
2061
|
+
outboundMicStreamRef.current = null;
|
|
2062
|
+
// The capture is gone; report it so consumers don't keep a stale
|
|
2063
|
+
// `active: true` across drops (a re-attach after reconnect
|
|
2064
|
+
// reports again).
|
|
2065
|
+
safeInvoke('onMicrophoneStateChange', onMicrophoneStateChangeRef.current, {
|
|
2066
|
+
active: false,
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
outboundMicSenderRef.current = null;
|
|
1848
2070
|
// A scheduled cursor flush would otherwise call setState on a
|
|
1849
2071
|
// teardown component once the next frame runs.
|
|
1850
2072
|
if (cursorRafIdRef.current !== undefined) {
|
|
@@ -2162,6 +2384,18 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
2162
2384
|
: null;
|
|
2163
2385
|
outboundCameraSenderRef.current = outboundCameraTransceiver?.sender ?? null;
|
|
2164
2386
|
|
|
2387
|
+
// Same pre-allocation for the live microphone: a sendonly audio
|
|
2388
|
+
// slot negotiated once at connection setup, so toggling the mic
|
|
2389
|
+
// later is just `replaceTrack` — no SDP renegotiation. iOS only,
|
|
2390
|
+
// like the camera.
|
|
2391
|
+
const outboundMicTransceiver =
|
|
2392
|
+
platform === 'ios' ?
|
|
2393
|
+
peerConnection.addTransceiver('audio', {
|
|
2394
|
+
direction: 'sendonly',
|
|
2395
|
+
})
|
|
2396
|
+
: null;
|
|
2397
|
+
outboundMicSenderRef.current = outboundMicTransceiver?.sender ?? null;
|
|
2398
|
+
|
|
2165
2399
|
// As hardware encoder, we use H265 for iOS and VP9 for Android.
|
|
2166
2400
|
// We make sure these two are the first ones in the list.
|
|
2167
2401
|
// If not, the fallback is H264 which is also hardware accelerated, although not as good,
|
|
@@ -2383,6 +2617,11 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
2383
2617
|
updateStatus('ICE state: ' + iceState);
|
|
2384
2618
|
if (iceState === 'connected' || iceState === 'completed') {
|
|
2385
2619
|
clearIceDisconnectedGrace();
|
|
2620
|
+
// Re-attach the live microphone across reconnects (or apply a
|
|
2621
|
+
// prop that was flipped on before the connection was up).
|
|
2622
|
+
if (microphoneEnabledRef.current && !outboundMicStreamRef.current) {
|
|
2623
|
+
void attachMicrophone();
|
|
2624
|
+
}
|
|
2386
2625
|
return;
|
|
2387
2626
|
}
|
|
2388
2627
|
if (iceState === 'failed') {
|
|
@@ -2780,6 +3019,22 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
2780
3019
|
startCameraStatsPoller();
|
|
2781
3020
|
break;
|
|
2782
3021
|
}
|
|
3022
|
+
case 'microphoneStartResult': {
|
|
3023
|
+
if (micStartPendingIdRef.current === null || message.id !== micStartPendingIdRef.current) {
|
|
3024
|
+
break;
|
|
3025
|
+
}
|
|
3026
|
+
micStartPendingIdRef.current = null;
|
|
3027
|
+
if (typeof message.error === 'string') {
|
|
3028
|
+
// Host rejected the stream (e.g. no loopback device
|
|
3029
|
+
// assigned on the node). Tear the capture back down so
|
|
3030
|
+
// the browser's mic indicator doesn't stay lit for a
|
|
3031
|
+
// stream nobody hears.
|
|
3032
|
+
// eslint-disable-next-line no-console
|
|
3033
|
+
console.warn('[RemoteControl] microphoneStart rejected by host:', message.error);
|
|
3034
|
+
void detachMicrophone(message.error);
|
|
3035
|
+
}
|
|
3036
|
+
break;
|
|
3037
|
+
}
|
|
2783
3038
|
case 'terminateAppResult':
|
|
2784
3039
|
if (typeof message.id !== 'string') {
|
|
2785
3040
|
debugWarn('Received invalid terminateApp result message:', message);
|
|
@@ -2906,6 +3161,18 @@ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>
|
|
|
2906
3161
|
}
|
|
2907
3162
|
}, [cameraAspect]);
|
|
2908
3163
|
|
|
3164
|
+
// Drive the live microphone from the `microphoneEnabled` prop.
|
|
3165
|
+
// When flipped on before the connection is up, attachMicrophone
|
|
3166
|
+
// bails and the ICE-connected handler picks it up instead.
|
|
3167
|
+
useEffect(() => {
|
|
3168
|
+
if (microphoneEnabled) {
|
|
3169
|
+
void attachMicrophone();
|
|
3170
|
+
} else {
|
|
3171
|
+
void detachMicrophone();
|
|
3172
|
+
}
|
|
3173
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3174
|
+
}, [microphoneEnabled]);
|
|
3175
|
+
|
|
2909
3176
|
useEffect(() => {
|
|
2910
3177
|
// Reset video loaded state when connection params change
|
|
2911
3178
|
setVideoLoaded(false);
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { RemoteControl } from './components/remote-control';
|
|
2
|
-
export type { RemoteControlHandle } from './components/remote-control';
|
|
2
|
+
export type { RemoteControlHandle, MicrophoneState } from './components/remote-control';
|
|
3
3
|
|
|
4
4
|
// Accessibility / inspect-mode types and helpers. Exported so customers can
|
|
5
5
|
// build their own side panels, search UIs, or agent-driven inspectors on top
|
package/vite.config.ts
CHANGED
|
@@ -11,15 +11,6 @@ export default defineConfig({
|
|
|
11
11
|
lib: {
|
|
12
12
|
entry: {
|
|
13
13
|
index: resolve(__dirname, 'src/index.ts'),
|
|
14
|
-
'app-store-relay/index': resolve(__dirname, 'src/app-store-relay/index.ts'),
|
|
15
|
-
'app-store-relay/react': resolve(__dirname, 'src/app-store-relay/react.ts'),
|
|
16
|
-
'apple-credentials/index': resolve(__dirname, 'src/apple-credentials/index.ts'),
|
|
17
|
-
'device-build/index': resolve(__dirname, 'src/device-build/index.ts'),
|
|
18
|
-
'device-build/react': resolve(__dirname, 'src/device-build/react.ts'),
|
|
19
|
-
'device-install/index': resolve(__dirname, 'src/device-install/index.ts'),
|
|
20
|
-
'device-install/react': resolve(__dirname, 'src/device-install/react.ts'),
|
|
21
|
-
'play-publish/index': resolve(__dirname, 'src/play-publish/index.ts'),
|
|
22
|
-
'play-publish/react': resolve(__dirname, 'src/play-publish/react.ts'),
|
|
23
14
|
},
|
|
24
15
|
name: 'LimrunUI',
|
|
25
16
|
formats: ['es', 'cjs'],
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("../client-D1drDXxE.js"),u=require("../index-ChhtuQ7e.js"),P=require("../gsa-srp-CCIfUz7Y.js"),p=require("../provisioning-BlQMccX_.js"),I={name:"RSASSA-PKCS1-v1_5",modulusLength:2048,publicExponent:new Uint8Array([1,0,1]),hash:"SHA-256"};async function S(e){if(!crypto.subtle)throw new Error("WebCrypto is not available in this browser.");const t=await crypto.subtle.generateKey(I,!0,["sign","verify"]),r=new Uint8Array(await crypto.subtle.exportKey("spki",t.publicKey)),n=d(R(0),h(e),r,C(0,new Uint8Array)),i=new Uint8Array(await crypto.subtle.sign("RSASSA-PKCS1-v1_5",t.privateKey,L(n))),o=d(n,d(b("1.2.840.113549.1.1.11"),T()),x(i)),l=new Uint8Array(await crypto.subtle.exportKey("pkcs8",t.privateKey));return{privateKey:t.privateKey,privateKeyPKCS8Base64:y(l),publicKeySPKIBase64:y(r),csrPEM:k("CERTIFICATE REQUEST",o),csrBase64:y(o)}}function q(e){if(!e.certificateBase64&&!e.certificatePEM)throw new Error("certificateBase64 or certificatePEM is required.");const t=u.forge.pki.privateKeyFromPem(F("PRIVATE KEY",e.privateKeyPKCS8Base64)),r=e.certificatePEM?u.forge.pki.certificateFromPem(e.certificatePEM):u.forge.pki.certificateFromAsn1(u.forge.asn1.fromDer(u.forge.util.createBuffer(N(e.certificateBase64)))),n=u.forge.pkcs12.toPkcs12Asn1(t,[r],e.password,{algorithm:"3des",friendlyName:e.friendlyName}),i=u.forge.asn1.toDer(n).getBytes();return O(i)}function h(e){const t=[v("2.5.4.3",K(e.commonName))];return e.emailAddress&&t.push(v("1.2.840.113549.1.9.1",E(e.emailAddress))),d(...t)}function v(e,t){return B(d(b(e),t))}function d(...e){return c(48,A(...e))}function B(...e){return c(49,A(...e))}function C(e,t){return c(160+e,t)}function R(e){return c(2,new Uint8Array([e]))}function T(){return new Uint8Array([5,0])}function K(e){return c(12,new TextEncoder().encode(e))}function E(e){return c(22,new TextEncoder().encode(e))}function x(e){return c(3,A(new Uint8Array([0]),e))}function b(e){const t=e.split(".").map(n=>parseInt(n,10));if(t.length<2||t.some(n=>!Number.isFinite(n)))throw new Error(`Invalid OID: ${e}`);const r=[t[0]*40+t[1]];for(const n of t.slice(2)){const i=[n&127];let o=n>>7;for(;o>0;)i.unshift(o&127|128),o>>=7;r.push(...i)}return c(6,new Uint8Array(r))}function c(e,t){return A(new Uint8Array([e]),U(t.byteLength),t)}function U(e){if(e<128)return new Uint8Array([e]);const t=[];let r=e;for(;r>0;)t.unshift(r&255),r>>=8;return new Uint8Array([128|t.length,...t])}function A(...e){const t=e.reduce((i,o)=>i+o.byteLength,0),r=new Uint8Array(t);let n=0;for(const i of e)r.set(i,n),n+=i.byteLength;return r}function k(e,t){const n=y(t).match(/.{1,64}/g)??[];return`-----BEGIN ${e}-----
|
|
2
|
-
${n.join(`
|
|
3
|
-
`)}
|
|
4
|
-
-----END ${e}-----
|
|
5
|
-
`}function F(e,t){const r=t.match(/.{1,64}/g)??[];return`-----BEGIN ${e}-----
|
|
6
|
-
${r.join(`
|
|
7
|
-
`)}
|
|
8
|
-
-----END ${e}-----
|
|
9
|
-
`}function y(e){let t="";for(const r of e)t+=String.fromCharCode(r);return btoa(t)}function O(e){return btoa(e)}function N(e){return atob(e)}function L(e){const t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function a({relay:e,request:t,label:r="Apple Developer Portal request",validatePortalResponse:n=!0,mapBody:i}){const o=await s.proxyProvisioningRequest(e,t);return n&&g(o.body,r),i?i(o.body,o):o}async function $(e){return a({...e,request:p.listTeamsRequest(),label:"Apple Developer team list",mapBody:t=>ne([...t?.teams??[],...t?.availableProviders??[],...t?.provider?[t.provider]:[]])})}async function W({certificateKind:e="development",teamId:t="",...r}){return a({...r,request:e==="distribution"?p.findDistributionCertificatesRequest(t):p.findDevelopmentCertificatesRequest(t),label:"Apple Developer certificate list",mapBody:n=>n?.certRequests??[]})}async function G({certificateKind:e="development",teamId:t="",csrPEM:r,...n}){return a({...n,request:e==="distribution"?p.submitDistributionCSRRequest({csrPEM:r,teamID:t}):p.submitDevelopmentCSRRequest({csrPEM:r,teamID:t}),label:e==="distribution"?"Apple Distribution certificate creation":"Apple Development certificate creation",mapBody:i=>i?.certRequest})}async function H({certificateKind:e="development",certificateId:t,teamId:r="",...n}){return a({...n,request:e==="distribution"?p.downloadDistributionCertificateRequest(t,r):p.downloadCertificateRequest(t,r),label:"Apple certificate download",validatePortalResponse:!1,mapBody:(i,o)=>o})}async function M({certificateKind:e="development",certificateId:t,teamId:r="",...n}){return a({...n,request:{method:"POST",path:"/account/ios/certificate/revokeCertificate.action",payload:{teamId:r,certificateId:t,type:e==="distribution"?"WXV89964HE":"83Q87W3TGH"}},label:"Apple certificate deletion",mapBody:i=>i})}async function _({teamId:e="",search:t="",...r}){const n=t.trim().toLowerCase();return a({...r,request:p.findBundleIDRequest({bundleID:t,teamID:e}),label:"Apple bundle ID list",mapBody:i=>{const o=i?.appIds??[];return n?o.filter(l=>[l.identifier,l.bundleId,l.name].some(f=>typeof f=="string"&&f.toLowerCase().includes(n))):o}})}async function j({teamId:e="",bundleId:t,name:r,...n}){return a({...n,request:p.createBundleIDRequest({bundleID:t,teamID:e,name:r}),label:"Apple bundle ID creation",mapBody:i=>i?.appId})}async function V({teamId:e="",appIdId:t,bundleId:r,name:n,...i}){return a({...i,request:{method:"POST",path:"/account/ios/identifiers/updateAppId.action",payload:{teamId:e,appIdId:t,...r?{identifier:r}:{},...n?{name:n}:{}}},label:"Apple bundle ID update",mapBody:o=>o?.appId})}async function Q({teamId:e="",appIdId:t,...r}){return a({...r,request:{method:"POST",path:"/account/ios/identifiers/deleteAppId.action",payload:{teamId:e,appIdId:t}},label:"Apple bundle ID deletion",mapBody:n=>n})}async function z({teamId:e="",deviceUDID:t="",...r}){const n=D(t);return a({...r,request:p.findDeviceRequest({deviceUDID:t,teamID:e}),label:"Apple device list",mapBody:i=>{const o=i?.devices??[];return n?o.filter(l=>D(l.deviceNumber)===n):o}})}function D(e){return(e??"").replace(/-/g,"").replace(/[^a-fA-F0-9]/g,"").toUpperCase()}async function J({teamId:e="",deviceUDID:t,name:r,...n}){return a({...n,request:p.registerDeviceRequest({deviceUDID:t,teamID:e,name:r}),label:"Apple device registration",mapBody:i=>i?.device})}async function X({teamId:e="",deviceId:t,name:r,...n}){return a({...n,request:{method:"POST",path:"/account/ios/device/updateDevice.action",payload:{teamId:e,deviceId:t,...r?{name:r}:{}}},label:"Apple device update",mapBody:i=>i?.device})}async function Y({teamId:e="",deviceId:t,...r}){return a({...r,request:{method:"POST",path:"/account/ios/device/deleteDevice.action",payload:{teamId:e,deviceId:t}},label:"Apple device deletion",mapBody:n=>n})}async function Z({profileKind:e="development",teamId:t="",bundleId:r="",...n}){return a({...n,request:e==="adhoc"?p.findAdHocProfilesRequest({bundleID:r,teamID:t}):p.findDevelopmentProfilesRequest({bundleID:r,teamID:t}),label:"Apple provisioning profile list",mapBody:i=>i?.provisioningProfiles??[]})}async function ee({profileKind:e="development",teamId:t="",bundleId:r,appIdId:n,certificateIds:i,deviceIds:o,name:l,...f}){const[m]=i;if(!m)throw new Error("At least one certificate ID is required to create an Apple provisioning profile.");return a({...f,request:e==="adhoc"?p.createAdHocProfileRequest({bundleID:r,teamID:t,appIDID:n,certificateID:m,deviceIDs:o,name:l}):p.createDevelopmentProfileRequest({bundleID:r,teamID:t,appIDID:n,certificateID:m,deviceIDs:o,name:l}),label:"Apple provisioning profile creation",mapBody:w=>w?.provisioningProfile})}async function te({teamId:e="",profileId:t,...r}){return a({...r,request:p.downloadProfileRequest(t,e),label:"Apple provisioning profile download",validatePortalResponse:!1,mapBody:(n,i)=>i})}async function re({teamId:e="",profileId:t,...r}){return a({...r,request:{method:"POST",path:"/account/ios/profile/deleteProvisioningProfile.action",payload:{teamId:e,provisioningProfileId:t}},label:"Apple provisioning profile deletion",mapBody:n=>n})}function g(e,t){if(!e)throw new Error(`${t} returned an empty response.`);if(e.resultCode!==void 0&&e.resultCode!==0)throw new Error(`${t} failed: ${e.userString??e.resultString??e.resultCode}`)}function ne(e){const t=new Set,r=[];for(const n of e){const i=String(n.teamId??n.providerId??n.publicProviderId??n.name??JSON.stringify(n));t.has(i)||(t.add(i),r.push(n))}return r}exports.AppleRelayWebSocketClient=s.AppleRelayWebSocketClient;exports.fetchAppleAccountSession=s.fetchAppleAccountSession;exports.openAppleRelayWebSocket=s.openAppleRelayWebSocket;exports.proxyPhoneTwoFactorCode=s.proxyPhoneTwoFactorCode;exports.proxySrpComplete=s.proxySrpComplete;exports.proxySrpInit=s.proxySrpInit;exports.proxyTwoFactorCode=s.proxyTwoFactorCode;exports.startBrowserOwnedAppleIDLogin=s.startBrowserOwnedAppleIDLogin;exports.triggerPhoneTwoFactor=s.triggerPhoneTwoFactor;exports.triggerTrustedDeviceTwoFactor=s.triggerTrustedDeviceTwoFactor;exports.AppleGsaSrpClient=P.AppleGsaSrpClient;exports.assertAppleDeveloperPortalResponseOK=g;exports.createAppleBundleID=j;exports.createAppleCertificate=G;exports.createAppleProfile=ee;exports.deleteAppleBundleID=Q;exports.deleteAppleCertificate=M;exports.deleteAppleDevice=Y;exports.deleteAppleProfile=re;exports.downloadAppleCertificate=H;exports.downloadAppleProfile=te;exports.exportAppleCertificateP12=q;exports.generateAppleSigningKeyAndCSR=S;exports.listAppleBundleIDs=_;exports.listAppleCertificates=W;exports.listAppleDevices=z;exports.listAppleProfiles=Z;exports.listAppleTeams=$;exports.registerAppleDevice=J;exports.requestAppleProvisioning=a;exports.updateAppleBundleID=V;exports.updateAppleDevice=X;
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { AppleDeveloperPortalAppID, AppleDeveloperPortalDevice, AppleDeveloperPortalResponse, AppleDeveloperPortalTeam, AppleProvisioningRequest, AppleRelayResponse, AppleRelayWebSocketClient } from '../core/device-install/apple';
|
|
2
|
-
export * from '../core/device-install/apple/client';
|
|
3
|
-
export * from '../core/device-install/apple/crypto';
|
|
4
|
-
export * from '../core/device-install/apple/gsa-srp';
|
|
5
|
-
export type { AppleDeveloperPortalAppID, AppleDeveloperPortalDevice, AppleDeveloperPortalResponse, AppleDeveloperPortalTeam, AppleProvisioningRequest, AppleRelayResponse, } from '../core/device-install/apple';
|
|
6
|
-
export { AppleRelayWebSocketClient, fetchAppleAccountSession, openAppleRelayWebSocket, proxyPhoneTwoFactorCode, proxySrpComplete, proxySrpInit, proxyTwoFactorCode, triggerPhoneTwoFactor, triggerTrustedDeviceTwoFactor, } from '../core/device-install/apple';
|
|
7
|
-
export type AppleRelayClientOptions = {
|
|
8
|
-
relay: AppleRelayWebSocketClient;
|
|
9
|
-
};
|
|
10
|
-
export type AppleTeamScopedOptions = AppleRelayClientOptions & {
|
|
11
|
-
teamId?: string;
|
|
12
|
-
};
|
|
13
|
-
export type AppleCertificateKind = 'development' | 'distribution';
|
|
14
|
-
export type AppleProfileKind = 'development' | 'adhoc';
|
|
15
|
-
export type RequestAppleProvisioningOptions<T = unknown> = AppleRelayClientOptions & {
|
|
16
|
-
request: AppleProvisioningRequest;
|
|
17
|
-
label?: string;
|
|
18
|
-
validatePortalResponse?: boolean;
|
|
19
|
-
mapBody?: (body: AppleDeveloperPortalResponse | undefined, response: AppleRelayResponse<T>) => T;
|
|
20
|
-
};
|
|
21
|
-
export type MappedAppleProvisioningOptions<T> = RequestAppleProvisioningOptions<T> & {
|
|
22
|
-
mapBody: (body: AppleDeveloperPortalResponse | undefined, response: AppleRelayResponse<T>) => T;
|
|
23
|
-
};
|
|
24
|
-
export type ListAppleCertificatesOptions = AppleTeamScopedOptions & {
|
|
25
|
-
certificateKind?: AppleCertificateKind;
|
|
26
|
-
};
|
|
27
|
-
export type CreateAppleCertificateOptions = AppleTeamScopedOptions & {
|
|
28
|
-
certificateKind?: AppleCertificateKind;
|
|
29
|
-
csrPEM: string;
|
|
30
|
-
};
|
|
31
|
-
export type DownloadAppleCertificateOptions = AppleTeamScopedOptions & {
|
|
32
|
-
certificateKind?: AppleCertificateKind;
|
|
33
|
-
certificateId: string;
|
|
34
|
-
};
|
|
35
|
-
export type DeleteAppleCertificateOptions = DownloadAppleCertificateOptions;
|
|
36
|
-
export type ListAppleBundleIDsOptions = AppleTeamScopedOptions & {
|
|
37
|
-
search?: string;
|
|
38
|
-
};
|
|
39
|
-
export type CreateAppleBundleIDOptions = AppleTeamScopedOptions & {
|
|
40
|
-
bundleId: string;
|
|
41
|
-
name?: string;
|
|
42
|
-
};
|
|
43
|
-
export type UpdateAppleBundleIDOptions = AppleTeamScopedOptions & {
|
|
44
|
-
appIdId: string;
|
|
45
|
-
bundleId?: string;
|
|
46
|
-
name?: string;
|
|
47
|
-
};
|
|
48
|
-
export type DeleteAppleBundleIDOptions = AppleTeamScopedOptions & {
|
|
49
|
-
appIdId: string;
|
|
50
|
-
};
|
|
51
|
-
export type ListAppleDevicesOptions = AppleTeamScopedOptions & {
|
|
52
|
-
deviceUDID?: string;
|
|
53
|
-
};
|
|
54
|
-
export type RegisterAppleDeviceOptions = AppleTeamScopedOptions & {
|
|
55
|
-
deviceUDID: string;
|
|
56
|
-
name?: string;
|
|
57
|
-
};
|
|
58
|
-
export type UpdateAppleDeviceOptions = AppleTeamScopedOptions & {
|
|
59
|
-
deviceId: string;
|
|
60
|
-
name?: string;
|
|
61
|
-
};
|
|
62
|
-
export type DeleteAppleDeviceOptions = AppleTeamScopedOptions & {
|
|
63
|
-
deviceId: string;
|
|
64
|
-
};
|
|
65
|
-
export type ListAppleProfilesOptions = AppleTeamScopedOptions & {
|
|
66
|
-
profileKind?: AppleProfileKind;
|
|
67
|
-
bundleId?: string;
|
|
68
|
-
};
|
|
69
|
-
export type CreateAppleProfileOptions = AppleTeamScopedOptions & {
|
|
70
|
-
profileKind?: AppleProfileKind;
|
|
71
|
-
bundleId: string;
|
|
72
|
-
appIdId: string;
|
|
73
|
-
certificateIds: string[];
|
|
74
|
-
deviceIds: string[];
|
|
75
|
-
name?: string;
|
|
76
|
-
};
|
|
77
|
-
export type DownloadAppleProfileOptions = AppleTeamScopedOptions & {
|
|
78
|
-
profileId: string;
|
|
79
|
-
};
|
|
80
|
-
export type DeleteAppleProfileOptions = DownloadAppleProfileOptions;
|
|
81
|
-
export declare function requestAppleProvisioning<T>(options: MappedAppleProvisioningOptions<T>): Promise<T>;
|
|
82
|
-
export declare function requestAppleProvisioning<T = AppleDeveloperPortalResponse>(options: RequestAppleProvisioningOptions<T>): Promise<AppleRelayResponse<T>>;
|
|
83
|
-
export declare function listAppleTeams(options: AppleRelayClientOptions): Promise<AppleDeveloperPortalTeam[]>;
|
|
84
|
-
export declare function listAppleCertificates({ certificateKind, teamId, ...options }: ListAppleCertificatesOptions): Promise<Record<string, unknown>[]>;
|
|
85
|
-
export declare function createAppleCertificate({ certificateKind, teamId, csrPEM, ...options }: CreateAppleCertificateOptions): Promise<Record<string, unknown> | undefined>;
|
|
86
|
-
export declare function downloadAppleCertificate({ certificateKind, certificateId, teamId, ...options }: DownloadAppleCertificateOptions): Promise<AppleRelayResponse>;
|
|
87
|
-
export declare function deleteAppleCertificate({ certificateKind, certificateId, teamId, ...options }: DeleteAppleCertificateOptions): Promise<AppleDeveloperPortalResponse | undefined>;
|
|
88
|
-
export declare function listAppleBundleIDs({ teamId, search, ...options }: ListAppleBundleIDsOptions): Promise<AppleDeveloperPortalAppID[]>;
|
|
89
|
-
export declare function createAppleBundleID({ teamId, bundleId, name, ...options }: CreateAppleBundleIDOptions): Promise<Record<string, unknown> | undefined>;
|
|
90
|
-
export declare function updateAppleBundleID({ teamId, appIdId, bundleId, name, ...options }: UpdateAppleBundleIDOptions): Promise<Record<string, unknown> | undefined>;
|
|
91
|
-
export declare function deleteAppleBundleID({ teamId, appIdId, ...options }: DeleteAppleBundleIDOptions): Promise<AppleDeveloperPortalResponse | undefined>;
|
|
92
|
-
export declare function listAppleDevices({ teamId, deviceUDID, ...options }: ListAppleDevicesOptions): Promise<AppleDeveloperPortalDevice[]>;
|
|
93
|
-
export declare function registerAppleDevice({ teamId, deviceUDID, name, ...options }: RegisterAppleDeviceOptions): Promise<Record<string, unknown> | undefined>;
|
|
94
|
-
export declare function updateAppleDevice({ teamId, deviceId, name, ...options }: UpdateAppleDeviceOptions): Promise<Record<string, unknown> | undefined>;
|
|
95
|
-
export declare function deleteAppleDevice({ teamId, deviceId, ...options }: DeleteAppleDeviceOptions): Promise<AppleDeveloperPortalResponse | undefined>;
|
|
96
|
-
export declare function listAppleProfiles({ profileKind, teamId, bundleId, ...options }: ListAppleProfilesOptions): Promise<Record<string, unknown>[]>;
|
|
97
|
-
export declare function createAppleProfile({ profileKind, teamId, bundleId, appIdId, certificateIds, deviceIds, name, ...options }: CreateAppleProfileOptions): Promise<Record<string, unknown> | undefined>;
|
|
98
|
-
export declare function downloadAppleProfile({ teamId, profileId, ...options }: DownloadAppleProfileOptions): Promise<AppleRelayResponse>;
|
|
99
|
-
export declare function deleteAppleProfile({ teamId, profileId, ...options }: DeleteAppleProfileOptions): Promise<AppleDeveloperPortalResponse | undefined>;
|
|
100
|
-
export declare function assertAppleDeveloperPortalResponseOK(response: AppleDeveloperPortalResponse | undefined, label: string): void;
|