shipthis 0.1.25 → 0.1.26
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-mPUG2R4N.js +76 -0
- package/dist/Command-B3AmRt2w.js +28 -0
- package/dist/CommandGame-BCMzP9pc.js +9 -0
- package/dist/Create-CsJxpzUs.js +59 -0
- package/dist/Import-v0M_ygyF.js +110 -0
- package/dist/JobProgress-9uvq8IBn.js +121 -0
- package/dist/JobStatusTable-Bf7J9WXe.js +191 -0
- package/dist/NextSteps-CK9zHOCt.js +18 -0
- package/dist/ProgressSpinner-6pw1T8Iw.js +16 -0
- package/dist/ProjectCredentialsTable-CTkP1mvy.js +37 -0
- package/dist/RunWithSpinner-BVXNWGD3.js +27 -0
- package/dist/StatusTable-Dm5St4g-.js +33 -0
- package/dist/Table-CvM6pccN.js +101 -0
- package/dist/Title-BCQtayg6.js +6 -0
- package/dist/UserCredentialsTable-DhtM_iTG.js +82 -0
- package/dist/baseAppleCommand-IGl6KTvv.js +10 -0
- package/dist/baseGameAndroidCommand-DFn4zMvq.js +43 -0
- package/dist/commands/apple/apiKey/create.js +103 -0
- package/dist/commands/apple/apiKey/export.js +81 -0
- package/dist/commands/apple/apiKey/import.js +85 -0
- package/dist/commands/apple/apiKey/status.js +122 -0
- package/dist/commands/apple/certificate/create.js +133 -0
- package/dist/commands/apple/certificate/export.js +81 -0
- package/dist/commands/apple/certificate/import.js +85 -0
- package/dist/commands/apple/certificate/status.js +130 -0
- package/dist/commands/apple/login.js +76 -0
- package/dist/commands/apple/status.js +79 -0
- package/dist/commands/dashboard.js +38 -0
- package/dist/commands/game/android/apiKey/connect.js +74 -0
- package/dist/commands/game/android/apiKey/create.js +74 -0
- package/dist/commands/game/android/apiKey/export.js +84 -0
- package/dist/commands/game/android/apiKey/import.js +93 -0
- package/dist/commands/game/android/apiKey/invite.js +81 -0
- package/dist/commands/game/android/apiKey/status.js +87 -0
- package/dist/commands/game/android/keyStore/create.js +69 -0
- package/dist/commands/game/android/keyStore/export.js +83 -0
- package/dist/commands/game/android/keyStore/import.js +112 -0
- package/dist/commands/game/android/keyStore/status.js +70 -0
- package/dist/commands/game/android/status.js +84 -0
- package/dist/commands/game/build/download.js +80 -0
- package/dist/commands/game/build/list.js +94 -0
- package/dist/commands/game/create.js +67 -0
- package/dist/commands/game/details.js +113 -0
- package/dist/commands/game/export.js +58 -0
- package/dist/commands/game/ios/app/addTester.js +124 -0
- package/dist/commands/game/ios/app/create.js +117 -0
- package/dist/commands/game/ios/app/status.js +66 -0
- package/dist/commands/game/ios/app/sync.js +95 -0
- package/dist/commands/game/ios/profile/create.js +129 -0
- package/dist/commands/game/ios/profile/export.js +83 -0
- package/dist/commands/game/ios/profile/import.js +92 -0
- package/dist/commands/game/ios/profile/status.js +139 -0
- package/dist/commands/game/ios/status.js +92 -0
- package/dist/commands/game/ios/wizard.js +153 -0
- package/dist/commands/game/job/list.js +91 -0
- package/dist/commands/game/job/status.js +91 -0
- package/dist/commands/game/list.js +83 -0
- package/dist/commands/game/ship.js +216 -0
- package/dist/commands/game/status.js +114 -0
- package/dist/commands/game/wizard.js +686 -0
- package/dist/commands/internal/fastlane.js +74 -0
- package/dist/commands/internal/readme.js +937 -0
- package/dist/commands/login.js +92 -0
- package/dist/commands/status.js +76 -0
- package/dist/export-CVs_xoDN.js +36 -0
- package/dist/git-DREGq-jc.js +32 -0
- package/dist/import-Ch5O7xfN.js +47 -0
- package/dist/index-BB00V5oF.js +136 -0
- package/dist/index-BD1WLuFJ.js +125 -0
- package/dist/index-CIa2EDQ6.js +24 -0
- package/dist/index-CboPN9aq.js +138 -0
- package/dist/index-DkNQs11R.js +711 -0
- package/dist/index-nnzhQ3nY.js +209 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/upload-CRE2nVdd.js +60 -0
- package/dist/useAndroidServiceAccountTestResult-DcYDam-p.js +52 -0
- package/dist/useAppleApp-B16WbUxJ.js +32 -0
- package/dist/useAppleBundleId-DobPATan.js +64 -0
- package/dist/useJobWatching--BvVn7xS.js +45 -0
- package/dist/useProjectCredentials-Btnr7WK3.js +54 -0
- package/dist/useWebSocket-ByuNoqRw.js +36 -0
- package/dist/utils/help.js +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { Flags } from '@oclif/core';
|
|
3
|
+
import { W as WEB_URL, Y as BaseCommand, q as API_URL, _ as setAuthToken, $ as acceptTerms } from '../index-DkNQs11R.js';
|
|
4
|
+
import { a as getInput } from '../index-BB00V5oF.js';
|
|
5
|
+
import 'path';
|
|
6
|
+
import 'fs';
|
|
7
|
+
import '@expo/apple-utils/build/index.js';
|
|
8
|
+
import 'crypto-js';
|
|
9
|
+
import 'uuid';
|
|
10
|
+
import 'luxon';
|
|
11
|
+
import 'crypto';
|
|
12
|
+
import 'readline-sync';
|
|
13
|
+
import 'node:readline';
|
|
14
|
+
import 'node:path';
|
|
15
|
+
import 'node:url';
|
|
16
|
+
import 'isomorphic-git';
|
|
17
|
+
import 'ini';
|
|
18
|
+
import 'deepmerge';
|
|
19
|
+
import 'react';
|
|
20
|
+
import '@tanstack/react-query';
|
|
21
|
+
import 'fast-glob';
|
|
22
|
+
import 'yazl';
|
|
23
|
+
import 'socket.io-client';
|
|
24
|
+
|
|
25
|
+
const TERMS_URL = new URL("/terms", WEB_URL).href;
|
|
26
|
+
const PRIVACY_URL = new URL("/privacy", WEB_URL).href;
|
|
27
|
+
class Login extends BaseCommand {
|
|
28
|
+
static args = {};
|
|
29
|
+
static description = "Authenticate - will create a new account if one does not exist.";
|
|
30
|
+
static examples = [
|
|
31
|
+
"<%= config.bin %> <%= command.id %>",
|
|
32
|
+
"<%= config.bin %> <%= command.id %> --force --email me@email.nowhere"
|
|
33
|
+
];
|
|
34
|
+
static flags = {
|
|
35
|
+
force: Flags.boolean({ char: "f" }),
|
|
36
|
+
email: Flags.string({
|
|
37
|
+
char: "e",
|
|
38
|
+
description: "Your email address"
|
|
39
|
+
})
|
|
40
|
+
};
|
|
41
|
+
async run() {
|
|
42
|
+
const { flags } = this;
|
|
43
|
+
const authConfig = await this.getAuthConfig();
|
|
44
|
+
if (authConfig.shipThisUser && !flags.force) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`You are already logged in as ${authConfig.shipThisUser.email} use --force to login as a different user or remove the auth file`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const getEmail = async () => {
|
|
50
|
+
if (flags.email) return flags.email;
|
|
51
|
+
const email2 = await getInput("Please enter your email address: ");
|
|
52
|
+
if (!email2) throw new Error("Email address is required");
|
|
53
|
+
return email2;
|
|
54
|
+
};
|
|
55
|
+
const email = await getEmail();
|
|
56
|
+
await axios.post(`${API_URL}/auth/email/send`, { email });
|
|
57
|
+
this.log("Please check your email for an email with an OTP.");
|
|
58
|
+
const getOTP = async () => {
|
|
59
|
+
const otp2 = await getInput("Please enter the OTP: ");
|
|
60
|
+
if (!otp2) throw new Error("OTP is required");
|
|
61
|
+
return otp2;
|
|
62
|
+
};
|
|
63
|
+
const otp = await getOTP();
|
|
64
|
+
const source = `shipthis-cli-${this.config.version}`;
|
|
65
|
+
const { data: shipThisUser } = await axios.post(`${API_URL}/auth/email/verify`, { email, otp, source });
|
|
66
|
+
const getAcceptedTermsResponse = async () => {
|
|
67
|
+
console.log(
|
|
68
|
+
`Please review the following documents:
|
|
69
|
+
|
|
70
|
+
${[
|
|
71
|
+
`- Privacy Policy: ${PRIVACY_URL}`,
|
|
72
|
+
`- Terms and Conditions: ${TERMS_URL}`
|
|
73
|
+
].join("\n")}
|
|
74
|
+
`
|
|
75
|
+
);
|
|
76
|
+
const accepted = await getInput("Do you accept the terms of these documents? (yes/no): ");
|
|
77
|
+
const answer = accepted.toLowerCase().trim().substring(0, 1);
|
|
78
|
+
return answer === "y";
|
|
79
|
+
};
|
|
80
|
+
await this.setAuthConfig({ shipThisUser });
|
|
81
|
+
setAuthToken(shipThisUser.jwt);
|
|
82
|
+
this.log("You are now logged in as", shipThisUser.email);
|
|
83
|
+
if (!shipThisUser.details?.hasAcceptedTerms) {
|
|
84
|
+
const didAccept = await getAcceptedTermsResponse();
|
|
85
|
+
if (!didAccept) throw new Error("You must accept the terms to continue");
|
|
86
|
+
await acceptTerms();
|
|
87
|
+
}
|
|
88
|
+
await this.config.runCommand("status");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { Login as default };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { render } from 'ink';
|
|
3
|
+
import { Y as BaseCommand, j as isCWDGodotGame } from '../index-DkNQs11R.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import '../index-nnzhQ3nY.js';
|
|
6
|
+
import 'ink-spinner';
|
|
7
|
+
import 'axios';
|
|
8
|
+
import 'crypto-js';
|
|
9
|
+
import 'uuid';
|
|
10
|
+
import 'fs';
|
|
11
|
+
import 'luxon';
|
|
12
|
+
import '@inkjs/ui';
|
|
13
|
+
import '@tanstack/react-query';
|
|
14
|
+
import 'yazl';
|
|
15
|
+
import 'crypto';
|
|
16
|
+
import 'readline-sync';
|
|
17
|
+
import 'node:readline';
|
|
18
|
+
import 'node:path';
|
|
19
|
+
import 'node:url';
|
|
20
|
+
import { i as isCWDGitRepo } from '../git-DREGq-jc.js';
|
|
21
|
+
import '@oclif/core';
|
|
22
|
+
import 'fast-glob';
|
|
23
|
+
import 'socket.io-client';
|
|
24
|
+
import 'open';
|
|
25
|
+
import 'marked';
|
|
26
|
+
import 'marked-terminal';
|
|
27
|
+
import 'path';
|
|
28
|
+
import { N as NextSteps } from '../NextSteps-CK9zHOCt.js';
|
|
29
|
+
import 'qrcode';
|
|
30
|
+
import { S as StatusTable } from '../StatusTable-Dm5St4g-.js';
|
|
31
|
+
import 'string-length';
|
|
32
|
+
import 'strip-ansi';
|
|
33
|
+
import { C as Command } from '../Command-B3AmRt2w.js';
|
|
34
|
+
import '@expo/apple-utils/build/index.js';
|
|
35
|
+
import 'isomorphic-git';
|
|
36
|
+
import 'ini';
|
|
37
|
+
import 'deepmerge';
|
|
38
|
+
import '../index-BB00V5oF.js';
|
|
39
|
+
import '../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
40
|
+
import '../Title-BCQtayg6.js';
|
|
41
|
+
|
|
42
|
+
class Status extends BaseCommand {
|
|
43
|
+
static args = {};
|
|
44
|
+
static description = "Displays the current overall status.";
|
|
45
|
+
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
46
|
+
static flags = {};
|
|
47
|
+
async run() {
|
|
48
|
+
const authConfig = await this.getAuthConfig();
|
|
49
|
+
const isLoggedIn = !!authConfig.shipThisUser;
|
|
50
|
+
const isGodotGame = isCWDGodotGame();
|
|
51
|
+
const isShipThisConfigured = await this.hasProjectConfig();
|
|
52
|
+
const isGitRepo = await isCWDGitRepo();
|
|
53
|
+
let steps = [];
|
|
54
|
+
if (!isLoggedIn) steps.push("$ shipthis login --email my.email@address.nowhere");
|
|
55
|
+
if (!isGodotGame) steps.push("Run this command in a Godot project directory");
|
|
56
|
+
if (!isShipThisConfigured) steps.push("$ shipthis game wizard");
|
|
57
|
+
if (steps.length === 0) steps = ["$ shipthis game status"];
|
|
58
|
+
const statusProps = {
|
|
59
|
+
title: "Status",
|
|
60
|
+
statuses: {
|
|
61
|
+
"Logged in": isLoggedIn,
|
|
62
|
+
"Godot project detected": isGodotGame,
|
|
63
|
+
"ShipThis project configured": isShipThisConfigured,
|
|
64
|
+
"Git repository detected (not required)": isGitRepo
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
render(
|
|
68
|
+
/* @__PURE__ */ jsxs(Command, { command: this, children: [
|
|
69
|
+
/* @__PURE__ */ jsx(StatusTable, { ...statusProps }),
|
|
70
|
+
/* @__PURE__ */ jsx(NextSteps, { steps })
|
|
71
|
+
] })
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { Status as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { p as getAuthedHeaders, q as API_URL } from './index-DkNQs11R.js';
|
|
4
|
+
|
|
5
|
+
async function exportCredential({ zipPath, credentialId, projectId }) {
|
|
6
|
+
const headers = getAuthedHeaders();
|
|
7
|
+
const url = projectId ? `${API_URL}/projects/${projectId}/credentials/${credentialId}/export` : `${API_URL}/credentials/${credentialId}/export`;
|
|
8
|
+
const { data } = await axios.post(
|
|
9
|
+
url,
|
|
10
|
+
{},
|
|
11
|
+
// no-body
|
|
12
|
+
{ headers }
|
|
13
|
+
);
|
|
14
|
+
const downloadUrl = data.url;
|
|
15
|
+
return await downloadFile(downloadUrl, zipPath);
|
|
16
|
+
}
|
|
17
|
+
async function downloadFile(url, destination) {
|
|
18
|
+
const response = await axios({
|
|
19
|
+
url,
|
|
20
|
+
method: "GET",
|
|
21
|
+
responseType: "stream"
|
|
22
|
+
});
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const file = fs.createWriteStream(destination);
|
|
25
|
+
response.data.pipe(file);
|
|
26
|
+
file.on("finish", () => {
|
|
27
|
+
file.close();
|
|
28
|
+
resolve();
|
|
29
|
+
});
|
|
30
|
+
file.on("error", (err) => {
|
|
31
|
+
fs.unlink(destination, () => reject(err));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { exportCredential as e };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import git from 'isomorphic-git';
|
|
2
|
+
import { promises } from 'fs';
|
|
3
|
+
|
|
4
|
+
async function isCWDGitRepo() {
|
|
5
|
+
const dir = process.cwd();
|
|
6
|
+
try {
|
|
7
|
+
await git.log({ fs: promises, dir, depth: 1 });
|
|
8
|
+
return true;
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function getCWDGitInfo() {
|
|
14
|
+
const dir = process.cwd();
|
|
15
|
+
const empty = {};
|
|
16
|
+
try {
|
|
17
|
+
const commits = await git.log({ fs: promises, dir, depth: 1 });
|
|
18
|
+
const branch = await git.currentBranch({
|
|
19
|
+
fs: promises,
|
|
20
|
+
dir,
|
|
21
|
+
fullname: false
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
gitCommitHash: commits[0].oid,
|
|
25
|
+
gitBranch: branch
|
|
26
|
+
};
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return empty;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { getCWDGitInfo as g, isCWDGitRepo as i };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { promises } from 'fs';
|
|
3
|
+
import { p as getAuthedHeaders, q as API_URL } from './index-DkNQs11R.js';
|
|
4
|
+
|
|
5
|
+
async function getNewImportTicket(projectId) {
|
|
6
|
+
const url = projectId ? `${API_URL}/projects/${projectId}/credentials/import/url` : `${API_URL}/credentials/import/url`;
|
|
7
|
+
const headers = getAuthedHeaders();
|
|
8
|
+
const { data: importInfo } = await axios({
|
|
9
|
+
method: "post",
|
|
10
|
+
url,
|
|
11
|
+
headers
|
|
12
|
+
});
|
|
13
|
+
return importInfo;
|
|
14
|
+
}
|
|
15
|
+
async function importCredential({
|
|
16
|
+
projectId,
|
|
17
|
+
zipPath,
|
|
18
|
+
type,
|
|
19
|
+
platform
|
|
20
|
+
}) {
|
|
21
|
+
const importTicket = await getNewImportTicket(projectId);
|
|
22
|
+
const zipBuffer = await promises.readFile(zipPath);
|
|
23
|
+
await axios.put(importTicket.url, zipBuffer, {
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-length": zipBuffer.length,
|
|
26
|
+
"Content-Type": "application/zip"
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const headers = getAuthedHeaders();
|
|
30
|
+
const url = projectId ? `${API_URL}/projects/${projectId}/credentials/import` : `${API_URL}/credentials/import`;
|
|
31
|
+
const { data: publicCredential } = await axios({
|
|
32
|
+
method: "post",
|
|
33
|
+
url,
|
|
34
|
+
headers,
|
|
35
|
+
data: {
|
|
36
|
+
uuid: importTicket.uuid,
|
|
37
|
+
type,
|
|
38
|
+
platform
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
if (projectId) {
|
|
42
|
+
return publicCredential;
|
|
43
|
+
}
|
|
44
|
+
return publicCredential;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { importCredential as i };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs__default from 'fs';
|
|
3
|
+
import readlineSync from 'readline-sync';
|
|
4
|
+
import { promises } from 'node:readline';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { N as JobStage, P as Platform, O as LogLevel, J as JobStatus } from './index-DkNQs11R.js';
|
|
8
|
+
import 'luxon';
|
|
9
|
+
import 'axios';
|
|
10
|
+
import 'isomorphic-git';
|
|
11
|
+
import '@oclif/core';
|
|
12
|
+
import 'react';
|
|
13
|
+
import '@tanstack/react-query';
|
|
14
|
+
import 'crypto-js';
|
|
15
|
+
import 'uuid';
|
|
16
|
+
import 'fast-glob';
|
|
17
|
+
import 'yazl';
|
|
18
|
+
import 'socket.io-client';
|
|
19
|
+
|
|
20
|
+
function getShortUUID(originalUuid) {
|
|
21
|
+
return originalUuid.slice(0, 8);
|
|
22
|
+
}
|
|
23
|
+
function getStageColor(stage) {
|
|
24
|
+
switch (stage) {
|
|
25
|
+
case JobStage.SETUP:
|
|
26
|
+
return "#FFB3B3";
|
|
27
|
+
// pastel red
|
|
28
|
+
case JobStage.CONFIGURE:
|
|
29
|
+
return "#FFD9B3";
|
|
30
|
+
// pastel orange
|
|
31
|
+
case JobStage.EXPORT:
|
|
32
|
+
return "#FFFACD";
|
|
33
|
+
// pastel yellow
|
|
34
|
+
case JobStage.BUILD:
|
|
35
|
+
return "#B3FFB3";
|
|
36
|
+
// pastel green
|
|
37
|
+
case JobStage.PUBLISH:
|
|
38
|
+
return "#B3D9FF";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getMessageColor(level) {
|
|
42
|
+
switch (level) {
|
|
43
|
+
case LogLevel.INFO:
|
|
44
|
+
return "white";
|
|
45
|
+
case LogLevel.WARN:
|
|
46
|
+
return "yellow";
|
|
47
|
+
case LogLevel.ERROR:
|
|
48
|
+
return "red";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getJobStatusColor(status) {
|
|
52
|
+
switch (status) {
|
|
53
|
+
case JobStatus.PENDING:
|
|
54
|
+
return "yellow";
|
|
55
|
+
case JobStatus.PROCESSING:
|
|
56
|
+
return "blue";
|
|
57
|
+
case JobStatus.COMPLETED:
|
|
58
|
+
return "green";
|
|
59
|
+
case JobStatus.FAILED:
|
|
60
|
+
return "red";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function getFileHash(filename) {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const hash = crypto.createHash("sha256");
|
|
66
|
+
const rs = fs__default.createReadStream(filename);
|
|
67
|
+
rs.on("error", reject);
|
|
68
|
+
rs.on("data", (chunk) => hash.update(chunk));
|
|
69
|
+
rs.on("end", () => resolve(hash.digest("hex")));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function isValidSemVer(versionString) {
|
|
73
|
+
const [semVer, major, minor, patch, prerelease, buildmetadata] = versionString.match(
|
|
74
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
|
75
|
+
) ?? [];
|
|
76
|
+
return !!semVer;
|
|
77
|
+
}
|
|
78
|
+
function makeHumanReadable(rawObject) {
|
|
79
|
+
const getLabel = (key) => {
|
|
80
|
+
const words = key.split(/(?=[A-Z])/);
|
|
81
|
+
return words.map((word) => word[0].toUpperCase() + word.slice(1)).join(" ").replaceAll(" ", " ");
|
|
82
|
+
};
|
|
83
|
+
const withLabels = Object.entries(rawObject).reduce((acc, [key, value]) => {
|
|
84
|
+
acc[getLabel(key)] = value;
|
|
85
|
+
return acc;
|
|
86
|
+
}, {});
|
|
87
|
+
return withLabels;
|
|
88
|
+
}
|
|
89
|
+
function getPlatformName(platform) {
|
|
90
|
+
switch (platform) {
|
|
91
|
+
case Platform.IOS:
|
|
92
|
+
return "iOS";
|
|
93
|
+
case Platform.ANDROID:
|
|
94
|
+
return "Android";
|
|
95
|
+
default:
|
|
96
|
+
throw new Error(`Unknown platform: ${platform}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function getMaskedInput(message) {
|
|
100
|
+
const password = readlineSync.question(message, {
|
|
101
|
+
hideEchoBack: true
|
|
102
|
+
// This will hide the input as the user types
|
|
103
|
+
});
|
|
104
|
+
return password;
|
|
105
|
+
}
|
|
106
|
+
async function getInput(message) {
|
|
107
|
+
const rl = promises.createInterface({
|
|
108
|
+
input: process.stdin,
|
|
109
|
+
output: process.stdout
|
|
110
|
+
});
|
|
111
|
+
const answer = await rl.question(message);
|
|
112
|
+
rl.close();
|
|
113
|
+
return answer;
|
|
114
|
+
}
|
|
115
|
+
function generatePackageName(gameName) {
|
|
116
|
+
let normalizedGameName = gameName.trim().toLowerCase();
|
|
117
|
+
normalizedGameName = normalizedGameName.replace(/[\s\-_]+/g, ".");
|
|
118
|
+
normalizedGameName = normalizedGameName.replace(/[^a-z0-9\.]/g, "");
|
|
119
|
+
normalizedGameName = normalizedGameName.replace(/\.+/g, ".");
|
|
120
|
+
normalizedGameName = normalizedGameName.replace(/^\./, "").replace(/\.$/, "");
|
|
121
|
+
if (/^[0-9]/.test(normalizedGameName)) {
|
|
122
|
+
normalizedGameName = "app." + normalizedGameName;
|
|
123
|
+
}
|
|
124
|
+
const prefix = "com.";
|
|
125
|
+
if (normalizedGameName === "") {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return prefix + normalizedGameName;
|
|
129
|
+
}
|
|
130
|
+
function scriptDir(importMeta) {
|
|
131
|
+
const filename = fileURLToPath(importMeta.url);
|
|
132
|
+
const dirname = path.dirname(filename);
|
|
133
|
+
return dirname;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { getInput as a, generatePackageName as b, getJobStatusColor as c, getMaskedInput as d, getFileHash as e, getPlatformName as f, getShortUUID as g, getStageColor as h, isValidSemVer as i, getMessageColor as j, makeHumanReadable as m, scriptDir as s };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { Text, useInput, Box } from 'ink';
|
|
3
|
+
import open from 'open';
|
|
4
|
+
import { useState, useEffect, useContext } from 'react';
|
|
5
|
+
import { T as getGoogleStatus, a3 as getShortAuthRequiredUrl, a4 as getGoogleAuthUrl, W as WEB_URL } from './index-DkNQs11R.js';
|
|
6
|
+
import 'crypto';
|
|
7
|
+
import 'fs';
|
|
8
|
+
import 'readline-sync';
|
|
9
|
+
import 'node:readline';
|
|
10
|
+
import 'node:path';
|
|
11
|
+
import 'node:url';
|
|
12
|
+
import 'luxon';
|
|
13
|
+
import 'axios';
|
|
14
|
+
import 'isomorphic-git';
|
|
15
|
+
import '@oclif/core';
|
|
16
|
+
import { useQuery } from '@tanstack/react-query';
|
|
17
|
+
import 'crypto-js';
|
|
18
|
+
import 'uuid';
|
|
19
|
+
import 'fast-glob';
|
|
20
|
+
import 'yazl';
|
|
21
|
+
import 'socket.io-client';
|
|
22
|
+
import { u as useWebSocket } from './useWebSocket-ByuNoqRw.js';
|
|
23
|
+
import { c as cacheKeys } from './useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
24
|
+
import { b as GameContext, M as Markdown } from './index-nnzhQ3nY.js';
|
|
25
|
+
import 'ink-spinner';
|
|
26
|
+
import '@inkjs/ui';
|
|
27
|
+
import 'string-length';
|
|
28
|
+
import 'strip-ansi';
|
|
29
|
+
import 'marked';
|
|
30
|
+
import 'marked-terminal';
|
|
31
|
+
import 'path';
|
|
32
|
+
import qrcode from 'qrcode';
|
|
33
|
+
|
|
34
|
+
const useGoogleStatus = () => {
|
|
35
|
+
return useQuery({
|
|
36
|
+
queryKey: cacheKeys.googleStatus(),
|
|
37
|
+
queryFn: getGoogleStatus
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function useGoogleStatusWatching({
|
|
42
|
+
projectId,
|
|
43
|
+
isWatching,
|
|
44
|
+
onGoogleStatusUpdate
|
|
45
|
+
}) {
|
|
46
|
+
const [wsGoogleStatus, setWsGoogleStatus] = useState(null);
|
|
47
|
+
const listener = {
|
|
48
|
+
getPattern: () => `project.${projectId}:google-status`,
|
|
49
|
+
eventHandler: async (pattern, data2) => {
|
|
50
|
+
setWsGoogleStatus(data2);
|
|
51
|
+
if (onGoogleStatusUpdate) onGoogleStatusUpdate(data2);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
useWebSocket([listener] );
|
|
55
|
+
const { isLoading, data: googleStatus } = useGoogleStatus();
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
setWsGoogleStatus(null);
|
|
58
|
+
}, [projectId, isWatching, googleStatus]);
|
|
59
|
+
const fetchedGoogleStatus = googleStatus ? googleStatus : null;
|
|
60
|
+
const data = wsGoogleStatus ? wsGoogleStatus : fetchedGoogleStatus;
|
|
61
|
+
return {
|
|
62
|
+
isLoading,
|
|
63
|
+
data
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const QRCodeTerminal = ({ url }) => {
|
|
68
|
+
const [code, setCode] = useState(null);
|
|
69
|
+
const handleLoad = async () => {
|
|
70
|
+
const codeString = await qrcode.toString(url, { type: "terminal", errorCorrectionLevel: "L", small: true });
|
|
71
|
+
setCode(codeString);
|
|
72
|
+
};
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
handleLoad();
|
|
75
|
+
}, []);
|
|
76
|
+
return /* @__PURE__ */ jsx(Fragment, { children: code && /* @__PURE__ */ jsx(Text, { children: code }) });
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
async function getConnectUrl(gameId, helpPage) {
|
|
80
|
+
const helpPagePath = `/docs/android?gameId=${gameId}#2-connect-shipthis-with-google`;
|
|
81
|
+
const url = helpPage ? await getShortAuthRequiredUrl(helpPagePath) : await getGoogleAuthUrl(gameId);
|
|
82
|
+
return url;
|
|
83
|
+
}
|
|
84
|
+
const GoogleAuthQRCode = ({ gameId, helpPage }) => {
|
|
85
|
+
const [url, setUrl] = useState(null);
|
|
86
|
+
const handleLoad = async () => {
|
|
87
|
+
const url2 = await getConnectUrl(gameId, helpPage);
|
|
88
|
+
setUrl(url2);
|
|
89
|
+
};
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
handleLoad();
|
|
92
|
+
}, []);
|
|
93
|
+
return /* @__PURE__ */ jsx(Fragment, { children: url && /* @__PURE__ */ jsx(QRCodeTerminal, { url }) });
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const ConnectGoogle = (props) => {
|
|
97
|
+
const { gameId } = useContext(GameContext);
|
|
98
|
+
return /* @__PURE__ */ jsx(Fragment, { children: gameId && /* @__PURE__ */ jsx(ConnectForGame, { gameId, ...props }) });
|
|
99
|
+
};
|
|
100
|
+
const ConnectForGame = ({ onComplete, onError, helpPage, gameId, ...boxProps }) => {
|
|
101
|
+
useGoogleStatusWatching({
|
|
102
|
+
projectId: gameId,
|
|
103
|
+
isWatching: true,
|
|
104
|
+
onGoogleStatusUpdate: (status) => {
|
|
105
|
+
if (status.isAuthenticated) return onComplete();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
useInput(async (input) => {
|
|
109
|
+
if (!gameId) return;
|
|
110
|
+
if (input !== "d") return;
|
|
111
|
+
const url = await getConnectUrl(gameId, true);
|
|
112
|
+
await open(url);
|
|
113
|
+
});
|
|
114
|
+
const templateVars = {
|
|
115
|
+
privacyURL: new URL("/privacy", WEB_URL).toString()
|
|
116
|
+
};
|
|
117
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, ...boxProps, children: [
|
|
118
|
+
/* @__PURE__ */ jsx(Markdown, { filename: "privacy-notification.md", templateVars }),
|
|
119
|
+
/* @__PURE__ */ jsx(Text, { children: "Scan the QR code below to connect your Google account to ShipThis:" }),
|
|
120
|
+
gameId && /* @__PURE__ */ jsx(GoogleAuthQRCode, { gameId, helpPage: !!helpPage }),
|
|
121
|
+
/* @__PURE__ */ jsx(Text, { children: "Or press D to sign-in using your browser" })
|
|
122
|
+
] });
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export { ConnectGoogle as C };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { p as getAuthedHeaders, q as API_URL, L as castArrayObjectDates } from './index-DkNQs11R.js';
|
|
3
|
+
import 'fs';
|
|
4
|
+
|
|
5
|
+
async function getUserCredentials(pageSize = 100) {
|
|
6
|
+
const headers = getAuthedHeaders();
|
|
7
|
+
const { data } = await axios({
|
|
8
|
+
method: "get",
|
|
9
|
+
url: `${API_URL}/credentials?pageSize=${pageSize}`,
|
|
10
|
+
headers
|
|
11
|
+
});
|
|
12
|
+
return castArrayObjectDates(data.data);
|
|
13
|
+
}
|
|
14
|
+
async function getProjectCredentials(projectId, pageSize = 100) {
|
|
15
|
+
const headers = getAuthedHeaders();
|
|
16
|
+
const { data } = await axios({
|
|
17
|
+
method: "get",
|
|
18
|
+
url: `${API_URL}/projects/${projectId}/credentials?pageSize=${pageSize}`,
|
|
19
|
+
headers
|
|
20
|
+
});
|
|
21
|
+
return castArrayObjectDates(data.data);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { getProjectCredentials as a, getUserCredentials as g };
|