@limrun/ui 0.14.0-rc.3 → 0.14.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-store-relay/index.cjs +3 -3
- package/dist/app-store-relay/index.d.ts +108 -4
- package/dist/app-store-relay/index.js +353 -160
- package/dist/app-store-relay/react.cjs +1 -1
- package/dist/app-store-relay/react.js +32 -33
- package/dist/apple-credentials/index.cjs +1 -0
- package/dist/apple-credentials/index.d.ts +110 -0
- package/dist/apple-credentials/index.js +291 -0
- package/dist/browser-storage-BnO-Ma-e.mjs +219 -0
- package/dist/browser-storage-DLxIqZk5.js +1 -0
- package/dist/client-C9z_sgOf.js +1 -0
- package/dist/{client-C8ZDEjtD.mjs → client-CFDB4mX5.mjs} +38 -31
- package/dist/components/remote-control.d.ts +156 -0
- package/dist/core/device-install/apple/provisioning.d.ts +25 -0
- package/dist/core/device-install/apple/relay.d.ts +13 -0
- package/dist/core/device-install/storage/browser-storage.d.ts +8 -0
- package/dist/core/device-install/storage/index.d.ts +1 -0
- package/dist/core/device-install/storage/secret-store.d.ts +124 -0
- package/dist/core/device-install/types.d.ts +6 -0
- package/dist/core/errors.d.ts +1 -0
- package/dist/core/play-publish/google.d.ts +1 -1
- package/dist/device-build/index.cjs +1 -1
- package/dist/device-build/index.js +21 -20
- package/dist/device-build/react.cjs +1 -1
- package/dist/device-build/react.js +42 -43
- package/dist/device-install/index.cjs +1 -1
- package/dist/device-install/index.js +64 -63
- package/dist/device-install/react.cjs +1 -1
- package/dist/device-install/react.js +47 -49
- package/dist/errors-BSkqS7U-.js +1 -0
- package/dist/errors-gy8yQJos.mjs +6 -0
- package/dist/gsa-srp-Bme3JLEi.mjs +266 -0
- package/dist/gsa-srp-CCIfUz7Y.js +1 -0
- package/dist/index-ChhtuQ7e.js +22 -0
- package/dist/index-YDu8K9a4.mjs +11279 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +1405 -1125
- package/dist/play-publish/index.cjs +1 -1
- package/dist/play-publish/index.js +27 -24
- package/dist/play-publish/react.cjs +1 -1
- package/dist/play-publish/react.d.ts +12 -2
- package/dist/play-publish/react.js +70 -60
- package/dist/{provisioning-BmsEnF6X.mjs → provisioning-CDPvxd1h.mjs} +64 -33
- package/dist/provisioning-CbC4h--7.js +1 -0
- package/package.json +6 -1
- package/src/app-store-relay/index.ts +358 -23
- package/src/app-store-relay/react.ts +1 -4
- package/src/apple-credentials/index.test.ts +180 -0
- package/src/apple-credentials/index.ts +388 -0
- package/src/components/remote-control.css +32 -0
- package/src/components/remote-control.tsx +865 -5
- package/src/core/device-install/apple/client.ts +13 -6
- package/src/core/device-install/apple/provisioning.test.ts +30 -0
- package/src/core/device-install/apple/provisioning.ts +39 -0
- package/src/core/device-install/apple/relay.ts +20 -0
- package/src/core/device-install/operations/operations.ts +7 -5
- package/src/core/device-install/storage/browser-storage.test.ts +65 -0
- package/src/core/device-install/storage/browser-storage.ts +33 -0
- package/src/core/device-install/storage/index.ts +1 -0
- package/src/core/device-install/storage/secret-store.ts +332 -0
- package/src/core/device-install/types.ts +6 -0
- package/src/core/errors.ts +3 -0
- package/src/core/play-publish/google.ts +11 -2
- package/src/device-build/react.ts +1 -4
- package/src/device-install/demo/demo.tsx +1 -4
- package/src/device-install/react.ts +1 -4
- package/src/play-publish/README.md +5 -4
- package/src/play-publish/react.ts +72 -32
- package/vite.config.ts +1 -0
- package/dist/browser-storage-Cx9eW-bm.mjs +0 -205
- package/dist/browser-storage-jJaIht4K.js +0 -1
- package/dist/client-BtC4n_qf.js +0 -1
- package/dist/index-CMeQfhYy.js +0 -22
- package/dist/index-DFdCvi2_.mjs +0 -11543
- package/dist/provisioning-Va0PH4Kk.js +0 -1
|
@@ -71,11 +71,20 @@ export type RequestGoogleAccessTokenInput = {
|
|
|
71
71
|
* call loadGoogleIdentityServices beforehand (e.g. when the surrounding
|
|
72
72
|
* dialog opens) to keep this call synchronous with the click.
|
|
73
73
|
*/
|
|
74
|
-
export
|
|
74
|
+
export function requestGoogleAccessToken(input: RequestGoogleAccessTokenInput): Promise<string> {
|
|
75
|
+
// When GSI is already loaded the popup must open inside the caller's
|
|
76
|
+
// click turn: even an await of a resolved promise yields a microtask,
|
|
77
|
+
// which the strictest popup blockers treat as leaving the gesture.
|
|
78
|
+
if (googleOAuth2()) {
|
|
79
|
+
return openTokenPopup(input);
|
|
80
|
+
}
|
|
81
|
+
return loadGoogleIdentityServices().then(() => openTokenPopup(input));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function openTokenPopup({
|
|
75
85
|
clientId,
|
|
76
86
|
scope = ANDROID_PUBLISHER_SCOPE,
|
|
77
87
|
}: RequestGoogleAccessTokenInput): Promise<string> {
|
|
78
|
-
await loadGoogleIdentityServices();
|
|
79
88
|
return new Promise<string>((resolve, reject) => {
|
|
80
89
|
const client = googleOAuth2()!.initTokenClient({
|
|
81
90
|
client_id: clientId,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type IOSOTAInstall,
|
|
9
9
|
type StoredSigningAssets,
|
|
10
10
|
} from './index';
|
|
11
|
+
import { errorMessage } from '../core/errors';
|
|
11
12
|
|
|
12
13
|
export type UseDeviceBuildOptions = {
|
|
13
14
|
apiUrl?: string;
|
|
@@ -127,7 +128,3 @@ export function useDeviceBuild({
|
|
|
127
128
|
reset,
|
|
128
129
|
};
|
|
129
130
|
}
|
|
130
|
-
|
|
131
|
-
function errorMessage(error: unknown) {
|
|
132
|
-
return error instanceof Error ? error.message : String(error);
|
|
133
|
-
}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
import { useDeviceBuild } from '../../device-build/react';
|
|
30
30
|
import { useDeviceInstallRelay } from '../react';
|
|
31
31
|
import './demo.css';
|
|
32
|
+
import { errorMessage } from '../../core/errors';
|
|
32
33
|
|
|
33
34
|
type ActivityLine = {
|
|
34
35
|
id: number;
|
|
@@ -1053,10 +1054,6 @@ function useLocalStorage(key: string, initialValue: string) {
|
|
|
1053
1054
|
return [value, setValue] as const;
|
|
1054
1055
|
}
|
|
1055
1056
|
|
|
1056
|
-
function errorMessage(error: unknown) {
|
|
1057
|
-
return error instanceof Error ? error.message : String(error);
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
1057
|
createRoot(document.getElementById('root')!).render(
|
|
1061
1058
|
<StrictMode>
|
|
1062
1059
|
<App />
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type RelayClient,
|
|
13
13
|
type StoredPairRecord,
|
|
14
14
|
} from './index';
|
|
15
|
+
import { errorMessage } from '../core/errors';
|
|
15
16
|
|
|
16
17
|
export type DeviceInstallRelayBusyAction = 'usb' | 'pair' | 'install';
|
|
17
18
|
|
|
@@ -192,7 +193,3 @@ export function useDeviceInstallRelay({
|
|
|
192
193
|
function noopLog() {
|
|
193
194
|
// Intentionally empty. Consumers can pass a logger for progress messages.
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
-
function errorMessage(error: unknown) {
|
|
197
|
-
return error instanceof Error ? error.message : String(error);
|
|
198
|
-
}
|
|
@@ -29,7 +29,8 @@ const play = usePlaystorePublish({
|
|
|
29
29
|
googleClientId: GOOGLE_OAUTH_CLIENT_ID,
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
// On dialog open, warm the sign-in script so the click stays popup-safe
|
|
32
|
+
// On dialog open, warm the sign-in script so the click stays popup-safe.
|
|
33
|
+
// Optionally await the returned promise (true = ready) to gate the button:
|
|
33
34
|
play.preloadGoogle();
|
|
34
35
|
|
|
35
36
|
// Button handlers:
|
|
@@ -39,9 +40,9 @@ await play.publish({ assetName: 'app-release.aab', packageName: 'com.example.app
|
|
|
39
40
|
// Render from state: play.status, play.versionCode, play.error, play.errorCode
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
`errorCode`
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
`errorCode` carries the registry's machine-readable error code; the
|
|
44
|
+
canonical value list lives on `PlaystorePublishError`'s doc comment and
|
|
45
|
+
grows additively.
|
|
45
46
|
|
|
46
47
|
Google access tokens expire after about an hour. A `permissionDenied`
|
|
47
48
|
error long after sign-in usually means the token expired; offer "Sign in
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react';
|
|
1
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { errorMessage } from '../core/errors';
|
|
2
3
|
import {
|
|
3
4
|
loadGoogleIdentityServices,
|
|
4
5
|
PlaystorePublishError,
|
|
@@ -29,10 +30,20 @@ export type UsePlaystorePublishResult = {
|
|
|
29
30
|
error?: string;
|
|
30
31
|
/** Registry error code driving per-cause UX, e.g. versionCodeExists. */
|
|
31
32
|
errorCode?: string;
|
|
32
|
-
/**
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Warm up the Google sign-in script (e.g. on dialog open) so
|
|
35
|
+
* signInWithGoogle stays synchronous with the click. Resolves true once
|
|
36
|
+
* the script is ready; await it to gate the sign-in button, or ignore
|
|
37
|
+
* the result and rely on the blocked-popup error plus retry.
|
|
38
|
+
*/
|
|
39
|
+
preloadGoogle: () => Promise<boolean>;
|
|
34
40
|
signInWithGoogle: () => Promise<boolean>;
|
|
35
41
|
publish: (request: PlaystorePublishRequest) => Promise<PlaystorePublishResult | undefined>;
|
|
42
|
+
/**
|
|
43
|
+
* Clears the outcome state (keeps the Google session). Does not cancel an
|
|
44
|
+
* in-flight sign-in or publish: their completion is ignored status-wise
|
|
45
|
+
* and new calls stay refused until the in-flight one settles.
|
|
46
|
+
*/
|
|
36
47
|
reset: () => void;
|
|
37
48
|
};
|
|
38
49
|
|
|
@@ -43,7 +54,9 @@ export function usePlaystorePublish({
|
|
|
43
54
|
googleClientId,
|
|
44
55
|
}: UsePlaystorePublishOptions): UsePlaystorePublishResult {
|
|
45
56
|
const [status, setStatus] = useState<PlaystorePublishStatus>('idle');
|
|
46
|
-
|
|
57
|
+
// isSignedIn derives from token possession so the two can never diverge,
|
|
58
|
+
// even when a reset() during the popup makes the flow's status stale.
|
|
59
|
+
const [accessToken, setAccessToken] = useState<string | undefined>();
|
|
47
60
|
const [versionCode, setVersionCode] = useState<number | undefined>();
|
|
48
61
|
const [error, setError] = useState<string | undefined>();
|
|
49
62
|
const [errorCode, setErrorCode] = useState<string | undefined>();
|
|
@@ -55,8 +68,22 @@ export function usePlaystorePublish({
|
|
|
55
68
|
const generationRef = useRef(0);
|
|
56
69
|
const busyRef = useRef(false);
|
|
57
70
|
|
|
58
|
-
const preloadGoogle = useCallback(
|
|
59
|
-
|
|
71
|
+
const preloadGoogle = useCallback(
|
|
72
|
+
() =>
|
|
73
|
+
loadGoogleIdentityServices().then(
|
|
74
|
+
() => true,
|
|
75
|
+
() => false,
|
|
76
|
+
),
|
|
77
|
+
[],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// Guard failures replace the whole outcome, like the main paths do: a
|
|
81
|
+
// stale errorCode or versionCode must not render beside the new error.
|
|
82
|
+
const failGuard = useCallback((message: string) => {
|
|
83
|
+
setError(message);
|
|
84
|
+
setErrorCode(undefined);
|
|
85
|
+
setVersionCode(undefined);
|
|
86
|
+
setStatus('error');
|
|
60
87
|
}, []);
|
|
61
88
|
|
|
62
89
|
const signInWithGoogle = useCallback(async () => {
|
|
@@ -64,8 +91,7 @@ export function usePlaystorePublish({
|
|
|
64
91
|
return false;
|
|
65
92
|
}
|
|
66
93
|
if (!googleClientId) {
|
|
67
|
-
|
|
68
|
-
setStatus('error');
|
|
94
|
+
failGuard('Google OAuth client ID is not configured.');
|
|
69
95
|
return false;
|
|
70
96
|
}
|
|
71
97
|
busyRef.current = true;
|
|
@@ -76,9 +102,14 @@ export function usePlaystorePublish({
|
|
|
76
102
|
try {
|
|
77
103
|
const nextToken = await requestGoogleAccessToken({ clientId: googleClientId });
|
|
78
104
|
accessTokenRef.current = nextToken;
|
|
105
|
+
setAccessToken(nextToken);
|
|
79
106
|
if (generation === generationRef.current) {
|
|
80
|
-
setIsSignedIn(true);
|
|
81
107
|
setStatus('ready');
|
|
108
|
+
} else {
|
|
109
|
+
// A reset() during the popup ran before the token landed and left
|
|
110
|
+
// idle; upgrade it so status agrees with isSignedIn. Anything but
|
|
111
|
+
// idle belongs to a newer flow and must not be stomped.
|
|
112
|
+
setStatus((current) => (current === 'idle' ? 'ready' : current));
|
|
82
113
|
}
|
|
83
114
|
return true;
|
|
84
115
|
} catch (caught) {
|
|
@@ -98,14 +129,12 @@ export function usePlaystorePublish({
|
|
|
98
129
|
return undefined;
|
|
99
130
|
}
|
|
100
131
|
if (!registryApiUrl) {
|
|
101
|
-
|
|
102
|
-
setStatus('error');
|
|
132
|
+
failGuard('Registry URL is not configured.');
|
|
103
133
|
return undefined;
|
|
104
134
|
}
|
|
105
|
-
const
|
|
106
|
-
if (!
|
|
107
|
-
|
|
108
|
-
setStatus('error');
|
|
135
|
+
const googleToken = accessTokenRef.current;
|
|
136
|
+
if (!googleToken) {
|
|
137
|
+
failGuard('Sign in with Google before publishing.');
|
|
109
138
|
return undefined;
|
|
110
139
|
}
|
|
111
140
|
busyRef.current = true;
|
|
@@ -113,13 +142,23 @@ export function usePlaystorePublish({
|
|
|
113
142
|
setStatus('publishing');
|
|
114
143
|
setError(undefined);
|
|
115
144
|
setErrorCode(undefined);
|
|
145
|
+
// A stale code from an earlier publish must not render as this
|
|
146
|
+
// attempt's success next to an error state.
|
|
147
|
+
setVersionCode(undefined);
|
|
116
148
|
try {
|
|
149
|
+
// Fields picked explicitly: spreading a wider-typed request object
|
|
150
|
+
// could smuggle same-named credential fields or excess properties
|
|
151
|
+
// into the request body.
|
|
117
152
|
const result = await publishToPlaystore({
|
|
118
153
|
registryApiUrl,
|
|
119
154
|
token,
|
|
120
155
|
organizationId,
|
|
121
|
-
accessToken,
|
|
122
|
-
|
|
156
|
+
accessToken: googleToken,
|
|
157
|
+
packageName: request.packageName,
|
|
158
|
+
assetId: request.assetId,
|
|
159
|
+
assetName: request.assetName,
|
|
160
|
+
track: request.track,
|
|
161
|
+
releaseStatus: request.releaseStatus,
|
|
123
162
|
});
|
|
124
163
|
if (generation === generationRef.current) {
|
|
125
164
|
setVersionCode(result.versionCode);
|
|
@@ -150,19 +189,20 @@ export function usePlaystorePublish({
|
|
|
150
189
|
setStatus(accessTokenRef.current ? 'ready' : 'idle');
|
|
151
190
|
}, []);
|
|
152
191
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
192
|
+
// Memoized so the result works as a prop or dependency without
|
|
193
|
+
// re-rendering consumers on unrelated parent renders.
|
|
194
|
+
return useMemo(
|
|
195
|
+
() => ({
|
|
196
|
+
status,
|
|
197
|
+
isSignedIn: accessToken !== undefined,
|
|
198
|
+
versionCode,
|
|
199
|
+
error,
|
|
200
|
+
errorCode,
|
|
201
|
+
preloadGoogle,
|
|
202
|
+
signInWithGoogle,
|
|
203
|
+
publish,
|
|
204
|
+
reset,
|
|
205
|
+
}),
|
|
206
|
+
[status, accessToken, versionCode, error, errorCode, preloadGoogle, signInWithGoogle, publish, reset],
|
|
207
|
+
);
|
|
168
208
|
}
|
package/vite.config.ts
CHANGED
|
@@ -13,6 +13,7 @@ export default defineConfig({
|
|
|
13
13
|
index: resolve(__dirname, 'src/index.ts'),
|
|
14
14
|
'app-store-relay/index': resolve(__dirname, 'src/app-store-relay/index.ts'),
|
|
15
15
|
'app-store-relay/react': resolve(__dirname, 'src/app-store-relay/react.ts'),
|
|
16
|
+
'apple-credentials/index': resolve(__dirname, 'src/apple-credentials/index.ts'),
|
|
16
17
|
'device-build/index': resolve(__dirname, 'src/device-build/index.ts'),
|
|
17
18
|
'device-build/react': resolve(__dirname, 'src/device-build/react.ts'),
|
|
18
19
|
'device-install/index': resolve(__dirname, 'src/device-install/index.ts'),
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
const v = "limbuild-device-pairing";
|
|
2
|
-
const d = "pairRecords", w = "limbuild-device-signing";
|
|
3
|
-
const c = "signingAssets";
|
|
4
|
-
function l(e) {
|
|
5
|
-
return (e ?? "").replace(/-/g, "").replace(/[^a-fA-F0-9]/g, "");
|
|
6
|
-
}
|
|
7
|
-
function f(e) {
|
|
8
|
-
return (e ?? "").trim();
|
|
9
|
-
}
|
|
10
|
-
async function R(e) {
|
|
11
|
-
const n = l(e);
|
|
12
|
-
if (!n) return;
|
|
13
|
-
const r = await p(v, 1, d, "udid");
|
|
14
|
-
return g(
|
|
15
|
-
r.transaction(d, "readonly").objectStore(d).get(n)
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
async function G(e, n = {}) {
|
|
19
|
-
const r = l(e.udid);
|
|
20
|
-
if (!r) throw new Error("Cannot store pair record without a UDID.");
|
|
21
|
-
const t = {
|
|
22
|
-
...e,
|
|
23
|
-
udid: r,
|
|
24
|
-
productName: n.productName,
|
|
25
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26
|
-
}, i = await p(v, 1, d, "udid");
|
|
27
|
-
return await g(
|
|
28
|
-
i.transaction(d, "readwrite").objectStore(d).put(t)
|
|
29
|
-
), t;
|
|
30
|
-
}
|
|
31
|
-
async function O({
|
|
32
|
-
deviceUDID: e,
|
|
33
|
-
bundleID: n,
|
|
34
|
-
signingMode: r = "development"
|
|
35
|
-
}) {
|
|
36
|
-
const t = f(n);
|
|
37
|
-
if (!t) return;
|
|
38
|
-
const i = l(e), s = await S(D("bundle", t, r));
|
|
39
|
-
if (s) return s;
|
|
40
|
-
if (i) {
|
|
41
|
-
const o = await S(D(i, t, r));
|
|
42
|
-
if (o) return o;
|
|
43
|
-
}
|
|
44
|
-
return (await h(t, r))[0];
|
|
45
|
-
}
|
|
46
|
-
async function T(e = "development") {
|
|
47
|
-
return (await m()).filter((r) => (r.signingMode ?? "development") === e).sort((r, t) => new Date(t.updatedAt).getTime() - new Date(r.updatedAt).getTime())[0];
|
|
48
|
-
}
|
|
49
|
-
async function V(e, n = "development") {
|
|
50
|
-
return (await m()).filter((t) => !t.certificateID || !t.certificateP12Base64 || (t.signingMode ?? "development") !== n ? !1 : !e || !t.teamID || t.teamID === e).sort((t, i) => new Date(i.updatedAt).getTime() - new Date(t.updatedAt).getTime())[0];
|
|
51
|
-
}
|
|
52
|
-
async function z(e) {
|
|
53
|
-
const n = f(e.bundleID);
|
|
54
|
-
if (!n)
|
|
55
|
-
throw new Error("Cannot store signing assets without a bundle ID.");
|
|
56
|
-
const r = l(e.deviceUDID), t = e.signingMode ?? "development", i = D("bundle", n, t), s = {
|
|
57
|
-
...e,
|
|
58
|
-
id: i,
|
|
59
|
-
deviceUDID: r || void 0,
|
|
60
|
-
signingMode: t,
|
|
61
|
-
bundleID: n,
|
|
62
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
63
|
-
}, a = await p(w, 1, c, "id");
|
|
64
|
-
return await g(
|
|
65
|
-
a.transaction(c, "readwrite").objectStore(c).put(s)
|
|
66
|
-
), s;
|
|
67
|
-
}
|
|
68
|
-
async function h(e, n = "development") {
|
|
69
|
-
const r = f(e);
|
|
70
|
-
return r ? (await m()).filter(
|
|
71
|
-
(i) => i.bundleID === r && (i.signingMode ?? "development") === n
|
|
72
|
-
) : [];
|
|
73
|
-
}
|
|
74
|
-
function U(e, n) {
|
|
75
|
-
const r = l(n);
|
|
76
|
-
return !!r && e.provisionedDevices.some((t) => l(t) === r);
|
|
77
|
-
}
|
|
78
|
-
function j(e, n) {
|
|
79
|
-
const r = f(n), t = f(e.bundleID);
|
|
80
|
-
if (!r || !t) return !1;
|
|
81
|
-
if (t === r || t === "*") return !0;
|
|
82
|
-
if (!t.endsWith(".*")) return !1;
|
|
83
|
-
const i = t.slice(0, -1);
|
|
84
|
-
return r.startsWith(i);
|
|
85
|
-
}
|
|
86
|
-
async function M(e) {
|
|
87
|
-
return E(new Uint8Array(await e.arrayBuffer()));
|
|
88
|
-
}
|
|
89
|
-
function C(e) {
|
|
90
|
-
const n = atob(e), r = new Uint8Array(n.length);
|
|
91
|
-
for (let t = 0; t < n.length; t += 1)
|
|
92
|
-
r[t] = n.charCodeAt(t);
|
|
93
|
-
return E(r);
|
|
94
|
-
}
|
|
95
|
-
function E(e) {
|
|
96
|
-
const n = new TextDecoder("latin1").decode(e), r = n.indexOf("<?xml"), t = n.indexOf("</plist>");
|
|
97
|
-
if (r < 0 || t < r)
|
|
98
|
-
throw new Error("Provisioning profile plist not found.");
|
|
99
|
-
const i = n.slice(r, t + 8);
|
|
100
|
-
if (/<!ENTITY/i.test(i))
|
|
101
|
-
throw new Error("Provisioning profile plist contains a disallowed ENTITY declaration.");
|
|
102
|
-
const s = new DOMParser().parseFromString(i, "application/xml");
|
|
103
|
-
if (s.querySelector("parsererror"))
|
|
104
|
-
throw new Error("Provisioning profile plist could not be parsed.");
|
|
105
|
-
const a = s.querySelector("plist > dict");
|
|
106
|
-
if (!a)
|
|
107
|
-
throw new Error("Provisioning profile plist dictionary not found.");
|
|
108
|
-
const o = A(a);
|
|
109
|
-
if (!b(o))
|
|
110
|
-
throw new Error("Provisioning profile plist has an unexpected shape.");
|
|
111
|
-
const I = b(o.Entitlements) ? o.Entitlements : {}, y = u(I["application-identifier"]), P = B(y);
|
|
112
|
-
return {
|
|
113
|
-
name: u(o.Name),
|
|
114
|
-
uuid: u(o.UUID),
|
|
115
|
-
teamID: u(I["com.apple.developer.team-identifier"]) ?? N(o.TeamIdentifier)[0],
|
|
116
|
-
applicationIdentifier: y,
|
|
117
|
-
bundleID: P,
|
|
118
|
-
provisionedDevices: N(o.ProvisionedDevices),
|
|
119
|
-
getTaskAllow: _(I["get-task-allow"]),
|
|
120
|
-
expirationDate: u(o.ExpirationDate)
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
async function S(e) {
|
|
124
|
-
if (!e) return;
|
|
125
|
-
const n = await p(w, 1, c, "id");
|
|
126
|
-
return g(
|
|
127
|
-
n.transaction(c, "readonly").objectStore(c).get(e)
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
async function m() {
|
|
131
|
-
const e = await p(w, 1, c, "id");
|
|
132
|
-
return g(
|
|
133
|
-
e.transaction(c, "readonly").objectStore(c).getAll()
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
function D(e, n, r) {
|
|
137
|
-
return `${r}:${e}:${n}`;
|
|
138
|
-
}
|
|
139
|
-
function B(e) {
|
|
140
|
-
if (!e) return;
|
|
141
|
-
const n = e.indexOf(".");
|
|
142
|
-
return n >= 0 ? e.slice(n + 1) : void 0;
|
|
143
|
-
}
|
|
144
|
-
function A(e) {
|
|
145
|
-
switch (e.tagName) {
|
|
146
|
-
case "dict":
|
|
147
|
-
return x(e);
|
|
148
|
-
case "array":
|
|
149
|
-
return Array.from(e.children).map(A);
|
|
150
|
-
case "string":
|
|
151
|
-
case "date":
|
|
152
|
-
return e.textContent ?? "";
|
|
153
|
-
default:
|
|
154
|
-
return e.textContent ?? "";
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
function x(e) {
|
|
158
|
-
const n = {}, r = Array.from(e.children);
|
|
159
|
-
for (let t = 0; t < r.length; t += 2) {
|
|
160
|
-
const i = r[t], s = r[t + 1];
|
|
161
|
-
!i || i.tagName !== "key" || !s || (n[i.textContent ?? ""] = A(s));
|
|
162
|
-
}
|
|
163
|
-
return n;
|
|
164
|
-
}
|
|
165
|
-
function u(e) {
|
|
166
|
-
return typeof e == "string" && e ? e : void 0;
|
|
167
|
-
}
|
|
168
|
-
function N(e) {
|
|
169
|
-
return Array.isArray(e) ? e.filter((n) => typeof n == "string") : [];
|
|
170
|
-
}
|
|
171
|
-
function _(e) {
|
|
172
|
-
return typeof e == "boolean" ? e : void 0;
|
|
173
|
-
}
|
|
174
|
-
function b(e) {
|
|
175
|
-
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
176
|
-
}
|
|
177
|
-
function p(e, n, r, t) {
|
|
178
|
-
return new Promise((i, s) => {
|
|
179
|
-
const a = indexedDB.open(e, n);
|
|
180
|
-
a.onupgradeneeded = () => {
|
|
181
|
-
const o = a.result;
|
|
182
|
-
o.objectStoreNames.contains(r) || o.createObjectStore(r, { keyPath: t });
|
|
183
|
-
}, a.onsuccess = () => i(a.result), a.onerror = () => s(a.error ?? new Error("Open IndexedDB failed"));
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
function g(e) {
|
|
187
|
-
return new Promise((n, r) => {
|
|
188
|
-
e.onsuccess = () => n(e.result), e.onerror = () => r(e.error ?? new Error("IndexedDB request failed"));
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
export {
|
|
192
|
-
z as a,
|
|
193
|
-
j as b,
|
|
194
|
-
U as c,
|
|
195
|
-
V as d,
|
|
196
|
-
O as e,
|
|
197
|
-
C as f,
|
|
198
|
-
T as g,
|
|
199
|
-
E as h,
|
|
200
|
-
f as i,
|
|
201
|
-
R as j,
|
|
202
|
-
G as k,
|
|
203
|
-
l as n,
|
|
204
|
-
M as p
|
|
205
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const b="limbuild-device-pairing";const l="pairRecords",w="limbuild-device-signing";const c="signingAssets";function d(e){return(e??"").replace(/-/g,"").replace(/[^a-fA-F0-9]/g,"")}function u(e){return(e??"").trim()}async function E(e){const n=d(e);if(!n)return;const r=await g(b,1,l,"udid");return p(r.transaction(l,"readonly").objectStore(l).get(n))}async function h(e,n={}){const r=d(e.udid);if(!r)throw new Error("Cannot store pair record without a UDID.");const t={...e,udid:r,productName:n.productName,updatedAt:new Date().toISOString()},i=await g(b,1,l,"udid");return await p(i.transaction(l,"readwrite").objectStore(l).put(t)),t}async function x({deviceUDID:e,bundleID:n,signingMode:r="development"}){const t=u(n);if(!t)return;const i=d(e),s=await v(I("bundle",t,r));if(s)return s;if(i){const o=await v(I(i,t,r));if(o)return o}return(await O(t,r))[0]}async function _(e="development"){return(await A()).filter(r=>(r.signingMode??"development")===e).sort((r,t)=>new Date(t.updatedAt).getTime()-new Date(r.updatedAt).getTime())[0]}async function R(e,n="development"){return(await A()).filter(t=>!t.certificateID||!t.certificateP12Base64||(t.signingMode??"development")!==n?!1:!e||!t.teamID||t.teamID===e).sort((t,i)=>new Date(i.updatedAt).getTime()-new Date(t.updatedAt).getTime())[0]}async function G(e){const n=u(e.bundleID);if(!n)throw new Error("Cannot store signing assets without a bundle ID.");const r=d(e.deviceUDID),t=e.signingMode??"development",i=I("bundle",n,t),s={...e,id:i,deviceUDID:r||void 0,signingMode:t,bundleID:n,updatedAt:new Date().toISOString()},a=await g(w,1,c,"id");return await p(a.transaction(c,"readwrite").objectStore(c).put(s)),s}async function O(e,n="development"){const r=u(e);return r?(await A()).filter(i=>i.bundleID===r&&(i.signingMode??"development")===n):[]}function T(e,n){const r=d(n);return!!r&&e.provisionedDevices.some(t=>d(t)===r)}function z(e,n){const r=u(n),t=u(e.bundleID);if(!r||!t)return!1;if(t===r||t==="*")return!0;if(!t.endsWith(".*"))return!1;const i=t.slice(0,-1);return r.startsWith(i)}async function U(e){return m(new Uint8Array(await e.arrayBuffer()))}function V(e){const n=atob(e),r=new Uint8Array(n.length);for(let t=0;t<n.length;t+=1)r[t]=n.charCodeAt(t);return m(r)}function m(e){const n=new TextDecoder("latin1").decode(e),r=n.indexOf("<?xml"),t=n.indexOf("</plist>");if(r<0||t<r)throw new Error("Provisioning profile plist not found.");const i=n.slice(r,t+8);if(/<!ENTITY/i.test(i))throw new Error("Provisioning profile plist contains a disallowed ENTITY declaration.");const s=new DOMParser().parseFromString(i,"application/xml");if(s.querySelector("parsererror"))throw new Error("Provisioning profile plist could not be parsed.");const a=s.querySelector("plist > dict");if(!a)throw new Error("Provisioning profile plist dictionary not found.");const o=S(a);if(!P(o))throw new Error("Provisioning profile plist has an unexpected shape.");const D=P(o.Entitlements)?o.Entitlements:{},y=f(D["application-identifier"]),B=C(y);return{name:f(o.Name),uuid:f(o.UUID),teamID:f(D["com.apple.developer.team-identifier"])??N(o.TeamIdentifier)[0],applicationIdentifier:y,bundleID:B,provisionedDevices:N(o.ProvisionedDevices),getTaskAllow:j(D["get-task-allow"]),expirationDate:f(o.ExpirationDate)}}async function v(e){if(!e)return;const n=await g(w,1,c,"id");return p(n.transaction(c,"readonly").objectStore(c).get(e))}async function A(){const e=await g(w,1,c,"id");return p(e.transaction(c,"readonly").objectStore(c).getAll())}function I(e,n,r){return`${r}:${e}:${n}`}function C(e){if(!e)return;const n=e.indexOf(".");return n>=0?e.slice(n+1):void 0}function S(e){switch(e.tagName){case"dict":return M(e);case"array":return Array.from(e.children).map(S);case"string":case"date":return e.textContent??"";default:return e.textContent??""}}function M(e){const n={},r=Array.from(e.children);for(let t=0;t<r.length;t+=2){const i=r[t],s=r[t+1];!i||i.tagName!=="key"||!s||(n[i.textContent??""]=S(s))}return n}function f(e){return typeof e=="string"&&e?e:void 0}function N(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function j(e){return typeof e=="boolean"?e:void 0}function P(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function g(e,n,r,t){return new Promise((i,s)=>{const a=indexedDB.open(e,n);a.onupgradeneeded=()=>{const o=a.result;o.objectStoreNames.contains(r)||o.createObjectStore(r,{keyPath:t})},a.onsuccess=()=>i(a.result),a.onerror=()=>s(a.error??new Error("Open IndexedDB failed"))})}function p(e){return new Promise((n,r)=>{e.onsuccess=()=>n(e.result),e.onerror=()=>r(e.error??new Error("IndexedDB request failed"))})}exports.getLatestSigningAssets=_;exports.getLatestSigningAssetsWithCertificate=R;exports.getPairRecord=E;exports.getSigningAssets=x;exports.normalizeBundleID=u;exports.normalizeUDID=d;exports.parseProvisioningProfile=U;exports.parseProvisioningProfileBase64=V;exports.parseProvisioningProfileBytes=m;exports.profileContainsDevice=T;exports.profileMatchesBundleID=z;exports.putPairRecord=h;exports.putSigningAssets=G;
|
package/dist/client-BtC4n_qf.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const F=require("./index-CMeQfhYy.js");class m{constructor(t,r,o){this.apiUrl=t,this.token=r,this.organizationId=o}socket;nextId=1;pending=new Map;async connect(){if(this.socket&&this.socket.readyState===WebSocket.OPEN)return;const t=new WebSocket(E(this.apiUrl,this.token,this.organizationId));this.socket=t,t.onmessage=r=>this.handleMessage(r),t.onclose=()=>this.rejectPending(new Error("Apple relay WebSocket closed")),t.onerror=()=>this.rejectPending(new Error("Apple relay WebSocket failed")),await new Promise((r,o)=>{t.onopen=()=>r(),t.onerror=()=>o(new Error("Apple relay WebSocket connection failed"))})}request(t,r){const o=this.socket;if(!o||o.readyState!==WebSocket.OPEN)throw new Error("Apple relay WebSocket is not connected.");const a=String(this.nextId++),n=new Promise((p,i)=>{this.pending.set(a,{resolve:h=>p(q(h)),reject:i})});return o.send(JSON.stringify({id:a,type:t,...r===void 0?{}:{payload:r}})),n}close(){this.rejectPending(new Error("Apple relay WebSocket closed")),this.socket?.close(),this.socket=void 0}handleMessage(t){const r=JSON.parse(String(t.data)),o=this.pending.get(r.id);if(o){if(this.pending.delete(r.id),!r.ok){o.reject(new Error(r.error||"Apple relay request failed"));return}if(!r.response){o.reject(new Error("Apple relay response was empty."));return}o.resolve(r.response)}}rejectPending(t){for(const r of this.pending.values())r.reject(t);this.pending.clear()}}async function g(e,t,r){const o=new m(e,t,r);return await o.connect(),o}async function A(e,t){return e.request("srpInit",t)}async function S(e,t){return e.request("srpComplete",t)}async function P(e){return e.request("triggerTrustedDevice2FA")}async function b(e,t,r="sms"){return e.request("triggerPhone2FA",{phoneNumberId:t,mode:r})}async function k(e,t){return e.request("submitTrustedDevice2FA",{code:t})}async function T(e,t,r,o="sms"){return e.request("submitPhone2FA",{phoneNumberId:t,mode:o,code:r})}async function v(e){return e.request("finalize")}async function R(e,t){return e.request("provisioning",t)}function q(e){if(e.body!==void 0||!e.rawBody)return e;try{return{...e,body:JSON.parse(e.rawBody)}}catch{return e}}function E(e,t,r){const o=new URL(e);return o.protocol=o.protocol==="https:"?"wss:":"ws:",o.pathname=`${o.pathname.replace(/\/$/,"")}/ios/appstoreconnect/ws`,t&&o.searchParams.set("token",t),r&&o.searchParams.set("organization",r),o.toString()}async function x({registryApiUrl:e,accountName:t,password:r,token:o,organizationId:a}){const n=await g(e,o,a);try{const p=new F.AppleGsaSrpClient(t),i=await A(n,await p.init());if(i.status<200||i.status>=300)throw new Error(`Apple SRP init failed: HTTP ${i.status} ${i.rawBody??""}`.trim());if(!i.body)throw new Error("Apple SRP init response did not include a body.");const h=await p.complete(r,i.body),u=await S(n,{...h,rememberMe:!1,trustTokens:[]}),y=u.status===409;let s,d={type:"trustedDevice"};if(y){s=await P(n);const c=N(s.body);if(s.status===412){if(!c)throw new Error("Apple requested phone verification but did not include a trusted phone number.");d={type:"phone",phoneNumberId:c.id,mode:c.pushMode??"sms"},s=await b(n,c.id,c.pushMode??"sms")}if(s.status<200||s.status>=300)throw new Error(`Apple two-factor challenge failed: HTTP ${s.status} ${s.rawBody??""}`.trim())}else if(u.status<200||u.status>=300)throw new Error(`Apple SRP complete failed: HTTP ${u.status} ${u.rawBody??""}`.trim());return{relay:n,completeResponse:u,twoFactorChallengeResponse:s,requiresTwoFactor:y,finishTwoFactor:async c=>{const l=d.type==="phone"?await T(n,d.phoneNumberId,c,d.mode):await k(n,c);if(l.status<200||l.status>=300)throw new Error(`Apple two-factor code failed: HTTP ${l.status} ${l.rawBody??""}`.trim());return l},finalize:async()=>v(n),close:async()=>n.close()}}catch(p){throw n.close(),p}}function N(e){if(!f(e))return;const t=f(e.phoneNumberVerification)?e.phoneNumberVerification:void 0,r=w(t?.trustedPhoneNumber)??w(e.trustedPhoneNumber)??w(e.phoneNumber);if(!r)return;const o=r.id;if(typeof o!="number")return;const a=typeof r.pushMode=="string"?r.pushMode:typeof e.mode=="string"?e.mode:void 0;return{id:o,pushMode:a}}function w(e){return f(e)?e:void 0}function f(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}exports.AppleRelayWebSocketClient=m;exports.fetchAppleAccountSession=v;exports.openAppleRelayWebSocket=g;exports.proxyPhoneTwoFactorCode=T;exports.proxyProvisioningRequest=R;exports.proxySrpComplete=S;exports.proxySrpInit=A;exports.proxyTwoFactorCode=k;exports.startBrowserOwnedAppleIDLogin=x;exports.triggerPhoneTwoFactor=b;exports.triggerTrustedDeviceTwoFactor=P;
|