@limrun/ui 0.14.0-rc.2 → 0.14.0-rc.3
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.js +3 -3
- package/dist/app-store-relay/react.d.ts +1 -1
- package/dist/app-store-relay/react.js +6 -2
- package/dist/{client-CBX-hLnL.mjs → client-C8ZDEjtD.mjs} +1 -6
- package/dist/components/remote-control.d.ts +0 -156
- package/dist/core/device-install/operations/operations.d.ts +1 -1
- package/dist/core/play-publish/google.d.ts +13 -0
- package/dist/core/play-publish/publish.d.ts +34 -0
- package/dist/device-build/index.js +5 -5
- package/dist/device-install/index.js +7 -1
- package/dist/device-install/react.js +24 -21
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +1125 -1405
- package/dist/play-publish/index.cjs +1 -0
- package/dist/play-publish/index.d.ts +2 -0
- package/dist/play-publish/index.js +106 -0
- package/dist/play-publish/react.cjs +1 -0
- package/dist/play-publish/react.d.ts +21 -0
- package/dist/play-publish/react.js +81 -0
- package/dist/{provisioning-DKbkBO-p.mjs → provisioning-BmsEnF6X.mjs} +8 -8
- package/package.json +13 -2
- package/src/app-store-relay/index.test.ts +6 -6
- package/src/app-store-relay/react.ts +5 -1
- package/src/components/remote-control.css +0 -32
- package/src/components/remote-control.tsx +5 -865
- package/src/core/device-install/apple/client.ts +1 -6
- package/src/core/device-install/apple/relay.ts +1 -4
- package/src/core/device-install/operations/operations.ts +7 -1
- package/src/core/play-publish/google.ts +104 -0
- package/src/core/play-publish/publish.test.ts +68 -0
- package/src/core/play-publish/publish.ts +89 -0
- package/src/device-install/demo/demo.tsx +1 -4
- package/src/device-install/react.ts +30 -27
- package/src/play-publish/README.md +65 -0
- package/src/play-publish/index.ts +12 -0
- package/src/play-publish/react.ts +168 -0
- package/vite.config.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y="https://accounts.google.com/gsi/client",p="https://www.googleapis.com/auth/androidpublisher";function d(){return globalThis.google?.accounts?.oauth2}let c;function w(){return d()?Promise.resolve():typeof document>"u"?Promise.reject(new Error("Google sign-in requires a browser environment.")):(c||(c=new Promise((r,o)=>{const t=document.createElement("script");t.src=y,t.async=!0,t.addEventListener("load",()=>{d()?r():o(new Error("Google sign-in script loaded without the OAuth client."))},{once:!0}),t.addEventListener("error",()=>{t.remove(),o(new Error("Failed to load the Google sign-in script."))},{once:!0}),document.head.appendChild(t)}),c.catch(()=>{c=void 0})),c)}async function f({clientId:r,scope:o=p}){return await w(),new Promise((t,n)=>{d().initTokenClient({client_id:r,scope:o,callback:e=>{if(e.error){n(new Error(e.error_description||e.error));return}if(!e.access_token){n(new Error("Google returned no access token."));return}t(e.access_token)},error_callback:e=>{const a=e?.type==="popup_failed_to_open"?"Google sign-in popup was blocked by the browser.":"Google sign-in was cancelled.";n(new Error(e?.message||a))}}).requestAccessToken()})}class l extends Error{code;status;constructor(o,t={}){super(o),this.name="PlaystorePublishError",this.code=t.code,this.status=t.status}}async function m(r){const{registryApiUrl:o,token:t,organizationId:n,...h}=r;let e;try{e=new URL(o)}catch{throw new l(`Invalid registry URL: ${o}`)}e.pathname=`${e.pathname.replace(/\/$/,"")}/android/playstore/publish`,e.search="",e.hash="";const a={"Content-Type":"application/json"};t&&(a.Authorization=`Bearer ${t}`),n&&(a["X-Limrun-Organization"]=n);let s;try{s=await fetch(e.toString(),{method:"POST",headers:a,body:JSON.stringify(h)})}catch(u){throw new l(`Cannot reach the registry: ${u instanceof Error?u.message:String(u)}`)}const g=await s.text();let i;try{i=g?JSON.parse(g):void 0}catch{i=void 0}if(!s.ok)throw new l(i?.message||`Play publish failed with HTTP ${s.status}`,{code:i?.code,status:s.status});if(typeof i?.versionCode!="number")throw new l("Play publish response is missing versionCode.",{status:s.status});return{versionCode:i.versionCode}}exports.ANDROID_PUBLISHER_SCOPE=p;exports.PlaystorePublishError=l;exports.loadGoogleIdentityServices=w;exports.publishToPlaystore=m;exports.requestGoogleAccessToken=f;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { ANDROID_PUBLISHER_SCOPE, loadGoogleIdentityServices, requestGoogleAccessToken, type RequestGoogleAccessTokenInput, } from '../core/play-publish/google';
|
|
2
|
+
export { publishToPlaystore, PlaystorePublishError, type PlaystorePublishInput, type PlaystorePublishResult, } from '../core/play-publish/publish';
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const p = "https://accounts.google.com/gsi/client", w = "https://www.googleapis.com/auth/androidpublisher";
|
|
2
|
+
function d() {
|
|
3
|
+
return globalThis.google?.accounts?.oauth2;
|
|
4
|
+
}
|
|
5
|
+
let c;
|
|
6
|
+
function y() {
|
|
7
|
+
return d() ? Promise.resolve() : typeof document > "u" ? Promise.reject(new Error("Google sign-in requires a browser environment.")) : (c || (c = new Promise((r, o) => {
|
|
8
|
+
const t = document.createElement("script");
|
|
9
|
+
t.src = p, t.async = !0, t.addEventListener(
|
|
10
|
+
"load",
|
|
11
|
+
() => {
|
|
12
|
+
d() ? r() : o(new Error("Google sign-in script loaded without the OAuth client."));
|
|
13
|
+
},
|
|
14
|
+
{ once: !0 }
|
|
15
|
+
), t.addEventListener(
|
|
16
|
+
"error",
|
|
17
|
+
() => {
|
|
18
|
+
t.remove(), o(new Error("Failed to load the Google sign-in script."));
|
|
19
|
+
},
|
|
20
|
+
{ once: !0 }
|
|
21
|
+
), document.head.appendChild(t);
|
|
22
|
+
}), c.catch(() => {
|
|
23
|
+
c = void 0;
|
|
24
|
+
})), c);
|
|
25
|
+
}
|
|
26
|
+
async function f({
|
|
27
|
+
clientId: r,
|
|
28
|
+
scope: o = w
|
|
29
|
+
}) {
|
|
30
|
+
return await y(), new Promise((t, n) => {
|
|
31
|
+
d().initTokenClient({
|
|
32
|
+
client_id: r,
|
|
33
|
+
scope: o,
|
|
34
|
+
callback: (e) => {
|
|
35
|
+
if (e.error) {
|
|
36
|
+
n(new Error(e.error_description || e.error));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!e.access_token) {
|
|
40
|
+
n(new Error("Google returned no access token."));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
t(e.access_token);
|
|
44
|
+
},
|
|
45
|
+
error_callback: (e) => {
|
|
46
|
+
const a = e?.type === "popup_failed_to_open" ? "Google sign-in popup was blocked by the browser." : "Google sign-in was cancelled.";
|
|
47
|
+
n(new Error(e?.message || a));
|
|
48
|
+
}
|
|
49
|
+
}).requestAccessToken();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
class l extends Error {
|
|
53
|
+
code;
|
|
54
|
+
status;
|
|
55
|
+
constructor(o, t = {}) {
|
|
56
|
+
super(o), this.name = "PlaystorePublishError", this.code = t.code, this.status = t.status;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function m(r) {
|
|
60
|
+
const { registryApiUrl: o, token: t, organizationId: n, ...h } = r;
|
|
61
|
+
let e;
|
|
62
|
+
try {
|
|
63
|
+
e = new URL(o);
|
|
64
|
+
} catch {
|
|
65
|
+
throw new l(`Invalid registry URL: ${o}`);
|
|
66
|
+
}
|
|
67
|
+
e.pathname = `${e.pathname.replace(/\/$/, "")}/android/playstore/publish`, e.search = "", e.hash = "";
|
|
68
|
+
const a = { "Content-Type": "application/json" };
|
|
69
|
+
t && (a.Authorization = `Bearer ${t}`), n && (a["X-Limrun-Organization"] = n);
|
|
70
|
+
let s;
|
|
71
|
+
try {
|
|
72
|
+
s = await fetch(e.toString(), {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: a,
|
|
75
|
+
body: JSON.stringify(h)
|
|
76
|
+
});
|
|
77
|
+
} catch (u) {
|
|
78
|
+
throw new l(
|
|
79
|
+
`Cannot reach the registry: ${u instanceof Error ? u.message : String(u)}`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
const g = await s.text();
|
|
83
|
+
let i;
|
|
84
|
+
try {
|
|
85
|
+
i = g ? JSON.parse(g) : void 0;
|
|
86
|
+
} catch {
|
|
87
|
+
i = void 0;
|
|
88
|
+
}
|
|
89
|
+
if (!s.ok)
|
|
90
|
+
throw new l(i?.message || `Play publish failed with HTTP ${s.status}`, {
|
|
91
|
+
code: i?.code,
|
|
92
|
+
status: s.status
|
|
93
|
+
});
|
|
94
|
+
if (typeof i?.versionCode != "number")
|
|
95
|
+
throw new l("Play publish response is missing versionCode.", {
|
|
96
|
+
status: s.status
|
|
97
|
+
});
|
|
98
|
+
return { versionCode: i.versionCode };
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
w as ANDROID_PUBLISHER_SCOPE,
|
|
102
|
+
l as PlaystorePublishError,
|
|
103
|
+
y as loadGoogleIdentityServices,
|
|
104
|
+
m as publishToPlaystore,
|
|
105
|
+
f as requestGoogleAccessToken
|
|
106
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),l=require("./index.cjs");function q({registryApiUrl:n,token:g,organizationId:v,googleClientId:d}){const[S,r]=e.useState("idle"),[P,R]=e.useState(!1),[k,b]=e.useState(),[C,t]=e.useState(),[p,c]=e.useState(),f=e.useRef(void 0),s=e.useRef(0),o=e.useRef(!1),G=e.useCallback(()=>{l.loadGoogleIdentityServices().catch(()=>{})},[]),T=e.useCallback(async()=>{if(o.current)return!1;if(!d)return t("Google OAuth client ID is not configured."),r("error"),!1;o.current=!0;const a=s.current;r("signing-in"),t(void 0),c(void 0);try{const u=await l.requestGoogleAccessToken({clientId:d});return f.current=u,a===s.current&&(R(!0),r("ready")),!0}catch(u){return a===s.current&&(t(y(u)),r("error")),!1}finally{o.current=!1}},[d]),E=e.useCallback(async a=>{if(o.current)return;if(!n){t("Registry URL is not configured."),r("error");return}const u=f.current;if(!u){t("Sign in with Google before publishing."),r("error");return}o.current=!0;const h=s.current;r("publishing"),t(void 0),c(void 0);try{const i=await l.publishToPlaystore({registryApiUrl:n,token:g,organizationId:v,accessToken:u,...a});return h===s.current&&(b(i.versionCode),r("published")),i}catch(i){h===s.current&&(t(y(i)),i instanceof l.PlaystorePublishError&&c(i.code),r("error"));return}finally{o.current=!1}},[n,g,v]),I=e.useCallback(()=>{s.current+=1,b(void 0),t(void 0),c(void 0),r(f.current?"ready":"idle")},[]);return{status:S,isSignedIn:P,versionCode:k,error:C,errorCode:p,preloadGoogle:G,signInWithGoogle:T,publish:E,reset:I}}function y(n){return n instanceof Error?n.message:String(n)}exports.usePlaystorePublish=q;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PlaystorePublishInput, PlaystorePublishResult } from './index';
|
|
2
|
+
export type UsePlaystorePublishOptions = Partial<Pick<PlaystorePublishInput, 'registryApiUrl' | 'token' | 'organizationId'>> & {
|
|
3
|
+
/** Google OAuth Web application client ID used for sign-in. */
|
|
4
|
+
googleClientId?: string;
|
|
5
|
+
};
|
|
6
|
+
export type PlaystorePublishStatus = 'idle' | 'signing-in' | 'ready' | 'publishing' | 'published' | 'error';
|
|
7
|
+
export type PlaystorePublishRequest = Omit<PlaystorePublishInput, 'registryApiUrl' | 'token' | 'organizationId' | 'accessToken'>;
|
|
8
|
+
export type UsePlaystorePublishResult = {
|
|
9
|
+
status: PlaystorePublishStatus;
|
|
10
|
+
isSignedIn: boolean;
|
|
11
|
+
versionCode?: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
/** Registry error code driving per-cause UX, e.g. versionCodeExists. */
|
|
14
|
+
errorCode?: string;
|
|
15
|
+
/** Warm up the Google sign-in script (e.g. on dialog open) so signInWithGoogle stays synchronous with the click. */
|
|
16
|
+
preloadGoogle: () => void;
|
|
17
|
+
signInWithGoogle: () => Promise<boolean>;
|
|
18
|
+
publish: (request: PlaystorePublishRequest) => Promise<PlaystorePublishResult | undefined>;
|
|
19
|
+
reset: () => void;
|
|
20
|
+
};
|
|
21
|
+
export declare function usePlaystorePublish({ registryApiUrl, token, organizationId, googleClientId, }: UsePlaystorePublishOptions): UsePlaystorePublishResult;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useState as c, useRef as g, useCallback as f } from "react";
|
|
2
|
+
import { loadGoogleIdentityServices as w, requestGoogleAccessToken as x, publishToPlaystore as q, PlaystorePublishError as D } from "./index.js";
|
|
3
|
+
function O({
|
|
4
|
+
registryApiUrl: t,
|
|
5
|
+
token: v,
|
|
6
|
+
organizationId: h,
|
|
7
|
+
googleClientId: d
|
|
8
|
+
}) {
|
|
9
|
+
const [S, e] = c("idle"), [G, R] = c(!1), [m, y] = c(), [P, r] = c(), [T, u] = c(), l = g(void 0), n = g(0), o = g(!1), k = f(() => {
|
|
10
|
+
w().catch(() => {
|
|
11
|
+
});
|
|
12
|
+
}, []), C = f(async () => {
|
|
13
|
+
if (o.current)
|
|
14
|
+
return !1;
|
|
15
|
+
if (!d)
|
|
16
|
+
return r("Google OAuth client ID is not configured."), e("error"), !1;
|
|
17
|
+
o.current = !0;
|
|
18
|
+
const a = n.current;
|
|
19
|
+
e("signing-in"), r(void 0), u(void 0);
|
|
20
|
+
try {
|
|
21
|
+
const s = await x({ clientId: d });
|
|
22
|
+
return l.current = s, a === n.current && (R(!0), e("ready")), !0;
|
|
23
|
+
} catch (s) {
|
|
24
|
+
return a === n.current && (r(p(s)), e("error")), !1;
|
|
25
|
+
} finally {
|
|
26
|
+
o.current = !1;
|
|
27
|
+
}
|
|
28
|
+
}, [d]), E = f(
|
|
29
|
+
async (a) => {
|
|
30
|
+
if (o.current)
|
|
31
|
+
return;
|
|
32
|
+
if (!t) {
|
|
33
|
+
r("Registry URL is not configured."), e("error");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const s = l.current;
|
|
37
|
+
if (!s) {
|
|
38
|
+
r("Sign in with Google before publishing."), e("error");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
o.current = !0;
|
|
42
|
+
const b = n.current;
|
|
43
|
+
e("publishing"), r(void 0), u(void 0);
|
|
44
|
+
try {
|
|
45
|
+
const i = await q({
|
|
46
|
+
registryApiUrl: t,
|
|
47
|
+
token: v,
|
|
48
|
+
organizationId: h,
|
|
49
|
+
accessToken: s,
|
|
50
|
+
...a
|
|
51
|
+
});
|
|
52
|
+
return b === n.current && (y(i.versionCode), e("published")), i;
|
|
53
|
+
} catch (i) {
|
|
54
|
+
b === n.current && (r(p(i)), i instanceof D && u(i.code), e("error"));
|
|
55
|
+
return;
|
|
56
|
+
} finally {
|
|
57
|
+
o.current = !1;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
[t, v, h]
|
|
61
|
+
), I = f(() => {
|
|
62
|
+
n.current += 1, y(void 0), r(void 0), u(void 0), e(l.current ? "ready" : "idle");
|
|
63
|
+
}, []);
|
|
64
|
+
return {
|
|
65
|
+
status: S,
|
|
66
|
+
isSignedIn: G,
|
|
67
|
+
versionCode: m,
|
|
68
|
+
error: P,
|
|
69
|
+
errorCode: T,
|
|
70
|
+
preloadGoogle: k,
|
|
71
|
+
signInWithGoogle: C,
|
|
72
|
+
publish: E,
|
|
73
|
+
reset: I
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function p(t) {
|
|
77
|
+
return t instanceof Error ? t.message : String(t);
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
O as usePlaystorePublish
|
|
81
|
+
};
|
|
@@ -224,15 +224,15 @@ export {
|
|
|
224
224
|
S as d,
|
|
225
225
|
v as e,
|
|
226
226
|
I as f,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
227
|
+
O as g,
|
|
228
|
+
q as h,
|
|
229
|
+
P as i,
|
|
230
|
+
y as j,
|
|
231
|
+
R as k,
|
|
232
232
|
g as l,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
w as m,
|
|
234
|
+
A as n,
|
|
235
|
+
H as o,
|
|
236
236
|
E as p,
|
|
237
237
|
D as r,
|
|
238
238
|
C as s
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@limrun/ui",
|
|
3
|
-
"version": "0.14.0-rc.
|
|
3
|
+
"version": "0.14.0-rc.3",
|
|
4
4
|
"publishConfig": {
|
|
5
|
-
"access": "public"
|
|
5
|
+
"access": "public",
|
|
6
|
+
"tag": "next"
|
|
6
7
|
},
|
|
7
8
|
"main": "./dist/index.js",
|
|
8
9
|
"module": "./dist/index.js",
|
|
@@ -43,6 +44,16 @@
|
|
|
43
44
|
"import": "./dist/device-install/react.js",
|
|
44
45
|
"require": "./dist/device-install/react.cjs"
|
|
45
46
|
},
|
|
47
|
+
"./play-publish": {
|
|
48
|
+
"types": "./dist/play-publish/index.d.ts",
|
|
49
|
+
"import": "./dist/play-publish/index.js",
|
|
50
|
+
"require": "./dist/play-publish/index.cjs"
|
|
51
|
+
},
|
|
52
|
+
"./play-publish/react": {
|
|
53
|
+
"types": "./dist/play-publish/react.d.ts",
|
|
54
|
+
"import": "./dist/play-publish/react.js",
|
|
55
|
+
"require": "./dist/play-publish/react.cjs"
|
|
56
|
+
},
|
|
46
57
|
"./package.json": "./package.json"
|
|
47
58
|
},
|
|
48
59
|
"scripts": {
|
|
@@ -21,12 +21,12 @@ describe('Registry relay primitives', () => {
|
|
|
21
21
|
expect(relay.request.mock.calls[0]).toMatchObject([
|
|
22
22
|
'provisioning',
|
|
23
23
|
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
method: 'POST',
|
|
25
|
+
path: '/account/ios/profile/deleteProvisioningProfile.action',
|
|
26
|
+
payload: {
|
|
27
|
+
teamId: 'TEAM',
|
|
28
|
+
provisioningProfileId: 'PROFILE',
|
|
29
|
+
},
|
|
30
30
|
},
|
|
31
31
|
]);
|
|
32
32
|
});
|
|
@@ -29,7 +29,11 @@ export type UseAppleIDLoginResult = {
|
|
|
29
29
|
close: () => Promise<void>;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
export function useAppleIDLogin({
|
|
32
|
+
export function useAppleIDLogin({
|
|
33
|
+
registryApiUrl,
|
|
34
|
+
token,
|
|
35
|
+
organizationId,
|
|
36
|
+
}: UseAppleIDLoginOptions): UseAppleIDLoginResult {
|
|
33
37
|
const [status, setStatus] = useState<AppleIDLoginStatus>('idle');
|
|
34
38
|
const [session, setSession] = useState<AppleIDLoginResult | undefined>();
|
|
35
39
|
const [completeResponse, setCompleteResponse] = useState<AppleRelayResponse | undefined>();
|
|
@@ -97,35 +97,3 @@
|
|
|
97
97
|
outline: 2px solid #2563eb;
|
|
98
98
|
outline-offset: 2px;
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
.rc-terminated {
|
|
102
|
-
position: absolute;
|
|
103
|
-
z-index: 50;
|
|
104
|
-
top: 50%;
|
|
105
|
-
left: 50%;
|
|
106
|
-
transform: translate(-50%, -50%);
|
|
107
|
-
display: flex;
|
|
108
|
-
flex-direction: column;
|
|
109
|
-
align-items: center;
|
|
110
|
-
gap: 4px;
|
|
111
|
-
max-width: 240px;
|
|
112
|
-
padding: 12px 18px;
|
|
113
|
-
border-radius: 16px;
|
|
114
|
-
text-align: center;
|
|
115
|
-
font: inherit;
|
|
116
|
-
background: rgba(255, 255, 255, 0.92);
|
|
117
|
-
color: #111827;
|
|
118
|
-
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.rc-terminated-title {
|
|
122
|
-
font: inherit;
|
|
123
|
-
font-weight: 600;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.rc-terminated-message {
|
|
127
|
-
font: inherit;
|
|
128
|
-
font-size: 0.8125rem;
|
|
129
|
-
line-height: 1.3;
|
|
130
|
-
color: #6b7280;
|
|
131
|
-
}
|