shipthis 0.1.25 → 0.1.27
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 +96 -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 +95 -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,122 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Flags } from '@oclif/core';
|
|
3
|
+
import { Box, Text, render } from 'ink';
|
|
4
|
+
import { b as getShortDate, A as ApiKey, C as CredentialsType, P as Platform, B as BaseAuthenticatedCommand } from '../../../index-DkNQs11R.js';
|
|
5
|
+
import 'react';
|
|
6
|
+
import '../../../index-nnzhQ3nY.js';
|
|
7
|
+
import Spinner from 'ink-spinner';
|
|
8
|
+
import 'axios';
|
|
9
|
+
import 'crypto-js';
|
|
10
|
+
import 'uuid';
|
|
11
|
+
import 'fs';
|
|
12
|
+
import { DateTime } from 'luxon';
|
|
13
|
+
import '@inkjs/ui';
|
|
14
|
+
import { useQuery } from '@tanstack/react-query';
|
|
15
|
+
import 'yazl';
|
|
16
|
+
import 'crypto';
|
|
17
|
+
import 'readline-sync';
|
|
18
|
+
import 'node:readline';
|
|
19
|
+
import 'node:path';
|
|
20
|
+
import 'node:url';
|
|
21
|
+
import 'isomorphic-git';
|
|
22
|
+
import 'fast-glob';
|
|
23
|
+
import 'socket.io-client';
|
|
24
|
+
import 'open';
|
|
25
|
+
import 'marked';
|
|
26
|
+
import 'marked-terminal';
|
|
27
|
+
import 'path';
|
|
28
|
+
import 'qrcode';
|
|
29
|
+
import 'string-length';
|
|
30
|
+
import 'strip-ansi';
|
|
31
|
+
import { u as useUserCredentials, U as UserCredentialsTable } from '../../../UserCredentialsTable-DhtM_iTG.js';
|
|
32
|
+
import { T as Table } from '../../../Table-CvM6pccN.js';
|
|
33
|
+
import { T as Title } from '../../../Title-BCQtayg6.js';
|
|
34
|
+
import { N as NextSteps } from '../../../NextSteps-CK9zHOCt.js';
|
|
35
|
+
import { C as Command } from '../../../Command-B3AmRt2w.js';
|
|
36
|
+
import '@expo/apple-utils/build/index.js';
|
|
37
|
+
import 'ini';
|
|
38
|
+
import 'deepmerge';
|
|
39
|
+
import '../../../index-BB00V5oF.js';
|
|
40
|
+
import '../../../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
41
|
+
|
|
42
|
+
async function queryAppleApiKeys({ ctx }) {
|
|
43
|
+
const keys = await ApiKey.getAsync(ctx);
|
|
44
|
+
const activeKeys = keys.filter((key) => key.attributes.isActive);
|
|
45
|
+
return activeKeys;
|
|
46
|
+
}
|
|
47
|
+
const canAppleApiKeyBeUsed = (key, userCredentials) => {
|
|
48
|
+
if (!key.attributes.isActive) return false;
|
|
49
|
+
return userCredentials.some((cred) => cred.isActive && cred.serialNumber == key.id);
|
|
50
|
+
};
|
|
51
|
+
function getAppleApiKeySummary(key, userCredentials) {
|
|
52
|
+
return {
|
|
53
|
+
keyID: key.id,
|
|
54
|
+
name: key.attributes.nickname,
|
|
55
|
+
roles: key.attributes.roles?.join(", "),
|
|
56
|
+
lastUsed: getShortDate(DateTime.fromISO(key.attributes.lastUsed)),
|
|
57
|
+
canBeUsed: canAppleApiKeyBeUsed(key, userCredentials)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const useAppleApiKeys = (props) => {
|
|
61
|
+
const queryResult = useQuery({
|
|
62
|
+
queryKey: ["appleApiKeys"],
|
|
63
|
+
queryFn: () => queryAppleApiKeys(props)
|
|
64
|
+
});
|
|
65
|
+
return queryResult;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const AppleApiKeysTable = ({ ctx, ...boxProps }) => {
|
|
69
|
+
const { data: userCredentialsResponse } = useUserCredentials({ platform: Platform.IOS, type: CredentialsType.KEY });
|
|
70
|
+
const { data: keys, isLoading } = useAppleApiKeys({ ctx });
|
|
71
|
+
const hasUsable = keys && userCredentialsResponse && keys.some((key) => canAppleApiKeyBeUsed(key, userCredentialsResponse.data));
|
|
72
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
73
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, ...boxProps, children: [
|
|
74
|
+
/* @__PURE__ */ jsx(Title, { children: "App Store Connect API Keys in your Apple account" }),
|
|
75
|
+
isLoading && /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
|
|
76
|
+
keys && userCredentialsResponse && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 2, marginBottom: 1, flexDirection: "column", children: [
|
|
78
|
+
/* @__PURE__ */ jsx(Text, { children: `You have ${keys.length} App Store Connect API Keys in your Apple account` }),
|
|
79
|
+
/* @__PURE__ */ jsx(Text, { children: `${hasUsable ? "One" : "None"} of these can be used by ShipThis` })
|
|
80
|
+
] }),
|
|
81
|
+
keys.length > 0 && /* @__PURE__ */ jsx(Table, { data: keys.map((key) => getAppleApiKeySummary(key, userCredentialsResponse.data)) }),
|
|
82
|
+
!hasUsable && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, children: "You do not have a usable App Store Connect API Key. To ship an iOS game, you will need a usable App Store Connect API Key." }) })
|
|
83
|
+
] })
|
|
84
|
+
] }),
|
|
85
|
+
keys && !hasUsable && /* @__PURE__ */ jsx(NextSteps, { steps: ["shipthis apple apiKey create"] })
|
|
86
|
+
] });
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
class AppleApiKeyStatus extends BaseAuthenticatedCommand {
|
|
90
|
+
static args = {};
|
|
91
|
+
static description = "Displays the status of App Store Connect API Keys in your Apple and ShipThis accounts.\nThis API key is used to automatically publish your games to the App Store.";
|
|
92
|
+
static examples = [
|
|
93
|
+
"<%= config.bin %> <%= command.id %>",
|
|
94
|
+
"<%= config.bin %> <%= command.id %> --noAppleAuth"
|
|
95
|
+
];
|
|
96
|
+
static flags = {
|
|
97
|
+
noAppleAuth: Flags.boolean({ char: "f" })
|
|
98
|
+
};
|
|
99
|
+
async run() {
|
|
100
|
+
const { flags } = this;
|
|
101
|
+
const showApple = !flags.noAppleAuth;
|
|
102
|
+
let ctx = null;
|
|
103
|
+
if (showApple) {
|
|
104
|
+
const authState = await this.refreshAppleAuthState();
|
|
105
|
+
ctx = authState.context;
|
|
106
|
+
}
|
|
107
|
+
render(
|
|
108
|
+
/* @__PURE__ */ jsxs(Command, { command: this, children: [
|
|
109
|
+
/* @__PURE__ */ jsx(
|
|
110
|
+
UserCredentialsTable,
|
|
111
|
+
{
|
|
112
|
+
credentialTypeName: "App Store Connect API Key",
|
|
113
|
+
queryProps: { type: CredentialsType.KEY, platform: Platform.IOS }
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
showApple && /* @__PURE__ */ jsx(AppleApiKeysTable, { ctx })
|
|
117
|
+
] })
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { AppleApiKeyStatus as default };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Flags } from '@oclif/core';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import { m as CertificateType, l as Certificate, P as Platform, C as CredentialsType } from '../../../index-DkNQs11R.js';
|
|
5
|
+
import { g as getUserCredentials } from '../../../index-CIa2EDQ6.js';
|
|
6
|
+
import 'react';
|
|
7
|
+
import '../../../index-nnzhQ3nY.js';
|
|
8
|
+
import 'ink-spinner';
|
|
9
|
+
import 'axios';
|
|
10
|
+
import 'crypto-js';
|
|
11
|
+
import 'uuid';
|
|
12
|
+
import 'fs';
|
|
13
|
+
import 'luxon';
|
|
14
|
+
import '@inkjs/ui';
|
|
15
|
+
import '@tanstack/react-query';
|
|
16
|
+
import 'yazl';
|
|
17
|
+
import 'crypto';
|
|
18
|
+
import 'readline-sync';
|
|
19
|
+
import 'node:readline';
|
|
20
|
+
import 'node:path';
|
|
21
|
+
import 'node:url';
|
|
22
|
+
import 'isomorphic-git';
|
|
23
|
+
import 'fast-glob';
|
|
24
|
+
import 'socket.io-client';
|
|
25
|
+
import 'open';
|
|
26
|
+
import 'marked';
|
|
27
|
+
import 'marked-terminal';
|
|
28
|
+
import 'path';
|
|
29
|
+
import 'qrcode';
|
|
30
|
+
import { R as RunWithSpinner } from '../../../RunWithSpinner-BVXNWGD3.js';
|
|
31
|
+
import 'string-length';
|
|
32
|
+
import 'strip-ansi';
|
|
33
|
+
import { C as Command } from '../../../Command-B3AmRt2w.js';
|
|
34
|
+
import forge from 'node-forge';
|
|
35
|
+
import { B as BaseAppleCommand } from '../../../baseAppleCommand-IGl6KTvv.js';
|
|
36
|
+
import { u as uploadUserCredentials } from '../../../upload-CRE2nVdd.js';
|
|
37
|
+
import '@expo/apple-utils/build/index.js';
|
|
38
|
+
import 'ini';
|
|
39
|
+
import 'deepmerge';
|
|
40
|
+
import '../../../index-BB00V5oF.js';
|
|
41
|
+
import '../../../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
42
|
+
|
|
43
|
+
function decodeCertificate(certificateContent) {
|
|
44
|
+
const decodedContent = forge.util.decode64(certificateContent);
|
|
45
|
+
const asn1 = forge.asn1.fromDer(decodedContent);
|
|
46
|
+
return forge.pki.certificateFromAsn1(asn1);
|
|
47
|
+
}
|
|
48
|
+
function encodePkcs12(pkcs12Asn1) {
|
|
49
|
+
const derBytes = forge.asn1.toDer(pkcs12Asn1).getBytes();
|
|
50
|
+
return forge.util.encode64(derBytes);
|
|
51
|
+
}
|
|
52
|
+
async function createCertificate(ctx, certificateType = CertificateType.IOS_DISTRIBUTION) {
|
|
53
|
+
const {
|
|
54
|
+
pem: csrPem,
|
|
55
|
+
keyPair: { privateKey }
|
|
56
|
+
} = await Certificate.createCertificateSigningRequestAsync();
|
|
57
|
+
const certificate = await Certificate.createAsync(ctx, {
|
|
58
|
+
csrContent: csrPem,
|
|
59
|
+
certificateType
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
certificate,
|
|
63
|
+
privateKey,
|
|
64
|
+
privateKeyPem: forge.pki.privateKeyToPem(privateKey)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function exportCertificate(certificate, privateKey) {
|
|
68
|
+
const decodedCertificate = decodeCertificate(certificate.attributes.certificateContent);
|
|
69
|
+
const password = forge.util.encode64(forge.random.getBytesSync(16));
|
|
70
|
+
const pkcs12Asn1 = forge.pkcs12.toPkcs12Asn1(privateKey, [decodedCertificate], password, {
|
|
71
|
+
friendlyName: "key",
|
|
72
|
+
algorithm: "3des"
|
|
73
|
+
});
|
|
74
|
+
const encodedPkcs12 = encodePkcs12(pkcs12Asn1);
|
|
75
|
+
return {
|
|
76
|
+
certificateBase64: encodedPkcs12,
|
|
77
|
+
certificatePassword: password
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class AppleCertificateCreate extends BaseAppleCommand {
|
|
82
|
+
static args = {};
|
|
83
|
+
static description = "Creates an iOS Distribution Certificate in your Apple Developer account.\nSaves the certificate with the private key to your ShipThis account";
|
|
84
|
+
static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> --force"];
|
|
85
|
+
static flags = {
|
|
86
|
+
force: Flags.boolean({ char: "f" }),
|
|
87
|
+
quiet: Flags.boolean({ char: "q", description: "Avoid output except for interactions and errors" })
|
|
88
|
+
};
|
|
89
|
+
async run() {
|
|
90
|
+
const { flags } = this;
|
|
91
|
+
const { force } = flags;
|
|
92
|
+
const userCredentials = await getUserCredentials();
|
|
93
|
+
const userAppleDistCredentials = userCredentials.filter(
|
|
94
|
+
(cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.CERTIFICATE
|
|
95
|
+
);
|
|
96
|
+
if (userAppleDistCredentials.length !== 0 && !force) {
|
|
97
|
+
this.error("An Apple Distribution Certificate already exists. Use --force to overwrite it.");
|
|
98
|
+
}
|
|
99
|
+
const authState = await this.refreshAppleAuthState();
|
|
100
|
+
const ctx = authState.context;
|
|
101
|
+
const createCert = async () => {
|
|
102
|
+
const { certificate, privateKey } = await createCertificate(ctx);
|
|
103
|
+
const exported = exportCertificate(certificate, privateKey);
|
|
104
|
+
const serialNumber = certificate.attributes.serialNumber;
|
|
105
|
+
await uploadUserCredentials({
|
|
106
|
+
platform: Platform.IOS,
|
|
107
|
+
type: CredentialsType.CERTIFICATE,
|
|
108
|
+
contents: {
|
|
109
|
+
serialNumber,
|
|
110
|
+
...exported
|
|
111
|
+
},
|
|
112
|
+
serialNumber
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
const handleComplete = async () => {
|
|
116
|
+
await this.config.runCommand(`apple:certificate:status`);
|
|
117
|
+
};
|
|
118
|
+
if (this.flags.quiet) return await createCert();
|
|
119
|
+
render(
|
|
120
|
+
/* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
|
|
121
|
+
RunWithSpinner,
|
|
122
|
+
{
|
|
123
|
+
msgInProgress: `Creating certificate in the Apple Developer Portal...`,
|
|
124
|
+
msgComplete: `Certificate created and saved to ShipThis`,
|
|
125
|
+
executeMethod: createCert,
|
|
126
|
+
onComplete: handleComplete
|
|
127
|
+
}
|
|
128
|
+
) })
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { AppleCertificateCreate as default };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { B as BaseAuthenticatedCommand, P as Platform, C as CredentialsType } from '../../../index-DkNQs11R.js';
|
|
6
|
+
import { g as getUserCredentials } from '../../../index-CIa2EDQ6.js';
|
|
7
|
+
import 'react';
|
|
8
|
+
import '../../../index-nnzhQ3nY.js';
|
|
9
|
+
import 'ink-spinner';
|
|
10
|
+
import 'axios';
|
|
11
|
+
import 'crypto-js';
|
|
12
|
+
import 'uuid';
|
|
13
|
+
import 'luxon';
|
|
14
|
+
import '@inkjs/ui';
|
|
15
|
+
import '@tanstack/react-query';
|
|
16
|
+
import 'yazl';
|
|
17
|
+
import 'crypto';
|
|
18
|
+
import 'readline-sync';
|
|
19
|
+
import 'node:readline';
|
|
20
|
+
import 'node:path';
|
|
21
|
+
import 'node:url';
|
|
22
|
+
import 'isomorphic-git';
|
|
23
|
+
import 'fast-glob';
|
|
24
|
+
import 'socket.io-client';
|
|
25
|
+
import 'open';
|
|
26
|
+
import 'marked';
|
|
27
|
+
import 'marked-terminal';
|
|
28
|
+
import 'path';
|
|
29
|
+
import 'qrcode';
|
|
30
|
+
import { R as RunWithSpinner } from '../../../RunWithSpinner-BVXNWGD3.js';
|
|
31
|
+
import 'string-length';
|
|
32
|
+
import 'strip-ansi';
|
|
33
|
+
import { C as Command } from '../../../Command-B3AmRt2w.js';
|
|
34
|
+
import { e as exportCredential } from '../../../export-CVs_xoDN.js';
|
|
35
|
+
import '@expo/apple-utils/build/index.js';
|
|
36
|
+
import 'ini';
|
|
37
|
+
import 'deepmerge';
|
|
38
|
+
import '../../../index-BB00V5oF.js';
|
|
39
|
+
import '../../../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
40
|
+
|
|
41
|
+
class AppleCertificateExport extends BaseAuthenticatedCommand {
|
|
42
|
+
static args = {
|
|
43
|
+
file: Args.string({ description: "Name of the ZIP file to create", required: true })
|
|
44
|
+
};
|
|
45
|
+
static description = "Saves the current Apple Distribution Certificate to a ZIP file.";
|
|
46
|
+
static examples = ["<%= config.bin %> <%= command.id %> userCert.zip"];
|
|
47
|
+
static flags = {
|
|
48
|
+
force: Flags.boolean({ char: "f", description: "Overwrite the file if it already exists" })
|
|
49
|
+
};
|
|
50
|
+
async run() {
|
|
51
|
+
const { args, flags } = this;
|
|
52
|
+
const { file } = args;
|
|
53
|
+
const { force } = flags;
|
|
54
|
+
const zipAlreadyExists = fs.existsSync(file);
|
|
55
|
+
if (zipAlreadyExists && !force) {
|
|
56
|
+
this.error(`The file ${file} already exists. Use --force to overwrite it.`);
|
|
57
|
+
}
|
|
58
|
+
const userCredentials = await getUserCredentials();
|
|
59
|
+
const userAppleDistCredentials = userCredentials.filter(
|
|
60
|
+
(cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.CERTIFICATE
|
|
61
|
+
);
|
|
62
|
+
if (userAppleDistCredentials.length === 0) {
|
|
63
|
+
this.error("No Apple Distribution Certificate found which can be exported.");
|
|
64
|
+
}
|
|
65
|
+
const [cert] = userAppleDistCredentials;
|
|
66
|
+
const handleComplete = async () => process.exit(0);
|
|
67
|
+
render(
|
|
68
|
+
/* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
|
|
69
|
+
RunWithSpinner,
|
|
70
|
+
{
|
|
71
|
+
msgInProgress: `Exporting certificate to ${file}...`,
|
|
72
|
+
msgComplete: `Certificate exported to ${file}`,
|
|
73
|
+
executeMethod: () => exportCredential({ zipPath: file, credentialId: cert.id }),
|
|
74
|
+
onComplete: handleComplete
|
|
75
|
+
}
|
|
76
|
+
) })
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { AppleCertificateExport as default };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { B as BaseAuthenticatedCommand, P as Platform, C as CredentialsType } from '../../../index-DkNQs11R.js';
|
|
6
|
+
import { g as getUserCredentials } from '../../../index-CIa2EDQ6.js';
|
|
7
|
+
import 'react';
|
|
8
|
+
import '../../../index-nnzhQ3nY.js';
|
|
9
|
+
import 'ink-spinner';
|
|
10
|
+
import 'axios';
|
|
11
|
+
import 'crypto-js';
|
|
12
|
+
import 'uuid';
|
|
13
|
+
import 'luxon';
|
|
14
|
+
import '@inkjs/ui';
|
|
15
|
+
import '@tanstack/react-query';
|
|
16
|
+
import 'yazl';
|
|
17
|
+
import 'crypto';
|
|
18
|
+
import 'readline-sync';
|
|
19
|
+
import 'node:readline';
|
|
20
|
+
import 'node:path';
|
|
21
|
+
import 'node:url';
|
|
22
|
+
import 'isomorphic-git';
|
|
23
|
+
import 'fast-glob';
|
|
24
|
+
import 'socket.io-client';
|
|
25
|
+
import 'open';
|
|
26
|
+
import 'marked';
|
|
27
|
+
import 'marked-terminal';
|
|
28
|
+
import 'path';
|
|
29
|
+
import 'qrcode';
|
|
30
|
+
import { R as RunWithSpinner } from '../../../RunWithSpinner-BVXNWGD3.js';
|
|
31
|
+
import 'string-length';
|
|
32
|
+
import 'strip-ansi';
|
|
33
|
+
import { C as Command } from '../../../Command-B3AmRt2w.js';
|
|
34
|
+
import { i as importCredential } from '../../../import-Ch5O7xfN.js';
|
|
35
|
+
import '@expo/apple-utils/build/index.js';
|
|
36
|
+
import 'ini';
|
|
37
|
+
import 'deepmerge';
|
|
38
|
+
import '../../../index-BB00V5oF.js';
|
|
39
|
+
import '../../../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
40
|
+
|
|
41
|
+
class AppleCertificateImport extends BaseAuthenticatedCommand {
|
|
42
|
+
static args = {
|
|
43
|
+
file: Args.string({
|
|
44
|
+
description: "Name of the ZIP file to import (must be in the same format as the export)",
|
|
45
|
+
required: true
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
static description = "Imports an iOS Distribution Certificate to your ShipThis account";
|
|
49
|
+
static examples = ["<%= config.bin %> <%= command.id %> userCert.zip"];
|
|
50
|
+
static flags = {
|
|
51
|
+
force: Flags.boolean({ char: "f" })
|
|
52
|
+
};
|
|
53
|
+
async run() {
|
|
54
|
+
const { args, flags } = this;
|
|
55
|
+
const { file } = args;
|
|
56
|
+
const { force } = flags;
|
|
57
|
+
const zipFound = fs.existsSync(file);
|
|
58
|
+
if (!zipFound) {
|
|
59
|
+
this.error(`The file ${file} does not exist.`);
|
|
60
|
+
}
|
|
61
|
+
const userCredentials = await getUserCredentials();
|
|
62
|
+
const userAppleDistCredentials = userCredentials.filter(
|
|
63
|
+
(cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.CERTIFICATE
|
|
64
|
+
);
|
|
65
|
+
if (userAppleDistCredentials.length !== 0 && !force) {
|
|
66
|
+
this.error("An Apple Distribution Certificate already exists. Use --force to overwrite it.");
|
|
67
|
+
}
|
|
68
|
+
const handleComplete = async () => {
|
|
69
|
+
await this.config.runCommand(`apple:certificate:status`, ["--noAppleAuth"]);
|
|
70
|
+
};
|
|
71
|
+
render(
|
|
72
|
+
/* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
|
|
73
|
+
RunWithSpinner,
|
|
74
|
+
{
|
|
75
|
+
msgInProgress: `Importing certificate from ${file}...`,
|
|
76
|
+
msgComplete: `Certificate imported from ${file}`,
|
|
77
|
+
executeMethod: () => importCredential({ zipPath: file, type: CredentialsType.CERTIFICATE, platform: Platform.IOS }),
|
|
78
|
+
onComplete: handleComplete
|
|
79
|
+
}
|
|
80
|
+
) })
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { AppleCertificateImport as default };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Flags } from '@oclif/core';
|
|
3
|
+
import { Box, Text, render } from 'ink';
|
|
4
|
+
import { b as getShortDate, l as Certificate, m as CertificateType, P as Platform, C as CredentialsType, B as BaseAuthenticatedCommand } from '../../../index-DkNQs11R.js';
|
|
5
|
+
import 'react';
|
|
6
|
+
import '../../../index-nnzhQ3nY.js';
|
|
7
|
+
import Spinner from 'ink-spinner';
|
|
8
|
+
import 'axios';
|
|
9
|
+
import 'crypto-js';
|
|
10
|
+
import 'uuid';
|
|
11
|
+
import 'fs';
|
|
12
|
+
import { DateTime } from 'luxon';
|
|
13
|
+
import '@inkjs/ui';
|
|
14
|
+
import { useQuery } from '@tanstack/react-query';
|
|
15
|
+
import 'yazl';
|
|
16
|
+
import 'crypto';
|
|
17
|
+
import 'readline-sync';
|
|
18
|
+
import 'node:readline';
|
|
19
|
+
import 'node:path';
|
|
20
|
+
import 'node:url';
|
|
21
|
+
import 'isomorphic-git';
|
|
22
|
+
import 'fast-glob';
|
|
23
|
+
import 'socket.io-client';
|
|
24
|
+
import 'open';
|
|
25
|
+
import 'marked';
|
|
26
|
+
import 'marked-terminal';
|
|
27
|
+
import 'path';
|
|
28
|
+
import 'qrcode';
|
|
29
|
+
import 'string-length';
|
|
30
|
+
import 'strip-ansi';
|
|
31
|
+
import { g as getShortUUID } from '../../../index-BB00V5oF.js';
|
|
32
|
+
import { u as useUserCredentials, U as UserCredentialsTable } from '../../../UserCredentialsTable-DhtM_iTG.js';
|
|
33
|
+
import { T as Table } from '../../../Table-CvM6pccN.js';
|
|
34
|
+
import { T as Title } from '../../../Title-BCQtayg6.js';
|
|
35
|
+
import { N as NextSteps } from '../../../NextSteps-CK9zHOCt.js';
|
|
36
|
+
import { C as Command } from '../../../Command-B3AmRt2w.js';
|
|
37
|
+
import '@expo/apple-utils/build/index.js';
|
|
38
|
+
import 'ini';
|
|
39
|
+
import 'deepmerge';
|
|
40
|
+
import '../../../useAndroidServiceAccountTestResult-DcYDam-p.js';
|
|
41
|
+
|
|
42
|
+
async function queryAppleCertificates({ ctx }) {
|
|
43
|
+
const appleCerts = await Certificate.getAsync(ctx, {
|
|
44
|
+
query: {
|
|
45
|
+
filter: {
|
|
46
|
+
certificateType: [CertificateType.DISTRIBUTION, CertificateType.IOS_DISTRIBUTION]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return appleCerts;
|
|
51
|
+
}
|
|
52
|
+
const canAppleCertificateBeUsed = (cert, userCredentials) => {
|
|
53
|
+
if (cert.attributes.status != "Issued") return false;
|
|
54
|
+
return userCredentials.some((cred) => cred.isActive && cred.serialNumber == cert.attributes.serialNumber);
|
|
55
|
+
};
|
|
56
|
+
function getAppleCertificateSummary(cert, userCredentials) {
|
|
57
|
+
return {
|
|
58
|
+
id: getShortUUID(cert.id),
|
|
59
|
+
name: cert.attributes.name,
|
|
60
|
+
serial: cert.attributes.serialNumber,
|
|
61
|
+
expires: getShortDate(DateTime.fromISO(cert.attributes.expirationDate)),
|
|
62
|
+
canBeUsed: canAppleCertificateBeUsed(cert, userCredentials)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const useAppleCertificates = (props) => {
|
|
66
|
+
const queryResult = useQuery({
|
|
67
|
+
queryKey: ["appleCertificates"],
|
|
68
|
+
queryFn: () => queryAppleCertificates(props)
|
|
69
|
+
});
|
|
70
|
+
return queryResult;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const AppleCertificatesTable = ({ ctx, ...boxProps }) => {
|
|
74
|
+
const { data: userCredentialsResponse } = useUserCredentials({
|
|
75
|
+
platform: Platform.IOS,
|
|
76
|
+
type: CredentialsType.CERTIFICATE
|
|
77
|
+
});
|
|
78
|
+
const { data: certs, isLoading } = useAppleCertificates({ ctx });
|
|
79
|
+
const hasUsable = certs && userCredentialsResponse && certs.some((cert) => canAppleCertificateBeUsed(cert, userCredentialsResponse.data));
|
|
80
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
81
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, ...boxProps, children: [
|
|
82
|
+
/* @__PURE__ */ jsx(Title, { children: "Distribution Certificates in your Apple account" }),
|
|
83
|
+
isLoading && /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
|
|
84
|
+
certs && userCredentialsResponse && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
85
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 2, marginBottom: 1, flexDirection: "column", children: [
|
|
86
|
+
/* @__PURE__ */ jsx(Text, { children: `You have ${certs.length} Distribution Certificates in your Apple account` }),
|
|
87
|
+
/* @__PURE__ */ jsx(Text, { children: `${hasUsable ? "One" : "None"} of these can be used by ShipThis` })
|
|
88
|
+
] }),
|
|
89
|
+
certs.length > 0 && /* @__PURE__ */ jsx(Table, { data: certs.map((cert) => getAppleCertificateSummary(cert, userCredentialsResponse.data)) }),
|
|
90
|
+
!hasUsable && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, children: "You do not have a usable Distribution Certificate. To ship an iOS game, you will need a usable Distribution Certificate." }) })
|
|
91
|
+
] })
|
|
92
|
+
] }),
|
|
93
|
+
certs && !hasUsable && /* @__PURE__ */ jsx(NextSteps, { steps: ["shipthis apple certificate create"] })
|
|
94
|
+
] });
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
class AppleCertificateStatus extends BaseAuthenticatedCommand {
|
|
98
|
+
static args = {};
|
|
99
|
+
static description = "Displays the status of the iOS Distribution certificates in your Apple and ShipThis accounts.\nThese are used to sign all of your iOS apps.";
|
|
100
|
+
static examples = [
|
|
101
|
+
"<%= config.bin %> <%= command.id %>",
|
|
102
|
+
"<%= config.bin %> <%= command.id %> --noAppleAuth"
|
|
103
|
+
];
|
|
104
|
+
static flags = {
|
|
105
|
+
noAppleAuth: Flags.boolean({ char: "f" })
|
|
106
|
+
};
|
|
107
|
+
async run() {
|
|
108
|
+
const { flags } = this;
|
|
109
|
+
const showApple = !flags.noAppleAuth;
|
|
110
|
+
let ctx = null;
|
|
111
|
+
if (showApple) {
|
|
112
|
+
const authState = await this.refreshAppleAuthState();
|
|
113
|
+
ctx = authState.context;
|
|
114
|
+
}
|
|
115
|
+
render(
|
|
116
|
+
/* @__PURE__ */ jsxs(Command, { command: this, children: [
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
UserCredentialsTable,
|
|
119
|
+
{
|
|
120
|
+
credentialTypeName: "Apple iOS Distribution Certificate",
|
|
121
|
+
queryProps: { type: CredentialsType.CERTIFICATE, platform: Platform.IOS }
|
|
122
|
+
}
|
|
123
|
+
),
|
|
124
|
+
showApple && /* @__PURE__ */ jsx(AppleCertificatesTable, { ctx })
|
|
125
|
+
] })
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export { AppleCertificateStatus as default };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { a0 as Auth, B as BaseAuthenticatedCommand } from '../../index-DkNQs11R.js';
|
|
3
|
+
import { a as getInput, d as getMaskedInput } from '../../index-BB00V5oF.js';
|
|
4
|
+
import 'path';
|
|
5
|
+
import 'fs';
|
|
6
|
+
import '@expo/apple-utils/build/index.js';
|
|
7
|
+
import 'axios';
|
|
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
|
+
async function getNewAuthState(username, password) {
|
|
26
|
+
const authState = await Auth.loginAsync({
|
|
27
|
+
username,
|
|
28
|
+
password
|
|
29
|
+
});
|
|
30
|
+
return authState;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class AppleLogin extends BaseAuthenticatedCommand {
|
|
34
|
+
static args = {};
|
|
35
|
+
static description = "Authenticate with Apple - saves the session to the auth file";
|
|
36
|
+
static examples = [
|
|
37
|
+
"<%= config.bin %> <%= command.id %>",
|
|
38
|
+
"<%= config.bin %> <%= command.id %> --force --appleEmail me@email.nowhere"
|
|
39
|
+
];
|
|
40
|
+
static flags = {
|
|
41
|
+
quiet: Flags.boolean({ char: "q", description: "Avoid output except for interactions and errors" }),
|
|
42
|
+
force: Flags.boolean({ char: "f" }),
|
|
43
|
+
appleEmail: Flags.string({
|
|
44
|
+
char: "e",
|
|
45
|
+
description: "Your Apple Developer email address"
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
async run() {
|
|
49
|
+
const { flags } = this;
|
|
50
|
+
const isLoggedIn = await this.hasValidAppleAuthState();
|
|
51
|
+
if (isLoggedIn && !flags.force) {
|
|
52
|
+
throw new Error("You are already logged in to Apple. Use --force to re-authenticate.");
|
|
53
|
+
}
|
|
54
|
+
const getAppleEmail = async () => {
|
|
55
|
+
if (flags.appleEmail) return flags.appleEmail;
|
|
56
|
+
const appleEmail2 = await getInput("Please enter your Apple Developer account email address: ");
|
|
57
|
+
if (!appleEmail2) throw new Error("Email address is required");
|
|
58
|
+
return appleEmail2;
|
|
59
|
+
};
|
|
60
|
+
const getApplePassword = async () => {
|
|
61
|
+
const applePassword2 = await getMaskedInput("Please enter your Apple Developer password: ");
|
|
62
|
+
if (!applePassword2) throw new Error("Password is required");
|
|
63
|
+
return applePassword2;
|
|
64
|
+
};
|
|
65
|
+
const appleEmail = await getAppleEmail();
|
|
66
|
+
const applePassword = await getApplePassword();
|
|
67
|
+
const authState = await getNewAuthState(appleEmail, applePassword);
|
|
68
|
+
if (!authState) {
|
|
69
|
+
throw new Error("Failed to authenticate with Apple");
|
|
70
|
+
}
|
|
71
|
+
await this.setAppleCookies(authState.cookies);
|
|
72
|
+
if (!this.flags.quiet) await this.config.runCommand(`apple:status`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { AppleLogin as default };
|