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.
Files changed (84) hide show
  1. package/dist/AppleBundleIdDetails-mPUG2R4N.js +76 -0
  2. package/dist/Command-B3AmRt2w.js +28 -0
  3. package/dist/CommandGame-BCMzP9pc.js +9 -0
  4. package/dist/Create-CsJxpzUs.js +59 -0
  5. package/dist/Import-v0M_ygyF.js +110 -0
  6. package/dist/JobProgress-9uvq8IBn.js +121 -0
  7. package/dist/JobStatusTable-Bf7J9WXe.js +191 -0
  8. package/dist/NextSteps-CK9zHOCt.js +18 -0
  9. package/dist/ProgressSpinner-6pw1T8Iw.js +16 -0
  10. package/dist/ProjectCredentialsTable-CTkP1mvy.js +37 -0
  11. package/dist/RunWithSpinner-BVXNWGD3.js +27 -0
  12. package/dist/StatusTable-Dm5St4g-.js +33 -0
  13. package/dist/Table-CvM6pccN.js +101 -0
  14. package/dist/Title-BCQtayg6.js +6 -0
  15. package/dist/UserCredentialsTable-DhtM_iTG.js +82 -0
  16. package/dist/baseAppleCommand-IGl6KTvv.js +10 -0
  17. package/dist/baseGameAndroidCommand-DFn4zMvq.js +43 -0
  18. package/dist/commands/apple/apiKey/create.js +103 -0
  19. package/dist/commands/apple/apiKey/export.js +81 -0
  20. package/dist/commands/apple/apiKey/import.js +85 -0
  21. package/dist/commands/apple/apiKey/status.js +122 -0
  22. package/dist/commands/apple/certificate/create.js +133 -0
  23. package/dist/commands/apple/certificate/export.js +81 -0
  24. package/dist/commands/apple/certificate/import.js +85 -0
  25. package/dist/commands/apple/certificate/status.js +130 -0
  26. package/dist/commands/apple/login.js +76 -0
  27. package/dist/commands/apple/status.js +79 -0
  28. package/dist/commands/dashboard.js +38 -0
  29. package/dist/commands/game/android/apiKey/connect.js +74 -0
  30. package/dist/commands/game/android/apiKey/create.js +74 -0
  31. package/dist/commands/game/android/apiKey/export.js +84 -0
  32. package/dist/commands/game/android/apiKey/import.js +93 -0
  33. package/dist/commands/game/android/apiKey/invite.js +81 -0
  34. package/dist/commands/game/android/apiKey/status.js +87 -0
  35. package/dist/commands/game/android/keyStore/create.js +69 -0
  36. package/dist/commands/game/android/keyStore/export.js +83 -0
  37. package/dist/commands/game/android/keyStore/import.js +112 -0
  38. package/dist/commands/game/android/keyStore/status.js +70 -0
  39. package/dist/commands/game/android/status.js +84 -0
  40. package/dist/commands/game/build/download.js +80 -0
  41. package/dist/commands/game/build/list.js +94 -0
  42. package/dist/commands/game/create.js +67 -0
  43. package/dist/commands/game/details.js +113 -0
  44. package/dist/commands/game/export.js +58 -0
  45. package/dist/commands/game/ios/app/addTester.js +124 -0
  46. package/dist/commands/game/ios/app/create.js +117 -0
  47. package/dist/commands/game/ios/app/status.js +66 -0
  48. package/dist/commands/game/ios/app/sync.js +95 -0
  49. package/dist/commands/game/ios/profile/create.js +129 -0
  50. package/dist/commands/game/ios/profile/export.js +83 -0
  51. package/dist/commands/game/ios/profile/import.js +92 -0
  52. package/dist/commands/game/ios/profile/status.js +139 -0
  53. package/dist/commands/game/ios/status.js +92 -0
  54. package/dist/commands/game/ios/wizard.js +153 -0
  55. package/dist/commands/game/job/list.js +91 -0
  56. package/dist/commands/game/job/status.js +91 -0
  57. package/dist/commands/game/list.js +83 -0
  58. package/dist/commands/game/ship.js +216 -0
  59. package/dist/commands/game/status.js +114 -0
  60. package/dist/commands/game/wizard.js +686 -0
  61. package/dist/commands/internal/fastlane.js +74 -0
  62. package/dist/commands/internal/readme.js +937 -0
  63. package/dist/commands/login.js +92 -0
  64. package/dist/commands/status.js +76 -0
  65. package/dist/export-CVs_xoDN.js +36 -0
  66. package/dist/git-DREGq-jc.js +32 -0
  67. package/dist/import-Ch5O7xfN.js +47 -0
  68. package/dist/index-BB00V5oF.js +136 -0
  69. package/dist/index-BD1WLuFJ.js +125 -0
  70. package/dist/index-CIa2EDQ6.js +24 -0
  71. package/dist/index-CboPN9aq.js +138 -0
  72. package/dist/index-DkNQs11R.js +711 -0
  73. package/dist/index-nnzhQ3nY.js +209 -0
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.js +1 -0
  76. package/dist/upload-CRE2nVdd.js +60 -0
  77. package/dist/useAndroidServiceAccountTestResult-DcYDam-p.js +52 -0
  78. package/dist/useAppleApp-B16WbUxJ.js +32 -0
  79. package/dist/useAppleBundleId-DobPATan.js +64 -0
  80. package/dist/useJobWatching--BvVn7xS.js +45 -0
  81. package/dist/useProjectCredentials-Btnr7WK3.js +54 -0
  82. package/dist/useWebSocket-ByuNoqRw.js +36 -0
  83. package/dist/utils/help.js +14 -0
  84. package/package.json +1 -1
@@ -0,0 +1,27 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import Spinner from 'ink-spinner';
5
+
6
+ const RunWithSpinner = ({
7
+ executeMethod,
8
+ msgInProgress,
9
+ msgComplete,
10
+ onComplete,
11
+ spinnerType
12
+ }) => {
13
+ const [isInProgress, setIsInProgress] = React.useState(true);
14
+ React.useEffect(() => {
15
+ setIsInProgress(true);
16
+ executeMethod().then(() => {
17
+ setIsInProgress(false);
18
+ return onComplete();
19
+ });
20
+ }, []);
21
+ return /* @__PURE__ */ jsxs(Box, { children: [
22
+ /* @__PURE__ */ jsx(Text, { children: isInProgress ? msgInProgress : msgComplete }),
23
+ isInProgress && /* @__PURE__ */ jsx(Spinner, { type: spinnerType })
24
+ ] });
25
+ };
26
+
27
+ export { RunWithSpinner as R };
@@ -0,0 +1,33 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Text } from 'ink';
3
+ import { T as Title } from './Title-BCQtayg6.js';
4
+
5
+ const StatusRowLabel = ({ label, width }) => /* @__PURE__ */ jsx(Box, { width: width || 10, marginRight: 2, children: /* @__PURE__ */ jsx(Text, { children: `${label}` }) });
6
+ const StatusRow = ({ label, labelWidth, value, ...textProps }) => {
7
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "flex-end", children: [
8
+ /* @__PURE__ */ jsx(StatusRowLabel, { width: labelWidth, label }),
9
+ /* @__PURE__ */ jsx(Text, { bold: true, ...textProps, children: value })
10
+ ] });
11
+ };
12
+ const StatusTable = ({ title, statuses, colors, ...rest }) => {
13
+ const getColor = (key) => {
14
+ const value = statuses[key];
15
+ if (typeof value === "boolean") return value ? "green" : "red";
16
+ const defaultColor = "green";
17
+ const color = colors?.[key];
18
+ return color || defaultColor;
19
+ };
20
+ const getText = (key) => {
21
+ const value = statuses[key];
22
+ if (typeof value === "boolean") return value ? "YES" : "NO";
23
+ return value;
24
+ };
25
+ const maxLabelLength = Math.max(...Object.keys(statuses).map((key) => key.length));
26
+ const labelWidth = Math.max(maxLabelLength, 10);
27
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", ...rest, children: [
28
+ /* @__PURE__ */ jsx(Title, { children: title }),
29
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: Object.entries(statuses).map(([key, value]) => /* @__PURE__ */ jsx(StatusRow, { labelWidth, label: key, value: getText(key), color: getColor(key) }, key)) })
30
+ ] });
31
+ };
32
+
33
+ export { StatusTable as S, StatusRow as a, StatusRowLabel as b };
@@ -0,0 +1,101 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { Box, Text } from 'ink';
4
+
5
+ const BASE_HEADER_PROPS = {
6
+ color: "blue",
7
+ bold: true
8
+ };
9
+ const BASE_TEXT_PROPS = {
10
+ color: "white"
11
+ };
12
+ function generateHeaders(data) {
13
+ let headers = {};
14
+ data.forEach((row) => {
15
+ Object.keys(row).forEach((key) => {
16
+ headers[key] = key;
17
+ });
18
+ });
19
+ return headers;
20
+ }
21
+ const Table = ({ data, showHeaders = true, headerTextProps, columnTextProps, getTextProps }) => {
22
+ const columns = getColumns(data);
23
+ const fullHeaderTextProps = {
24
+ ...BASE_HEADER_PROPS,
25
+ ...headerTextProps
26
+ };
27
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
28
+ renderHeaderSeparators(columns),
29
+ showHeaders && /* @__PURE__ */ jsxs(Fragment, { children: [
30
+ renderRow(generateHeaders(data), columns, fullHeaderTextProps),
31
+ renderRowSeparators(columns)
32
+ ] }),
33
+ data.map((row, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
34
+ index !== 0 && renderRowSeparators(columns),
35
+ renderRow(row, columns, BASE_TEXT_PROPS, columnTextProps, getTextProps)
36
+ ] }, `row-${index}`)),
37
+ renderFooterSeparators(columns)
38
+ ] });
39
+ };
40
+ function getColumns(data) {
41
+ let columnWidths = {};
42
+ data.forEach((row) => {
43
+ Object.keys(row).forEach((key) => {
44
+ const valueLength = row[key]?.toString().length || 0;
45
+ columnWidths[key] = Math.max(columnWidths[key] || key.length, valueLength);
46
+ });
47
+ });
48
+ return Object.keys(columnWidths).map((key) => ({
49
+ key,
50
+ width: (columnWidths[key] ?? 0) + 2
51
+ // adding padding
52
+ }));
53
+ }
54
+ function renderRow(row, columns, baseCellTextProps, columnTextProps, getTextProps) {
55
+ const getDisplayValue = (row2, column) => {
56
+ const value = row2[column.key];
57
+ if (typeof value === "boolean") return value ? "YES" : "NO";
58
+ return value?.toString() || "";
59
+ };
60
+ const getTextPropsForCell = (row2, column) => {
61
+ const { key } = column;
62
+ const value = row2[key];
63
+ const columnTextPropsForCell = columnTextProps?.[key] || {};
64
+ const valueBasedProps = typeof row2[column.key] === "boolean" ? { color: value == false ? "red" : "green" } : {};
65
+ const callbackBasedProps = getTextProps ? getTextProps(column, value) : {};
66
+ return {
67
+ ...baseCellTextProps,
68
+ ...columnTextPropsForCell,
69
+ ...valueBasedProps,
70
+ ...callbackBasedProps
71
+ };
72
+ };
73
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
74
+ /* @__PURE__ */ jsx(Text, { children: "\u2502" }),
75
+ columns.map((column, index) => {
76
+ const cellTextProps = getTextPropsForCell(row, column);
77
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
78
+ index !== 0 && /* @__PURE__ */ jsx(Text, { children: "\u2502" }),
79
+ /* @__PURE__ */ jsx(Box, { width: column.width, justifyContent: "center", children: /* @__PURE__ */ jsx(Text, { ...cellTextProps, children: getDisplayValue(row, column) }) })
80
+ ] }, column.key);
81
+ }),
82
+ /* @__PURE__ */ jsx(Text, { children: "\u2502" })
83
+ ] });
84
+ }
85
+ function renderHeaderSeparators(columns) {
86
+ return renderRowSeparators(columns, "\u250C", "\u252C", "\u2510");
87
+ }
88
+ function renderFooterSeparators(columns) {
89
+ return renderRowSeparators(columns, "\u2514", "\u2534", "\u2518");
90
+ }
91
+ function renderRowSeparators(columns, leftChar = "\u251C", midChar = "\u253C", rightChar = "\u2524") {
92
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
93
+ /* @__PURE__ */ jsx(Text, { children: leftChar }),
94
+ columns.map((column, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
95
+ /* @__PURE__ */ jsx(Text, { children: "\u2500".repeat(column.width) }),
96
+ index < columns.length - 1 ? /* @__PURE__ */ jsx(Text, { children: midChar }) : /* @__PURE__ */ jsx(Text, { children: rightChar })
97
+ ] }, column.key))
98
+ ] });
99
+ }
100
+
101
+ export { Table as T };
@@ -0,0 +1,6 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Text } from 'ink';
3
+
4
+ const Title = ({ children, ...rest }) => /* @__PURE__ */ jsx(Text, { bold: true, ...rest, children: children.toUpperCase() });
5
+
6
+ export { Title as T };
@@ -0,0 +1,82 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Text } from 'ink';
3
+ import Spinner from 'ink-spinner';
4
+ import 'crypto';
5
+ import 'fs';
6
+ import 'readline-sync';
7
+ import 'node:readline';
8
+ import 'node:path';
9
+ import 'node:url';
10
+ import 'luxon';
11
+ import axios from 'axios';
12
+ import 'isomorphic-git';
13
+ import { b as getShortDate, p as getAuthedHeaders, q as API_URL, L as castArrayObjectDates } from './index-DkNQs11R.js';
14
+ import '@oclif/core';
15
+ import 'react';
16
+ import { useQuery } from '@tanstack/react-query';
17
+ import 'crypto-js';
18
+ import 'uuid';
19
+ import 'fast-glob';
20
+ import 'yazl';
21
+ import { c as cacheKeys } from './useAndroidServiceAccountTestResult-DcYDam-p.js';
22
+ import { g as getShortUUID } from './index-BB00V5oF.js';
23
+ import 'socket.io-client';
24
+ import { T as Table } from './Table-CvM6pccN.js';
25
+ import { T as Title } from './Title-BCQtayg6.js';
26
+
27
+ async function queryUserCredentials(params) {
28
+ try {
29
+ const headers = getAuthedHeaders();
30
+ const url = `${API_URL}/credentials`;
31
+ const response = await axios.get(url, { headers, params });
32
+ return {
33
+ ...response.data,
34
+ data: castArrayObjectDates(response.data.data)
35
+ };
36
+ } catch (error) {
37
+ console.warn("queryUserCredentials Error", error);
38
+ throw error;
39
+ }
40
+ }
41
+ function getUserCredentialSummary(credential) {
42
+ return {
43
+ id: getShortUUID(credential.id),
44
+ type: credential.type,
45
+ serial: credential.serialNumber,
46
+ isActive: credential.isActive,
47
+ createdAt: getShortDate(credential.createdAt)
48
+ };
49
+ }
50
+ const useUserCredentials = ({
51
+ platform,
52
+ type,
53
+ ...pageAndSortParams
54
+ }) => {
55
+ const queryResult = useQuery({
56
+ queryKey: cacheKeys.userCredentials(pageAndSortParams),
57
+ queryFn: async () => queryUserCredentials(pageAndSortParams),
58
+ select: (data) => {
59
+ if (!(platform || type)) return data;
60
+ return {
61
+ ...data,
62
+ data: data.data.filter((credential) => {
63
+ return (!platform || credential.platform === platform) && (!type || credential.type === type);
64
+ })
65
+ };
66
+ }
67
+ });
68
+ return queryResult;
69
+ };
70
+
71
+ const UserCredentialsTable = ({ credentialTypeName, queryProps, ...boxProps }) => {
72
+ const { isLoading, data } = useUserCredentials(queryProps);
73
+ const hasActive = data?.data.some((credential) => credential.isActive);
74
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, ...boxProps, children: [
75
+ /* @__PURE__ */ jsx(Title, { children: `${credentialTypeName}s in your ShipThis account` }),
76
+ /* @__PURE__ */ jsx(Box, { marginLeft: 2, marginBottom: 1, flexDirection: "column", children: /* @__PURE__ */ jsx(Text, { children: hasActive ? `You have an active ${credentialTypeName} in your ShipThis account.` : `You DO NOT have an active ${credentialTypeName} which ShipThis can use.` }) }),
77
+ isLoading && /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
78
+ data && data.data.length > 0 && /* @__PURE__ */ jsx(Table, { data: data.data.map(getUserCredentialSummary) })
79
+ ] });
80
+ };
81
+
82
+ export { UserCredentialsTable as U, useUserCredentials as u };
@@ -0,0 +1,10 @@
1
+ import { B as BaseAuthenticatedCommand } from './index-DkNQs11R.js';
2
+
3
+ class BaseAppleCommand extends BaseAuthenticatedCommand {
4
+ async init() {
5
+ await super.init();
6
+ await this.ensureWeHaveAppleCookies();
7
+ }
8
+ }
9
+
10
+ export { BaseAppleCommand as B };
@@ -0,0 +1,43 @@
1
+ import { c as BaseGameCommand, S as getGodotAndroidPackageName, T as getGoogleStatus } from './index-DkNQs11R.js';
2
+ import { b as generatePackageName, a as getInput } from './index-BB00V5oF.js';
3
+
4
+ class BaseGameAndroidCommand extends BaseGameCommand {
5
+ async init() {
6
+ await super.init();
7
+ await this.ensureWeHaveAndroidPackageName();
8
+ }
9
+ // Prompts the user for the Android package name
10
+ async getAndroidPackageName(gameId) {
11
+ const game = await this.getGame();
12
+ const generated = generatePackageName(game.name);
13
+ const suggested = game.details?.iosBundleId || getGodotAndroidPackageName() || generated || "com.example.game";
14
+ const question = `Please enter the Android Package Name, or press enter to use ${suggested}: `;
15
+ const entered = await getInput(question);
16
+ return entered || suggested;
17
+ }
18
+ // Forces us to have the androidPackageName in the game details
19
+ async ensureWeHaveAndroidPackageName() {
20
+ const game = await this.getGame();
21
+ if (!game.details?.androidPackageName) {
22
+ const androidPackageName = await this.getAndroidPackageName(game.id);
23
+ await this.updateGame({ details: { ...game.details, androidPackageName } });
24
+ }
25
+ }
26
+ async checkGoogleAuth(waitForAuth = false) {
27
+ let status = await getGoogleStatus();
28
+ if (status.isAuthenticated) return;
29
+ if (!waitForAuth)
30
+ this.error("You must connect to Google first. Run `shipthis game android apiKey connect`", { exit: 1 });
31
+ this.log("Waiting for Google authentication...");
32
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
33
+ for (let i = 0; i < 600; i++) {
34
+ process.stdout.write(".");
35
+ await sleep(1e3 * 10);
36
+ status = await getGoogleStatus();
37
+ if (status.isAuthenticated) return;
38
+ }
39
+ this.error("Google authentication failed. Please try again.", { exit: 1 });
40
+ }
41
+ }
42
+
43
+ export { BaseGameAndroidCommand as B };
@@ -0,0 +1,103 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Flags } from '@oclif/core';
3
+ import { render } from 'ink';
4
+ import { P as Platform, C as CredentialsType, A as ApiKey, a as ApiKeyType, U as UserRole } 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 { B as BaseAppleCommand } from '../../../baseAppleCommand-IGl6KTvv.js';
35
+ import { u as uploadUserCredentials } from '../../../upload-CRE2nVdd.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
+ class AppleApiKeyCreate extends BaseAppleCommand {
43
+ static args = {};
44
+ static description = "Creates an App Store Connect API Key in your Apple Developer account.\nSaves the private key in your ShipThis account.";
45
+ static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> --force"];
46
+ static flags = {
47
+ force: Flags.boolean({ char: "f" }),
48
+ quiet: Flags.boolean({ char: "q", description: "Avoid output except for interactions and errors" })
49
+ };
50
+ async run() {
51
+ const { flags } = this;
52
+ const { force } = flags;
53
+ const userCredentials = await getUserCredentials();
54
+ const userAppleApiKeyCredentials = userCredentials.filter(
55
+ (cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.KEY
56
+ );
57
+ if (userAppleApiKeyCredentials.length !== 0 && !force) {
58
+ this.error("An App Store Connect API already exists. Use --force to overwrite it.");
59
+ }
60
+ const authState = await this.refreshAppleAuthState();
61
+ const ctx = authState.context;
62
+ const createApiKey = async () => {
63
+ const userKey = await ApiKey.createAsync(ctx, {
64
+ nickname: `ShipThis ${Math.floor((/* @__PURE__ */ new Date()).valueOf() / 1e3)}`,
65
+ allAppsVisible: true,
66
+ roles: [UserRole.ADMIN],
67
+ keyType: ApiKeyType.PUBLIC_API
68
+ });
69
+ const keyContent = await userKey.downloadAsync();
70
+ if (!keyContent) throw new Error("Failed to download key content");
71
+ const reloadedKey = await ApiKey.infoAsync(ctx, { id: userKey.id });
72
+ const key = {
73
+ keyId: userKey.id,
74
+ issuer: `${reloadedKey.attributes.provider?.id}`,
75
+ p8Content: keyContent,
76
+ serialNumber: userKey.id
77
+ };
78
+ await uploadUserCredentials({
79
+ platform: Platform.IOS,
80
+ type: CredentialsType.KEY,
81
+ contents: key,
82
+ serialNumber: key.serialNumber
83
+ });
84
+ };
85
+ const handleComplete = async () => {
86
+ await this.config.runCommand(`apple:apiKey:status`);
87
+ };
88
+ if (this.flags.quiet) return await createApiKey();
89
+ render(
90
+ /* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
91
+ RunWithSpinner,
92
+ {
93
+ msgInProgress: `Creating App Store Connect API in the Apple Developer Portal...`,
94
+ msgComplete: `App Store Connect API created and saved to ShipThis`,
95
+ executeMethod: createApiKey,
96
+ onComplete: handleComplete
97
+ }
98
+ ) })
99
+ );
100
+ }
101
+ }
102
+
103
+ export { AppleApiKeyCreate 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 AppleApiKeyExport 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 App Store Connect API Key to a ZIP file";
46
+ static examples = ["<%= config.bin %> <%= command.id %> userApiKey.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 userAppleApiKeyCredentials = userCredentials.filter(
60
+ (cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.KEY
61
+ );
62
+ if (userAppleApiKeyCredentials.length === 0) {
63
+ this.error("No App Store Connect API Key found which can be exported.");
64
+ }
65
+ const [key] = userAppleApiKeyCredentials;
66
+ const handleComplete = async () => process.exit(0);
67
+ render(
68
+ /* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
69
+ RunWithSpinner,
70
+ {
71
+ msgInProgress: `Exporting App Store Connect API Key to ${file}...`,
72
+ msgComplete: `App Store Connect API Key exported to ${file}`,
73
+ executeMethod: () => exportCredential({ zipPath: file, credentialId: key.id }),
74
+ onComplete: handleComplete
75
+ }
76
+ ) })
77
+ );
78
+ }
79
+ }
80
+
81
+ export { AppleApiKeyExport 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 AppleApiKeyImport 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 App Store Connect API Key ZIP file into your ShipThis account";
49
+ static examples = ["<%= config.bin %> <%= command.id %> userApiKey.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 userAppleApiKeyCredentials = userCredentials.filter(
63
+ (cred) => cred.platform == Platform.IOS && cred.type == CredentialsType.KEY
64
+ );
65
+ if (userAppleApiKeyCredentials.length !== 0 && !force) {
66
+ this.error("An App Store Connect API Key already exists. Use --force to overwrite it.");
67
+ }
68
+ const handleComplete = async () => {
69
+ await this.config.runCommand(`apple:apiKey:status`, ["--noAppleAuth"]);
70
+ };
71
+ render(
72
+ /* @__PURE__ */ jsx(Command, { command: this, children: /* @__PURE__ */ jsx(
73
+ RunWithSpinner,
74
+ {
75
+ msgInProgress: `Importing App Store Connect API from ${file}...`,
76
+ msgComplete: `App Store Connect API imported from ${file}`,
77
+ executeMethod: () => importCredential({ zipPath: file, type: CredentialsType.KEY, platform: Platform.IOS }),
78
+ onComplete: handleComplete
79
+ }
80
+ ) })
81
+ );
82
+ }
83
+ }
84
+
85
+ export { AppleApiKeyImport as default };