shipthis 0.1.31 → 0.1.33
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/{AppleBundleIdDetails-eoK5F8Qn.js → AppleBundleIdDetails-BhHPCvRm.js} +17 -19
- package/dist/Command-BDIkuv2g.js +29 -0
- package/dist/CommandGame-CvBIjPZp.js +7 -0
- package/dist/{Create-ISdroJ3G.js → Create-Lpe0B8nT.js} +20 -20
- package/dist/GameStatus-5XpufIY_.js +137 -0
- package/dist/{Import-CfThJF6k.js → Import-DFzrAG04.js} +34 -36
- package/dist/{JobLogTail-BWzbQBZz.js → JobLogTail-BYcJgPcL.js} +53 -52
- package/dist/{JobProgress-DjIkuk5U.js → JobProgress-BcrE7CUK.js} +40 -38
- package/dist/{JobStatusTable-CEqWU73q.js → JobStatusTable-Bi-y8ZZT.js} +14 -13
- package/dist/{NextSteps-CK9zHOCt.js → NextSteps-DbJHmscQ.js} +1 -3
- package/dist/{ProgressSpinner-6pw1T8Iw.js → ProgressSpinner-Um6ARKlk.js} +2 -2
- package/dist/{ProjectCredentialsTable-u9ruZ9mN.js → ProjectCredentialsTable-B4vDJl4l.js} +11 -10
- package/dist/{StatusTable-Dm5St4g-.js → StatusTable-DzRWcMr4.js} +7 -9
- package/dist/{Table-CvM6pccN.js → Table-FaNgpyeq.js} +15 -15
- package/dist/{UserCredentialsTable-Q7u9M-ap.js → UserCredentialsTable-CwkZTFBD.js} +18 -19
- package/dist/{baseAppleCommand-zhkGlKq0.js → baseAppleCommand-BKXweb-U.js} +1 -1
- package/dist/{baseGameAndroidCommand-DJ-cMLa_.js → baseGameAndroidCommand-CAi-BSsH.js} +23 -23
- package/dist/commands/apple/apiKey/create.js +36 -36
- package/dist/commands/apple/apiKey/export.js +27 -27
- package/dist/commands/apple/apiKey/import.js +28 -28
- package/dist/commands/apple/apiKey/status.js +32 -32
- package/dist/commands/apple/certificate/create.js +40 -40
- package/dist/commands/apple/certificate/export.js +27 -27
- package/dist/commands/apple/certificate/import.js +28 -28
- package/dist/commands/apple/certificate/status.js +33 -33
- package/dist/commands/apple/login.js +15 -15
- package/dist/commands/apple/status.js +27 -27
- package/dist/commands/dashboard.js +10 -10
- package/dist/commands/game/android/apiKey/connect.js +28 -28
- package/dist/commands/game/android/apiKey/create.js +29 -29
- package/dist/commands/game/android/apiKey/export.js +30 -30
- package/dist/commands/game/android/apiKey/import.js +32 -32
- package/dist/commands/game/android/apiKey/invite.js +14 -14
- package/dist/commands/game/android/apiKey/status.js +30 -30
- package/dist/commands/game/android/keyStore/create.js +25 -25
- package/dist/commands/game/android/keyStore/export.js +29 -29
- package/dist/commands/game/android/keyStore/import.js +36 -36
- package/dist/commands/game/android/keyStore/status.js +26 -26
- package/dist/commands/game/android/status.js +15 -58
- package/dist/commands/game/build/download.js +24 -24
- package/dist/commands/game/build/list.js +37 -37
- package/dist/commands/game/create.js +15 -15
- package/dist/commands/game/details.js +35 -36
- package/dist/commands/game/export.js +12 -12
- package/dist/commands/game/ios/app/addTester.js +37 -32
- package/dist/commands/game/ios/app/create.js +24 -24
- package/dist/commands/game/ios/app/status.js +29 -29
- package/dist/commands/game/ios/app/sync.js +31 -31
- package/dist/commands/game/ios/profile/create.js +32 -32
- package/dist/commands/game/ios/profile/export.js +29 -29
- package/dist/commands/game/ios/profile/import.js +33 -33
- package/dist/commands/game/ios/profile/status.js +36 -36
- package/dist/commands/game/ios/status.js +46 -58
- package/dist/commands/game/ios/wizard.js +39 -34
- package/dist/commands/game/job/list.js +34 -34
- package/dist/commands/game/job/status.js +32 -32
- package/dist/commands/game/list.js +38 -40
- package/dist/commands/game/ship.js +81 -77
- package/dist/commands/game/status.js +38 -85
- package/dist/commands/game/wizard.js +253 -242
- package/dist/commands/internal/fastlane.js +15 -17
- package/dist/commands/internal/readme.js +38 -36
- package/dist/commands/login.js +14 -14
- package/dist/commands/status.js +32 -30
- package/dist/{export-DZxo2_e_.js → export-DLQrUEBK.js} +5 -5
- package/dist/{git-DREGq-jc.js → git-BpsfNFZ_.js} +8 -8
- package/dist/{import-8pL1AF47.js → import-BoY5e0uJ.js} +14 -14
- package/dist/{index-DJ078v-U.js → index-B27WJDxn.js} +43 -27
- package/dist/{index-DKQjnJrC.js → index-CisLwc7e.js} +42 -44
- package/dist/{index-C6aAyrXW.js → index-Crv7S0bl.js} +6 -6
- package/dist/{index-BHh0BZvD.js → index-DC0GJtAy.js} +50 -60
- package/dist/{index-CyvGh-kt.js → index-DfUg5j06.js} +93 -92
- package/dist/{index-w3lHxk5O.js → index-pj8JVg5X.js} +242 -225
- package/dist/{upload-BTpxj3QP.js → upload-C8S17EU_.js} +22 -22
- package/dist/{useAndroidServiceAccountTestResult-Dy3Ag7_r.js → useAndroidServiceAccountTestResult-D4e5AKAZ.js} +11 -13
- package/dist/{useAppleApp-h1Ogi_qc.js → useAppleApp-Dr6URQvC.js} +4 -4
- package/dist/{useAppleBundleId-B3TTNap0.js → useAppleBundleId-DELAwSQp.js} +6 -6
- package/dist/{useProjectCredentials-DpeXZcHP.js → useProjectCredentials-BjvdJdQg.js} +10 -12
- package/dist/{useWebSocket-gyuCsore.js → useWebSocket-CRV7V69Q.js} +1 -1
- package/dist/utils/help.js +4 -4
- package/package.json +5 -4
- package/dist/Command-DFdHXDiU.js +0 -44
- package/dist/CommandGame-Dif-oSky.js +0 -9
- package/dist/{RunWithSpinner-BVXNWGD3.js → RunWithSpinner-gMVA07bZ.js} +2 -2
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
import { useState, useRef, useEffect, useContext } from 'react';
|
|
4
3
|
import Spinner from 'ink-spinner';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import 'crypto-js';
|
|
9
|
-
import 'uuid';
|
|
10
|
-
import 'fs';
|
|
11
|
-
import 'luxon';
|
|
12
|
-
import '@inkjs/ui';
|
|
13
|
-
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
14
|
-
import 'yazl';
|
|
15
|
-
import 'crypto';
|
|
16
|
-
import 'readline-sync';
|
|
17
|
-
import 'node:readline';
|
|
4
|
+
import { useState, useRef, useEffect, useContext } from 'react';
|
|
5
|
+
import 'node:crypto';
|
|
6
|
+
import 'node:fs';
|
|
18
7
|
import 'node:path';
|
|
8
|
+
import 'node:readline';
|
|
19
9
|
import 'node:url';
|
|
10
|
+
import 'readline-sync';
|
|
11
|
+
import 'luxon';
|
|
12
|
+
import axios from 'axios';
|
|
20
13
|
import 'isomorphic-git';
|
|
14
|
+
import { p as getAuthedHeaders, o as API_URL, a1 as castObjectDates, P as Platform, C as CredentialsType, Q as getGoogleStatus } from './index-pj8JVg5X.js';
|
|
21
15
|
import '@oclif/core';
|
|
22
|
-
import {
|
|
16
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
17
|
+
import { c as cacheKeys } from './useAndroidServiceAccountTestResult-D4e5AKAZ.js';
|
|
23
18
|
import 'fast-glob';
|
|
19
|
+
import 'uuid';
|
|
20
|
+
import 'yazl';
|
|
24
21
|
import 'socket.io-client';
|
|
25
|
-
import
|
|
26
|
-
import { u as
|
|
22
|
+
import 'fullscreen-ink';
|
|
23
|
+
import { u as useWebSocket } from './useWebSocket-CRV7V69Q.js';
|
|
24
|
+
import { u as useProjectCredentials } from './useProjectCredentials-BjvdJdQg.js';
|
|
25
|
+
import 'crypto-js';
|
|
26
|
+
import 'string-length';
|
|
27
|
+
import 'strip-ansi';
|
|
27
28
|
import 'open';
|
|
29
|
+
import '@inkjs/ui';
|
|
28
30
|
import 'marked';
|
|
29
31
|
import 'marked-terminal';
|
|
30
|
-
import '
|
|
31
|
-
import { P as ProgressSpinner } from './ProgressSpinner-6pw1T8Iw.js';
|
|
32
|
+
import { P as ProgressSpinner } from './ProgressSpinner-Um6ARKlk.js';
|
|
32
33
|
import 'qrcode';
|
|
33
|
-
import '
|
|
34
|
-
import 'strip-ansi';
|
|
34
|
+
import { G as GameContext } from './index-DfUg5j06.js';
|
|
35
35
|
|
|
36
36
|
async function fetchStatus({ projectId }) {
|
|
37
37
|
try {
|
|
@@ -45,37 +45,35 @@ async function fetchStatus({ projectId }) {
|
|
|
45
45
|
throw error;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
const useAndroidServiceAccountSetupStatus = (props) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
56
|
-
};
|
|
48
|
+
const useAndroidServiceAccountSetupStatus = (props) => useQuery({
|
|
49
|
+
queryFn: () => fetchStatus(props),
|
|
50
|
+
queryKey: cacheKeys.androidSetupStatus(props),
|
|
51
|
+
// Status changes frequently, so we want to keep it fresh
|
|
52
|
+
refetchInterval: 1e3 * 5,
|
|
53
|
+
staleTime: 1e3 * 5
|
|
54
|
+
});
|
|
57
55
|
|
|
58
56
|
const ERR_NOT_AUTHENTICATED = "You must be connected to Google to create a Service Account Key";
|
|
59
57
|
const useHasServiceAccountKey = (projectId) => {
|
|
60
|
-
const { data, isSuccess } = useProjectCredentials({
|
|
61
|
-
return isSuccess && data.data.some((cred) => cred.isActive && cred.platform === Platform.ANDROID && cred.type
|
|
58
|
+
const { data, isSuccess } = useProjectCredentials({ platform: Platform.ANDROID, projectId });
|
|
59
|
+
return isSuccess && data.data.some((cred) => cred.isActive && cred.platform === Platform.ANDROID && cred.type === CredentialsType.KEY);
|
|
62
60
|
};
|
|
63
|
-
const useAndroidServiceAccount = ({
|
|
61
|
+
const useAndroidServiceAccount = ({ onComplete, onError, projectId }) => {
|
|
64
62
|
const queryClient = useQueryClient();
|
|
65
63
|
const [isStarting, setIsStarting] = useState(false);
|
|
66
64
|
const hasServiceAccountKey = useHasServiceAccountKey(projectId);
|
|
67
65
|
const listener = {
|
|
68
|
-
|
|
69
|
-
eventHandler: async (pattern, data) => {
|
|
66
|
+
async eventHandler(pattern, data) {
|
|
70
67
|
const key = cacheKeys.androidSetupStatus({ projectId });
|
|
71
68
|
queryClient.setQueryData(key, () => data);
|
|
72
|
-
}
|
|
69
|
+
},
|
|
70
|
+
getPattern: () => `project.${projectId}:android-setup-status`
|
|
73
71
|
};
|
|
74
72
|
useWebSocket([listener]);
|
|
75
73
|
const { data: setupStatus } = useAndroidServiceAccountSetupStatus({ projectId });
|
|
76
74
|
const prevSetupStatusRef = useRef("unknown");
|
|
77
75
|
useEffect(() => {
|
|
78
|
-
if (["
|
|
76
|
+
if (["queued", "running"].includes(prevSetupStatusRef.current)) {
|
|
79
77
|
if (setupStatus?.status === "complete") onComplete();
|
|
80
78
|
if (setupStatus?.status === "error") onError(new Error(setupStatus.errorMessage));
|
|
81
79
|
}
|
|
@@ -91,7 +89,7 @@ const useAndroidServiceAccount = ({ projectId, onError, onComplete }) => {
|
|
|
91
89
|
const startUrl = `${androidKeyApiBase}/setup/`;
|
|
92
90
|
const { data: updatedStatus } = await axios.post(startUrl, {}, { headers });
|
|
93
91
|
queryClient.invalidateQueries({
|
|
94
|
-
queryKey: cacheKeys.projectCredentials({
|
|
92
|
+
queryKey: cacheKeys.projectCredentials({ pageNumber: 0, projectId })
|
|
95
93
|
});
|
|
96
94
|
await queryClient.setQueryData(cacheKeys.androidSetupStatus({ projectId }), (_) => updatedStatus);
|
|
97
95
|
setIsStarting(false);
|
|
@@ -106,9 +104,9 @@ const useAndroidServiceAccount = ({ projectId, onError, onComplete }) => {
|
|
|
106
104
|
const isCreating = isStarting || setupStatus?.status === "queued" || setupStatus?.status === "running";
|
|
107
105
|
return {
|
|
108
106
|
handleStart,
|
|
109
|
-
|
|
107
|
+
hasServiceAccountKey,
|
|
110
108
|
isCreating,
|
|
111
|
-
|
|
109
|
+
setupStatus
|
|
112
110
|
};
|
|
113
111
|
};
|
|
114
112
|
|
|
@@ -116,12 +114,12 @@ const CreateServiceAccountKey = (props) => {
|
|
|
116
114
|
const { gameId } = useContext(GameContext);
|
|
117
115
|
return /* @__PURE__ */ jsx(Fragment, { children: gameId && /* @__PURE__ */ jsx(CreateForGame, { gameId, ...props }) });
|
|
118
116
|
};
|
|
119
|
-
const CreateForGame = ({ onComplete, onError,
|
|
117
|
+
const CreateForGame = ({ gameId, onComplete, onError, ...boxProps }) => {
|
|
120
118
|
const [didStart, setDidStart] = useState(false);
|
|
121
|
-
const { handleStart,
|
|
122
|
-
|
|
119
|
+
const { handleStart, isCreating, setupStatus } = useAndroidServiceAccount({
|
|
120
|
+
onComplete,
|
|
123
121
|
onError,
|
|
124
|
-
|
|
122
|
+
projectId: gameId
|
|
125
123
|
});
|
|
126
124
|
useEffect(() => {
|
|
127
125
|
handleStart().then(() => setDidStart(true));
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import {
|
|
3
|
-
import 'fs';
|
|
2
|
+
import { o as API_URL, p as getAuthedHeaders, I as castArrayObjectDates } from './index-pj8JVg5X.js';
|
|
3
|
+
import 'node:fs';
|
|
4
4
|
|
|
5
5
|
async function getUserCredentials(pageSize = 100) {
|
|
6
6
|
const headers = getAuthedHeaders();
|
|
7
7
|
const { data } = await axios({
|
|
8
|
+
headers,
|
|
8
9
|
method: "get",
|
|
9
|
-
url: `${API_URL}/credentials?pageSize=${pageSize}
|
|
10
|
-
headers
|
|
10
|
+
url: `${API_URL}/credentials?pageSize=${pageSize}`
|
|
11
11
|
});
|
|
12
12
|
return castArrayObjectDates(data.data);
|
|
13
13
|
}
|
|
14
14
|
async function getProjectCredentials(projectId, pageSize = 100) {
|
|
15
15
|
const headers = getAuthedHeaders();
|
|
16
16
|
const { data } = await axios({
|
|
17
|
+
headers,
|
|
17
18
|
method: "get",
|
|
18
|
-
url: `${API_URL}/projects/${projectId}/credentials?pageSize=${pageSize}
|
|
19
|
-
headers
|
|
19
|
+
url: `${API_URL}/projects/${projectId}/credentials?pageSize=${pageSize}`
|
|
20
20
|
});
|
|
21
21
|
return castArrayObjectDates(data.data);
|
|
22
22
|
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { Text,
|
|
2
|
+
import { Text, Box } from 'ink';
|
|
3
3
|
import open from 'open';
|
|
4
4
|
import { useState, useEffect, useContext } from 'react';
|
|
5
|
-
import
|
|
6
|
-
import 'crypto';
|
|
7
|
-
import 'fs';
|
|
8
|
-
import 'readline-sync';
|
|
9
|
-
import 'node:readline';
|
|
5
|
+
import 'ink-spinner';
|
|
6
|
+
import 'node:crypto';
|
|
7
|
+
import 'node:fs';
|
|
10
8
|
import 'node:path';
|
|
9
|
+
import 'node:readline';
|
|
11
10
|
import 'node:url';
|
|
11
|
+
import 'readline-sync';
|
|
12
12
|
import 'luxon';
|
|
13
13
|
import 'axios';
|
|
14
14
|
import 'isomorphic-git';
|
|
15
|
+
import { Q as getGoogleStatus, a2 as getShortAuthRequiredUrl, a3 as getGoogleAuthUrl, W as WEB_URL } from './index-pj8JVg5X.js';
|
|
15
16
|
import '@oclif/core';
|
|
16
17
|
import { useQuery } from '@tanstack/react-query';
|
|
17
18
|
import 'crypto-js';
|
|
@@ -19,70 +20,52 @@ import 'uuid';
|
|
|
19
20
|
import 'fast-glob';
|
|
20
21
|
import 'yazl';
|
|
21
22
|
import 'socket.io-client';
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
26
|
-
import 'ink-spinner';
|
|
27
|
-
import '@inkjs/ui';
|
|
23
|
+
import { c as cacheKeys } from './useAndroidServiceAccountTestResult-D4e5AKAZ.js';
|
|
24
|
+
import { u as useWebSocket } from './useWebSocket-CRV7V69Q.js';
|
|
25
|
+
import 'fullscreen-ink';
|
|
26
|
+
import { G as GameContext, e as useSafeInput, M as Markdown } from './index-DfUg5j06.js';
|
|
28
27
|
import 'string-length';
|
|
29
28
|
import 'strip-ansi';
|
|
29
|
+
import '@inkjs/ui';
|
|
30
30
|
import 'marked';
|
|
31
31
|
import 'marked-terminal';
|
|
32
|
-
import 'path';
|
|
33
32
|
import qrcode from 'qrcode';
|
|
34
33
|
|
|
35
|
-
const useGoogleStatus = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
40
|
-
};
|
|
34
|
+
const useGoogleStatus = () => useQuery({
|
|
35
|
+
queryFn: getGoogleStatus,
|
|
36
|
+
queryKey: cacheKeys.googleStatus()
|
|
37
|
+
});
|
|
41
38
|
|
|
42
39
|
function useGoogleStatusWatching({
|
|
43
|
-
projectId,
|
|
44
40
|
isWatching,
|
|
45
|
-
onGoogleStatusUpdate
|
|
41
|
+
onGoogleStatusUpdate,
|
|
42
|
+
projectId
|
|
46
43
|
}) {
|
|
47
44
|
const [wsGoogleStatus, setWsGoogleStatus] = useState(null);
|
|
48
45
|
const listener = {
|
|
49
|
-
|
|
50
|
-
eventHandler: async (pattern, data2) => {
|
|
46
|
+
async eventHandler(pattern, data2) {
|
|
51
47
|
setWsGoogleStatus(data2);
|
|
52
48
|
if (onGoogleStatusUpdate) onGoogleStatusUpdate(data2);
|
|
53
|
-
}
|
|
49
|
+
},
|
|
50
|
+
getPattern: () => `project.${projectId}:google-status`
|
|
54
51
|
};
|
|
55
52
|
useWebSocket([listener] );
|
|
56
|
-
const {
|
|
53
|
+
const { data: googleStatus, isLoading } = useGoogleStatus();
|
|
57
54
|
useEffect(() => {
|
|
58
55
|
setWsGoogleStatus(null);
|
|
59
56
|
}, [projectId, isWatching, googleStatus]);
|
|
60
57
|
const fetchedGoogleStatus = googleStatus ? googleStatus : null;
|
|
61
58
|
const data = wsGoogleStatus ? wsGoogleStatus : fetchedGoogleStatus;
|
|
62
59
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const WIDE_BREAKPOINT = 100;
|
|
69
|
-
const TALL_BREAKPOINT = 35;
|
|
70
|
-
function useResponsive() {
|
|
71
|
-
const { width, height } = useScreenSize();
|
|
72
|
-
const isWide = width >= WIDE_BREAKPOINT;
|
|
73
|
-
const isTall = height >= TALL_BREAKPOINT;
|
|
74
|
-
return {
|
|
75
|
-
width,
|
|
76
|
-
height,
|
|
77
|
-
isWide,
|
|
78
|
-
isTall
|
|
60
|
+
data,
|
|
61
|
+
isLoading
|
|
79
62
|
};
|
|
80
63
|
}
|
|
81
64
|
|
|
82
65
|
const QRCodeTerminal = ({ url }) => {
|
|
83
66
|
const [code, setCode] = useState(null);
|
|
84
67
|
const handleLoad = async () => {
|
|
85
|
-
const codeString = await qrcode.toString(url, {
|
|
68
|
+
const codeString = await qrcode.toString(url, { errorCorrectionLevel: "L", small: true, type: "terminal" });
|
|
86
69
|
setCode(codeString);
|
|
87
70
|
};
|
|
88
71
|
useEffect(() => {
|
|
@@ -112,31 +95,38 @@ const ConnectGoogle = (props) => {
|
|
|
112
95
|
const { gameId } = useContext(GameContext);
|
|
113
96
|
return /* @__PURE__ */ jsx(Fragment, { children: gameId && /* @__PURE__ */ jsx(ConnectForGame, { gameId, ...props }) });
|
|
114
97
|
};
|
|
115
|
-
const ConnectForGame = ({
|
|
116
|
-
const
|
|
117
|
-
const [
|
|
98
|
+
const ConnectForGame = ({ gameId, helpPage, onComplete, onError, ...boxProps }) => {
|
|
99
|
+
const [showQRCode, setShowQRCode] = useState(false);
|
|
100
|
+
const [connectUrl, setConnectUrl] = useState(null);
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const fetchConnectUrl = async () => {
|
|
103
|
+
const url = await getConnectUrl(gameId, Boolean(helpPage));
|
|
104
|
+
setConnectUrl(url);
|
|
105
|
+
};
|
|
106
|
+
if (!connectUrl) fetchConnectUrl();
|
|
107
|
+
}, []);
|
|
118
108
|
useGoogleStatusWatching({
|
|
119
|
-
projectId: gameId,
|
|
120
109
|
isWatching: true,
|
|
121
|
-
onGoogleStatusUpdate
|
|
110
|
+
onGoogleStatusUpdate(status) {
|
|
122
111
|
if (status.isAuthenticated) return onComplete();
|
|
123
|
-
}
|
|
112
|
+
},
|
|
113
|
+
projectId: gameId
|
|
124
114
|
});
|
|
125
|
-
|
|
115
|
+
useSafeInput(async (input) => {
|
|
126
116
|
switch (input) {
|
|
127
|
-
case "q":
|
|
117
|
+
case "q": {
|
|
128
118
|
setShowQRCode(true);
|
|
129
119
|
return;
|
|
130
|
-
|
|
120
|
+
}
|
|
121
|
+
case "x": {
|
|
131
122
|
setShowQRCode(false);
|
|
132
123
|
return;
|
|
133
|
-
|
|
124
|
+
}
|
|
125
|
+
case "b": {
|
|
134
126
|
if (!gameId) return;
|
|
135
|
-
|
|
136
|
-
await open(
|
|
137
|
-
|
|
138
|
-
default:
|
|
139
|
-
return;
|
|
127
|
+
if (!connectUrl) return;
|
|
128
|
+
await open(connectUrl);
|
|
129
|
+
}
|
|
140
130
|
}
|
|
141
131
|
});
|
|
142
132
|
const templateVars = {
|
|
@@ -145,15 +135,15 @@ const ConnectForGame = ({ onComplete, onError, helpPage, gameId, ...boxProps })
|
|
|
145
135
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, ...boxProps, children: [
|
|
146
136
|
!showQRCode && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
147
137
|
/* @__PURE__ */ jsx(Markdown, { filename: "privacy-notification.md", templateVars }),
|
|
148
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "#4CE64C", children:
|
|
138
|
+
connectUrl && /* @__PURE__ */ jsx(Text, { bold: true, color: "#4CE64C", children: `Press B to open ${connectUrl} in your browser and connect your Google account to ShipThis` }),
|
|
149
139
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "#4CE64C", children: "Press Q to show a QR-code to connect using your mobile phone" })
|
|
150
140
|
] }),
|
|
151
141
|
showQRCode && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
152
142
|
/* @__PURE__ */ jsx(Text, { children: "Scan the QR code below to connect your Google account to ShipThis:" }),
|
|
153
|
-
gameId && /* @__PURE__ */ jsx(GoogleAuthQRCode, { gameId, helpPage:
|
|
143
|
+
gameId && /* @__PURE__ */ jsx(GoogleAuthQRCode, { gameId, helpPage: Boolean(helpPage) }),
|
|
154
144
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "#4CE64C", children: "Press X to hide the QR code" })
|
|
155
145
|
] })
|
|
156
146
|
] });
|
|
157
147
|
};
|
|
158
148
|
|
|
159
|
-
export { ConnectGoogle as C
|
|
149
|
+
export { ConnectGoogle as C };
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
|
+
import { useStdin, useInput, Text, Box } from 'ink';
|
|
4
3
|
import Spinner from 'ink-spinner';
|
|
5
4
|
import open from 'open';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import '@inkjs/ui';
|
|
10
|
-
import axios from 'axios';
|
|
5
|
+
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
6
|
+
import { p as getAuthedHeaders, o as API_URL, I as castArrayObjectDates, P as Platform, a6 as getShortDateTime, J as JobStatus, a7 as getShortTimeDelta, z as getJob, E as getProject, a2 as getShortAuthRequiredUrl, K as queryClient, a8 as BuildType, W as WEB_URL } from './index-pj8JVg5X.js';
|
|
7
|
+
import { h as getPlatformName, g as getShortUUID, s as scriptDir } from './index-B27WJDxn.js';
|
|
11
8
|
import { useQuery } from '@tanstack/react-query';
|
|
12
|
-
import
|
|
9
|
+
import axios from 'axios';
|
|
10
|
+
import { c as cacheKeys, u as useAndroidServiceAccountTestResult, K as KeyTestStatus, a as KeyTestError } from './useAndroidServiceAccountTestResult-D4e5AKAZ.js';
|
|
11
|
+
import 'luxon';
|
|
12
|
+
import fs__default from 'node:fs';
|
|
13
|
+
import 'fast-glob';
|
|
13
14
|
import 'uuid';
|
|
14
15
|
import 'yazl';
|
|
16
|
+
import 'socket.io-client';
|
|
17
|
+
import 'fullscreen-ink';
|
|
18
|
+
import 'string-length';
|
|
19
|
+
import 'strip-ansi';
|
|
20
|
+
import '@inkjs/ui';
|
|
21
|
+
import path from 'node:path';
|
|
15
22
|
import { setOptions, parse } from 'marked';
|
|
16
23
|
import TerminalRenderer from 'marked-terminal';
|
|
17
|
-
import path from 'path';
|
|
18
24
|
import 'qrcode';
|
|
19
|
-
import 'string-length';
|
|
20
|
-
import 'strip-ansi';
|
|
21
|
-
import 'luxon';
|
|
22
|
-
import 'fast-glob';
|
|
23
|
-
import 'socket.io-client';
|
|
24
25
|
|
|
25
26
|
async function queryBuilds({ projectId, ...pageAndSortParams }) {
|
|
26
27
|
try {
|
|
@@ -37,21 +38,21 @@ async function queryBuilds({ projectId, ...pageAndSortParams }) {
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
function getBuildSummary(build) {
|
|
40
|
-
const ext = build.buildType || (build.platform
|
|
41
|
+
const ext = build.buildType || (build.platform === Platform.IOS ? "IPA" : "AAB");
|
|
41
42
|
const filename = `game.${ext.toLowerCase()}`;
|
|
42
43
|
return {
|
|
43
44
|
id: getShortUUID(build.id),
|
|
44
45
|
jobId: getShortUUID(build.jobId),
|
|
45
46
|
...getJobDetailsSummary(build.jobDetails),
|
|
46
|
-
|
|
47
|
+
cmd: `shipthis game build download ${getShortUUID(build.id)} ${filename}`,
|
|
47
48
|
createdAt: getShortDateTime(build.createdAt),
|
|
48
|
-
|
|
49
|
+
type: `${getPlatformName(build.platform)} ${build.buildType || ""}`.trim()
|
|
49
50
|
};
|
|
50
51
|
}
|
|
51
52
|
const useBuilds = (props) => {
|
|
52
53
|
const queryResult = useQuery({
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
queryFn: async () => queryBuilds(props),
|
|
55
|
+
queryKey: cacheKeys.builds(props)
|
|
55
56
|
});
|
|
56
57
|
return queryResult;
|
|
57
58
|
};
|
|
@@ -62,8 +63,8 @@ function getJobDetailsSummary(jobDetails) {
|
|
|
62
63
|
const gitCommit = jobDetails?.gitCommitHash ? getShortUUID(jobDetails?.gitCommitHash) : "";
|
|
63
64
|
const gitBranch = jobDetails?.gitBranch || "";
|
|
64
65
|
return {
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
gitInfo: gitCommit ? `${gitCommit} (${gitBranch})` : "",
|
|
67
|
+
version: `${semanticVersion} (${buildNumber})`
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
function getJobSummary(job, timeNow) {
|
|
@@ -71,65 +72,34 @@ function getJobSummary(job, timeNow) {
|
|
|
71
72
|
return {
|
|
72
73
|
id: getShortUUID(job.id),
|
|
73
74
|
...getJobDetailsSummary(job.details),
|
|
74
|
-
platform: getPlatformName(job.type),
|
|
75
|
-
status: job.status,
|
|
76
75
|
createdAt: getShortDateTime(job.createdAt),
|
|
77
|
-
|
|
76
|
+
platform: getPlatformName(job.type),
|
|
77
|
+
runtime: getShortTimeDelta(job.createdAt, inProgress ? timeNow : job.updatedAt),
|
|
78
|
+
status: job.status
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
|
-
const useJob = (props) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
queryFn: () => getJob(props.jobId, props.projectId)
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const CommandContext = React.createContext({
|
|
88
|
-
command: null,
|
|
89
|
-
setCommand: (command) => {
|
|
90
|
-
}
|
|
81
|
+
const useJob = (props) => useQuery({
|
|
82
|
+
queryFn: () => getJob(props.jobId, props.projectId),
|
|
83
|
+
queryKey: cacheKeys.job(props)
|
|
91
84
|
});
|
|
92
|
-
const CommandProvider = (props) => {
|
|
93
|
-
const [command, setCommand] = useState(props.command || null);
|
|
94
|
-
return /* @__PURE__ */ jsx(CommandContext.Provider, { value: { command, setCommand }, children: props.children });
|
|
95
|
-
};
|
|
96
85
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const handleLoad = async () => {
|
|
108
|
-
if (command) {
|
|
109
|
-
const commandGameId = await command.getGameId();
|
|
110
|
-
if (commandGameId) setGameId(commandGameId);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
const handleGameIdChange = async () => {
|
|
114
|
-
if (!gameId) {
|
|
115
|
-
setGame(null);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const game2 = await getProject(gameId);
|
|
119
|
-
setGame(game2);
|
|
120
|
-
};
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
handleGameIdChange();
|
|
123
|
-
}, [gameId]);
|
|
124
|
-
useEffect(() => {
|
|
125
|
-
handleLoad();
|
|
126
|
-
}, [command]);
|
|
127
|
-
return /* @__PURE__ */ jsx(GameContext.Provider, { value: { gameId, game, setGameId }, children });
|
|
86
|
+
const useSafeInput = (handler, options = { isActive: true }) => {
|
|
87
|
+
const { isRawModeSupported } = useStdin();
|
|
88
|
+
const isActive = isRawModeSupported === true && options.isActive !== false;
|
|
89
|
+
useInput(
|
|
90
|
+
(input, key) => {
|
|
91
|
+
const lowerInput = input.toLowerCase();
|
|
92
|
+
return handler(lowerInput, key);
|
|
93
|
+
},
|
|
94
|
+
{ isActive }
|
|
95
|
+
);
|
|
128
96
|
};
|
|
129
97
|
|
|
130
|
-
const cleanHyperlinks = (input) =>
|
|
131
|
-
|
|
132
|
-
|
|
98
|
+
const cleanHyperlinks = (input) => (
|
|
99
|
+
// When we run in a <ScrollArea> the links break
|
|
100
|
+
// Remove OSC 8 hyperlink wrappers but preserve the styled content inside
|
|
101
|
+
input.replaceAll(/\u001B]8;;[^\u0007]*\u0007/g, "").replaceAll("\x1B]8;;\x07", "")
|
|
102
|
+
);
|
|
133
103
|
const getRenderedMarkdown = ({ filename, templateVars, ...options }) => {
|
|
134
104
|
setOptions({
|
|
135
105
|
renderer: new TerminalRenderer({
|
|
@@ -142,10 +112,8 @@ const getRenderedMarkdown = ({ filename, templateVars, ...options }) => {
|
|
|
142
112
|
const mdTemplate = fs__default.readFileSync(mdPath, "utf8").trim();
|
|
143
113
|
let markdown = mdTemplate;
|
|
144
114
|
if (templateVars) {
|
|
145
|
-
markdown = markdown.
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
markdown = markdown.replace(/\${(.*?)}/g, (_, key) => {
|
|
115
|
+
markdown = markdown.replaceAll(/\${if (.*?)}([\S\s]*?)\${endif}/g, (_, key, content) => templateVars[key.trim()] ? content : "");
|
|
116
|
+
markdown = markdown.replaceAll(/\${(.*?)}/g, (_, key) => {
|
|
149
117
|
const trimmed = key.trim();
|
|
150
118
|
return templateVars[trimmed] ? String(templateVars[trimmed]) : "";
|
|
151
119
|
});
|
|
@@ -163,6 +131,40 @@ const Markdown = ({ filename, templateVars, ...options }) => {
|
|
|
163
131
|
return /* @__PURE__ */ jsx(Text, { children: text });
|
|
164
132
|
};
|
|
165
133
|
|
|
134
|
+
const CommandContext = React.createContext({
|
|
135
|
+
command: null,
|
|
136
|
+
setCommand(command) {
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
const CommandProvider = (props) => {
|
|
140
|
+
const [command, setCommand] = useState(props.command || null);
|
|
141
|
+
return /* @__PURE__ */ jsx(CommandContext.Provider, { value: { command, setCommand }, children: props.children });
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const GameContext = React.createContext({
|
|
145
|
+
game: null,
|
|
146
|
+
gameId: null,
|
|
147
|
+
setGameId(gameId) {
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
const GameProvider = ({ children }) => {
|
|
151
|
+
const { command } = React.useContext(CommandContext);
|
|
152
|
+
const [gameId, setGameId] = useState(command?.getGameId() || null);
|
|
153
|
+
const [game, setGame] = useState(null);
|
|
154
|
+
const handleGameIdChange = async () => {
|
|
155
|
+
if (!gameId) {
|
|
156
|
+
setGame(null);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const game2 = await getProject(gameId);
|
|
160
|
+
setGame(game2);
|
|
161
|
+
};
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
handleGameIdChange();
|
|
164
|
+
}, [gameId]);
|
|
165
|
+
return /* @__PURE__ */ jsx(GameContext.Provider, { value: { game, gameId, setGameId }, children });
|
|
166
|
+
};
|
|
167
|
+
|
|
166
168
|
scriptDir(import.meta);
|
|
167
169
|
const getIsAppFound = (result) => {
|
|
168
170
|
const isFound = result?.status === KeyTestStatus.SUCCESS || result?.status === KeyTestStatus.ERROR && result?.error === KeyTestError.NOT_INVITED;
|
|
@@ -172,9 +174,9 @@ const CreateGooglePlayGame = (props) => {
|
|
|
172
174
|
const { gameId } = useContext(GameContext);
|
|
173
175
|
return /* @__PURE__ */ jsx(Fragment, { children: gameId && /* @__PURE__ */ jsx(Create, { gameId, ...props }) });
|
|
174
176
|
};
|
|
175
|
-
const Create = ({ onComplete, onError,
|
|
177
|
+
const Create = ({ gameId, onComplete, onError, ...boxProps }) => {
|
|
176
178
|
const { data: result, isFetching } = useAndroidServiceAccountTestResult({ projectId: gameId });
|
|
177
|
-
const { data: builds } = useBuilds({
|
|
179
|
+
const { data: builds } = useBuilds({ pageNumber: 0, projectId: gameId });
|
|
178
180
|
const previousIsFound = useRef(false);
|
|
179
181
|
useEffect(() => {
|
|
180
182
|
const isFound = getIsAppFound(result);
|
|
@@ -183,30 +185,29 @@ const Create = ({ onComplete, onError, gameId, ...boxProps }) => {
|
|
|
183
185
|
}
|
|
184
186
|
previousIsFound.current = isFound;
|
|
185
187
|
}, [result]);
|
|
186
|
-
|
|
188
|
+
useSafeInput(async (input) => {
|
|
187
189
|
if (!gameId) return;
|
|
188
190
|
switch (input) {
|
|
189
|
-
case "r":
|
|
191
|
+
case "r": {
|
|
190
192
|
queryClient.invalidateQueries({
|
|
191
193
|
queryKey: cacheKeys.androidKeyTestResult({ projectId: gameId })
|
|
192
194
|
});
|
|
193
195
|
break;
|
|
194
|
-
|
|
196
|
+
}
|
|
197
|
+
case "d": {
|
|
195
198
|
const dashUrl = await getShortAuthRequiredUrl(`/games/${getShortUUID(gameId)}/builds`);
|
|
196
199
|
await open(dashUrl);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
197
202
|
}
|
|
198
|
-
if (input !== "r") return;
|
|
199
|
-
queryClient.invalidateQueries({
|
|
200
|
-
queryKey: cacheKeys.androidKeyTestResult({ projectId: gameId })
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
const initialBuild = builds?.data.find((build) => {
|
|
204
|
-
return build.platform === Platform.ANDROID && build.buildType === BuildType.AAB;
|
|
205
203
|
});
|
|
204
|
+
const initialBuild = builds?.data.find(
|
|
205
|
+
(build) => build.platform === Platform.ANDROID && build.buildType === BuildType.AAB
|
|
206
|
+
);
|
|
206
207
|
const downloadCmd = initialBuild ? `${getBuildSummary(initialBuild).cmd}` : "Initial AAB build not found!";
|
|
207
208
|
const templateVars = {
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
dashboardURL: new URL(`/games/${getShortUUID(gameId)}/builds`, WEB_URL).toString(),
|
|
210
|
+
downloadCmd
|
|
210
211
|
};
|
|
211
212
|
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, ...boxProps, children: [
|
|
212
213
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
@@ -217,4 +218,4 @@ const Create = ({ onComplete, onError, gameId, ...boxProps }) => {
|
|
|
217
218
|
] }) });
|
|
218
219
|
};
|
|
219
220
|
|
|
220
|
-
export {
|
|
221
|
+
export { CommandContext as C, GameContext as G, Markdown as M, getJobSummary as a, CommandProvider as b, GameProvider as c, getBuildSummary as d, useSafeInput as e, useJob as f, getRenderedMarkdown as g, CreateGooglePlayGame as h, queryBuilds as q, useBuilds as u };
|