shipthis 0.0.1

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 (67) hide show
  1. package/README.md +894 -0
  2. package/bin/alias.sh +10 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +7 -0
  5. package/bin/dev.tsc.js +15 -0
  6. package/bin/loader.js +20 -0
  7. package/bin/run.cmd +3 -0
  8. package/bin/run.js +5 -0
  9. package/bin/run.tsc.js +15 -0
  10. package/dist/App-DFPMSEZF.js +21 -0
  11. package/dist/AppleBundleIdDetails-CuhAbVEp.js +61 -0
  12. package/dist/NextSteps-CK9zHOCt.js +18 -0
  13. package/dist/RunWithSpinner-BVXNWGD3.js +27 -0
  14. package/dist/StatusTable-CxuX_R1D.js +38 -0
  15. package/dist/Table-CvM6pccN.js +101 -0
  16. package/dist/Title-BCQtayg6.js +6 -0
  17. package/dist/UserCredentialsTable-DHeRI4h6.js +76 -0
  18. package/dist/baseAppleCommand-BXUu-026.js +10 -0
  19. package/dist/baseGameCommand-xrD2WDDN.js +599 -0
  20. package/dist/cacheKeys-CShA-ZjE.js +9 -0
  21. package/dist/commands/apple/apiKey/create.js +88 -0
  22. package/dist/commands/apple/apiKey/export.js +66 -0
  23. package/dist/commands/apple/apiKey/import.js +70 -0
  24. package/dist/commands/apple/apiKey/status.js +108 -0
  25. package/dist/commands/apple/certificate/create.js +118 -0
  26. package/dist/commands/apple/certificate/export.js +66 -0
  27. package/dist/commands/apple/certificate/import.js +70 -0
  28. package/dist/commands/apple/certificate/status.js +116 -0
  29. package/dist/commands/apple/login.js +74 -0
  30. package/dist/commands/apple/status.js +50 -0
  31. package/dist/commands/dashboard.js +32 -0
  32. package/dist/commands/game/build/download.js +78 -0
  33. package/dist/commands/game/build/list.js +83 -0
  34. package/dist/commands/game/create.js +59 -0
  35. package/dist/commands/game/details.js +89 -0
  36. package/dist/commands/game/export.js +52 -0
  37. package/dist/commands/game/ios/app/addTester.js +111 -0
  38. package/dist/commands/game/ios/app/create.js +104 -0
  39. package/dist/commands/game/ios/app/status.js +52 -0
  40. package/dist/commands/game/ios/app/sync.js +81 -0
  41. package/dist/commands/game/ios/profile/create.js +110 -0
  42. package/dist/commands/game/ios/profile/export.js +68 -0
  43. package/dist/commands/game/ios/profile/import.js +77 -0
  44. package/dist/commands/game/ios/profile/status.js +183 -0
  45. package/dist/commands/game/ios/status.js +79 -0
  46. package/dist/commands/game/job/list.js +80 -0
  47. package/dist/commands/game/job/status.js +297 -0
  48. package/dist/commands/game/list.js +69 -0
  49. package/dist/commands/game/ship.js +67 -0
  50. package/dist/commands/game/status.js +76 -0
  51. package/dist/commands/game/wizard.js +124 -0
  52. package/dist/commands/login.js +63 -0
  53. package/dist/commands/status.js +80 -0
  54. package/dist/export-CujqsTR_.js +36 -0
  55. package/dist/git-DREGq-jc.js +32 -0
  56. package/dist/import-Q-KO61ll.js +38 -0
  57. package/dist/index-DKsVctbw.js +125 -0
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.js +1 -0
  60. package/dist/run.js +3 -0
  61. package/dist/upload-CUlWmNbS.js +60 -0
  62. package/dist/useAppleApp-BmwYu7qG.js +32 -0
  63. package/dist/useAppleBundleId-DCJnfNWr.js +64 -0
  64. package/dist/useBuilds-Dh_PWwCf.js +41 -0
  65. package/dist/useJob-CCkqCMvF.js +34 -0
  66. package/oclif.manifest.json +1510 -0
  67. package/package.json +167 -0
@@ -0,0 +1,74 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { W as Auth, B as BaseAuthenticatedCommand } from '../../baseGameCommand-xrD2WDDN.js';
3
+ import 'path';
4
+ import 'fs';
5
+ import '@expo/apple-utils/build/index.js';
6
+ import 'axios';
7
+ import 'luxon';
8
+ import { a as getInput, f as getMaskedInput } from '../../index-DKsVctbw.js';
9
+ import 'tough-cookie';
10
+ import 'nativescript/lib/services/apple-portal/apple-portal-cookie-service.js';
11
+ import 'nativescript/lib/services/apple-portal/apple-portal-session-service.js';
12
+ import 'nativescript/lib/common/http-client.js';
13
+ import 'crypto';
14
+ import 'readline-sync';
15
+ import 'node:readline';
16
+ import 'react';
17
+ import '@tanstack/react-query';
18
+ import 'socket.io-client';
19
+ import 'ini';
20
+ import 'deepmerge';
21
+ import 'isomorphic-git';
22
+
23
+ async function getNewAuthState(username, password) {
24
+ const authState = await Auth.loginAsync({
25
+ username,
26
+ password
27
+ });
28
+ return authState;
29
+ }
30
+
31
+ class AppleLogin extends BaseAuthenticatedCommand {
32
+ static args = {};
33
+ static description = "Authenticate with Apple - saves the session to the auth file";
34
+ static examples = [
35
+ "<%= config.bin %> <%= command.id %>",
36
+ "<%= config.bin %> <%= command.id %> --force --appleEmail me@email.nowhere"
37
+ ];
38
+ static flags = {
39
+ quiet: Flags.boolean({ char: "q", description: "Avoid output except for interactions and errors" }),
40
+ force: Flags.boolean({ char: "f" }),
41
+ appleEmail: Flags.string({
42
+ char: "e",
43
+ description: "Your Apple email address"
44
+ })
45
+ };
46
+ async run() {
47
+ const { flags } = this;
48
+ const isLoggedIn = await this.hasValidAppleAuthState();
49
+ if (isLoggedIn && !flags.force) {
50
+ throw new Error("You are already logged in to Apple. Use --force to re-authenticate.");
51
+ }
52
+ const getAppleEmail = async () => {
53
+ if (flags.appleEmail) return flags.appleEmail;
54
+ const appleEmail2 = await getInput("Please enter your Apple email address: ");
55
+ if (!appleEmail2) throw new Error("Email address is required");
56
+ return appleEmail2;
57
+ };
58
+ const getApplePassword = async () => {
59
+ const applePassword2 = await getMaskedInput("Please enter your Apple password: ");
60
+ if (!applePassword2) throw new Error("Password is required");
61
+ return applePassword2;
62
+ };
63
+ const appleEmail = await getAppleEmail();
64
+ const applePassword = await getApplePassword();
65
+ const authState = await getNewAuthState(appleEmail, applePassword);
66
+ if (!authState) {
67
+ throw new Error("Failed to authenticate with Apple");
68
+ }
69
+ await this.setAppleCookies(authState.cookies);
70
+ if (!this.flags.quiet) await this.config.runCommand(`apple:status`);
71
+ }
72
+ }
73
+
74
+ export { AppleLogin as default };
@@ -0,0 +1,50 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import 'path';
3
+ import 'fs';
4
+ import '@oclif/core';
5
+ import '@expo/apple-utils/build/index.js';
6
+ import 'axios';
7
+ import '../../baseGameCommand-xrD2WDDN.js';
8
+ import 'luxon';
9
+ import 'crypto';
10
+ import 'readline-sync';
11
+ import 'node:readline';
12
+ import 'react';
13
+ import '@tanstack/react-query';
14
+ import 'socket.io-client';
15
+ import 'isomorphic-git';
16
+ import { B as BaseAppleCommand } from '../../baseAppleCommand-BXUu-026.js';
17
+ import { A as App } from '../../App-DFPMSEZF.js';
18
+ import { render } from 'ink';
19
+ import 'ink-spinner';
20
+ import { S as StatusTable } from '../../StatusTable-CxuX_R1D.js';
21
+ import 'string-length';
22
+ import 'strip-ansi';
23
+ import { N as NextSteps } from '../../NextSteps-CK9zHOCt.js';
24
+ import 'ini';
25
+ import 'deepmerge';
26
+ import '../../Title-BCQtayg6.js';
27
+
28
+ class AppleStatus extends BaseAppleCommand {
29
+ static args = {};
30
+ static description = "Shows the status of the Apple authentication and integration";
31
+ static examples = ["<%= config.bin %> <%= command.id %>"];
32
+ static flags = {};
33
+ async run() {
34
+ const authState = await this.refreshAppleAuthState();
35
+ const { session } = authState;
36
+ const statuses = {
37
+ "Full Name": session.user.fullName,
38
+ "Provider Name": session.provider.name
39
+ };
40
+ const steps = [];
41
+ render(
42
+ /* @__PURE__ */ jsxs(App, { children: [
43
+ /* @__PURE__ */ jsx(StatusTable, { marginBottom: 1, title: "Apple Status", statuses }),
44
+ /* @__PURE__ */ jsx(NextSteps, { steps })
45
+ ] })
46
+ );
47
+ }
48
+ }
49
+
50
+ export { AppleStatus as default };
@@ -0,0 +1,32 @@
1
+ import open from 'open';
2
+ import { B as BaseAuthenticatedCommand, T as getSingleUseUrl } from '../baseGameCommand-xrD2WDDN.js';
3
+ import 'path';
4
+ import 'fs';
5
+ import '@oclif/core';
6
+ import '@expo/apple-utils/build/index.js';
7
+ import 'crypto';
8
+ import 'readline-sync';
9
+ import 'node:readline';
10
+ import 'react';
11
+ import 'axios';
12
+ import '@tanstack/react-query';
13
+ import 'socket.io-client';
14
+ import 'luxon';
15
+ import 'isomorphic-git';
16
+ import 'ini';
17
+ import 'deepmerge';
18
+
19
+ class Dashboard extends BaseAuthenticatedCommand {
20
+ static args = {};
21
+ static description = "Opens the web-browser to your ShipThis dashboard";
22
+ static examples = ["<%= config.bin %> <%= command.id %>"];
23
+ static flags = {};
24
+ async run() {
25
+ const dashboardUrl = await getSingleUseUrl("/dashboard");
26
+ console.log(`Opening ${dashboardUrl}...`);
27
+ await open(dashboardUrl);
28
+ process.exit(0);
29
+ }
30
+ }
31
+
32
+ export { Dashboard as default };
@@ -0,0 +1,78 @@
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 'path';
6
+ import '@expo/apple-utils/build/index.js';
7
+ import { d as BaseGameCommand, F as getBuild } from '../../../baseGameCommand-xrD2WDDN.js';
8
+ import 'crypto';
9
+ import 'readline-sync';
10
+ import 'node:readline';
11
+ import 'react';
12
+ import axios from 'axios';
13
+ import '@tanstack/react-query';
14
+ import 'socket.io-client';
15
+ import 'luxon';
16
+ import 'isomorphic-git';
17
+ import { A as App } from '../../../App-DFPMSEZF.js';
18
+ import 'ink-spinner';
19
+ import 'string-length';
20
+ import 'strip-ansi';
21
+ import { R as RunWithSpinner } from '../../../RunWithSpinner-BVXNWGD3.js';
22
+ import 'ini';
23
+ import 'deepmerge';
24
+
25
+ class GameBuildDownload extends BaseGameCommand {
26
+ static args = {
27
+ build_id: Args.string({ description: "The ID of the build to download", required: true }),
28
+ file: Args.string({ description: "Name of the file to output", required: true })
29
+ };
30
+ static description = "Downloads the given build artifact to the specified file";
31
+ static examples = [
32
+ "<%= config.bin %> <%= command.id %> 7a3f5c92 output.ipa",
33
+ "<%= config.bin %> <%= command.id %> --gameId 0c179fc4 e4b9a3d7 output.apk"
34
+ ];
35
+ static flags = {
36
+ ...BaseGameCommand.flags,
37
+ force: Flags.boolean({ char: "f", description: "Overwrite the file if it already exists" })
38
+ };
39
+ async run() {
40
+ const { args, flags } = this;
41
+ const { file, build_id } = args;
42
+ const { force } = flags;
43
+ const alreadyExists = fs.existsSync(file);
44
+ if (alreadyExists && !force) {
45
+ this.error(`The file ${file} already exists. Use --force to overwrite it.`);
46
+ }
47
+ const executeMethod = async () => {
48
+ const game = await this.getGame();
49
+ const build = await getBuild(game.id, build_id);
50
+ const url = build.url;
51
+ const writer = fs.createWriteStream(file);
52
+ const response = await axios({
53
+ url,
54
+ method: "GET",
55
+ responseType: "stream"
56
+ });
57
+ response.data.pipe(writer);
58
+ return new Promise((resolve, reject) => {
59
+ writer.on("finish", resolve);
60
+ writer.on("error", reject);
61
+ });
62
+ };
63
+ const handleComplete = async () => process.exit(0);
64
+ render(
65
+ /* @__PURE__ */ jsx(App, { children: /* @__PURE__ */ jsx(
66
+ RunWithSpinner,
67
+ {
68
+ msgInProgress: `Downloading to ${file}...`,
69
+ msgComplete: `Downloaded build artifact to ${file}`,
70
+ executeMethod,
71
+ onComplete: handleComplete
72
+ }
73
+ ) })
74
+ );
75
+ }
76
+ }
77
+
78
+ export { GameBuildDownload as default };
@@ -0,0 +1,83 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Text, render } from 'ink';
3
+ import { Flags } from '@oclif/core';
4
+ import 'path';
5
+ import 'fs';
6
+ import '@expo/apple-utils/build/index.js';
7
+ import 'axios';
8
+ import { d as BaseGameCommand } from '../../../baseGameCommand-xrD2WDDN.js';
9
+ import 'luxon';
10
+ import 'crypto';
11
+ import 'readline-sync';
12
+ import 'node:readline';
13
+ import 'react';
14
+ import '@tanstack/react-query';
15
+ import 'socket.io-client';
16
+ import 'isomorphic-git';
17
+ import { A as App } from '../../../App-DFPMSEZF.js';
18
+ import Spinner from 'ink-spinner';
19
+ import { u as useBuilds, g as getBuildSummary } from '../../../useBuilds-Dh_PWwCf.js';
20
+ import { T as Table } from '../../../Table-CvM6pccN.js';
21
+ import { T as Title } from '../../../Title-BCQtayg6.js';
22
+ import 'string-length';
23
+ import 'strip-ansi';
24
+ import 'ini';
25
+ import 'deepmerge';
26
+ import '../../../cacheKeys-CShA-ZjE.js';
27
+ import '../../../index-DKsVctbw.js';
28
+ import '../../../useJob-CCkqCMvF.js';
29
+
30
+ const BuildsTable = ({ queryProps, ...boxProps }) => {
31
+ const { isLoading, data } = useBuilds(queryProps);
32
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, ...boxProps, children: [
33
+ /* @__PURE__ */ jsx(Title, { children: `Builds uploaded to ShipThis from completed jobs for this game.` }),
34
+ isLoading && /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
35
+ data && /* @__PURE__ */ jsx(Table, { data: data.data.map(getBuildSummary) }),
36
+ data && data.pageCount > 1 && /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
37
+ /* @__PURE__ */ jsx(Text, { children: `Showing page ${(queryProps.pageNumber || 0) + 1} of ${data.pageCount}.` }),
38
+ /* @__PURE__ */ jsx(Text, { children: "Use the --pageNumber parameter to see other pages." })
39
+ ] })
40
+ ] });
41
+ };
42
+
43
+ class GameBuildList extends BaseGameCommand {
44
+ static args = {};
45
+ static description = "Lists the builds for successful jobs of a game.";
46
+ static examples = [
47
+ "<%= config.bin %> <%= command.id %>",
48
+ "<%= config.bin %> <%= command.id %> --gameId 0c179fc4",
49
+ "<%= config.bin %> <%= command.id %> --gameId 0c179fc4 --pageSize 20 --pageNumber 1"
50
+ ];
51
+ static flags = {
52
+ ...super.flags,
53
+ pageNumber: Flags.integer({ char: "p", description: "The page number to show (starts at 0)", default: 0 }),
54
+ pageSize: Flags.integer({ char: "s", description: "The number of items to show per page", default: 10 }),
55
+ orderBy: Flags.string({
56
+ char: "o",
57
+ description: "The field to order by",
58
+ default: "createdAt",
59
+ options: ["createdAt", "updatedAt"]
60
+ }),
61
+ order: Flags.string({
62
+ char: "r",
63
+ description: "The order to sort by",
64
+ default: "desc",
65
+ options: ["asc", "desc"]
66
+ })
67
+ };
68
+ async run() {
69
+ const game = await this.getGame();
70
+ const { flags } = this;
71
+ const { gameId, ...otherFlags } = flags;
72
+ const params = otherFlags;
73
+ const queryProps = {
74
+ projectId: game.id,
75
+ ...params
76
+ };
77
+ render(
78
+ /* @__PURE__ */ jsx(App, { children: /* @__PURE__ */ jsx(BuildsTable, { queryProps }) })
79
+ );
80
+ }
81
+ }
82
+
83
+ export { GameBuildList as default };
@@ -0,0 +1,59 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { B as BaseAuthenticatedCommand, i as isCWDGodotGame, x as GameEngine, y as getGodotVersion, z as createProject, D as DEFAULT_SHIPPED_FILES_GLOBS, c as DEFAULT_IGNORED_FILES_GLOBS, E as getGodotProjectName } from '../../baseGameCommand-xrD2WDDN.js';
3
+ import 'path';
4
+ import 'fs';
5
+ import '@expo/apple-utils/build/index.js';
6
+ import { a as getInput } from '../../index-DKsVctbw.js';
7
+ import 'axios';
8
+ import 'luxon';
9
+ import 'crypto';
10
+ import 'readline-sync';
11
+ import 'node:readline';
12
+ import 'react';
13
+ import '@tanstack/react-query';
14
+ import 'socket.io-client';
15
+ import 'ini';
16
+ import 'deepmerge';
17
+ import 'isomorphic-git';
18
+
19
+ class GameCreate extends BaseAuthenticatedCommand {
20
+ static args = {};
21
+ static description = "Create a new game";
22
+ static examples = ["<%= config.bin %> <%= command.id %>"];
23
+ static flags = {
24
+ quiet: Flags.boolean({ char: "q", description: "Avoid output except for interactions and errors" }),
25
+ force: Flags.boolean({ char: "f" }),
26
+ name: Flags.string({ char: "n", description: "The name of the game" })
27
+ };
28
+ async run() {
29
+ const { flags } = this;
30
+ if (this.hasProjectConfig() && !flags.force) {
31
+ throw new Error("This directory already has a ShipThis project. Use --force to overwrite.");
32
+ }
33
+ if (!isCWDGodotGame()) {
34
+ this.error("No Godot project detected. Please run this from a godot project directory.", { exit: 1 });
35
+ }
36
+ const getName = async () => {
37
+ if (flags.name) return flags.name;
38
+ const suggested = getGodotProjectName() || "My Awesome Game";
39
+ const name2 = await getInput(`Please enter the name of the game, or press enter to use ${suggested}: `);
40
+ return name2 || suggested;
41
+ };
42
+ const name = await getName();
43
+ const gameEngine = GameEngine.GODOT;
44
+ const gameEngineVersion = getGodotVersion();
45
+ const details = {
46
+ gameEngine,
47
+ gameEngineVersion
48
+ };
49
+ const project = await createProject({ name, details });
50
+ await this.setProjectConfig({
51
+ project,
52
+ shippedFilesGlobs: DEFAULT_SHIPPED_FILES_GLOBS,
53
+ ignoredFilesGlobs: DEFAULT_IGNORED_FILES_GLOBS
54
+ });
55
+ if (!flags.quiet) await this.config.runCommand("game:status");
56
+ }
57
+ }
58
+
59
+ export { GameCreate as default };
@@ -0,0 +1,89 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { render } from 'ink';
3
+ import { Flags } from '@oclif/core';
4
+ import { A as App } from '../../App-DFPMSEZF.js';
5
+ import 'ink-spinner';
6
+ import { d as BaseGameCommand, x as GameEngine } from '../../baseGameCommand-xrD2WDDN.js';
7
+ import { i as isValidSemVer } from '../../index-DKsVctbw.js';
8
+ import 'react';
9
+ import 'luxon';
10
+ import '@tanstack/react-query';
11
+ import '@expo/apple-utils/build/index.js';
12
+ import 'axios';
13
+ import 'fs';
14
+ import { S as StatusTable } from '../../StatusTable-CxuX_R1D.js';
15
+ import 'socket.io-client';
16
+ import 'string-length';
17
+ import 'strip-ansi';
18
+ import 'path';
19
+ import 'crypto';
20
+ import 'readline-sync';
21
+ import 'node:readline';
22
+ import 'isomorphic-git';
23
+ import 'ini';
24
+ import 'deepmerge';
25
+ import '../../Title-BCQtayg6.js';
26
+
27
+ class GameDetails extends BaseGameCommand {
28
+ static args = {};
29
+ static description = "Shows and sets the details of a game. If --gameId is not provided it will look in the current directory.";
30
+ static examples = [
31
+ "<%= config.bin %> <%= command.id %>",
32
+ "<%= config.bin %> <%= command.id %> --gameId 0c179fc4",
33
+ "<%= config.bin %> <%= command.id %> --buildNumber 5 --semanticVersion 1.2.3",
34
+ "<%= config.bin %> <%= command.id %> --gameEngine godot --gameEngineVersion 4.2 --force"
35
+ ];
36
+ static flags = {
37
+ ...BaseGameCommand.flags,
38
+ force: Flags.boolean({ char: "f", description: "Force the command to run" }),
39
+ buildNumber: Flags.integer({ char: "b", description: "Set the build number" }),
40
+ semanticVersion: Flags.string({ char: "s", description: "Set the semantic version" }),
41
+ gameEngine: Flags.string({ char: "e", description: "Set the game engine" }),
42
+ gameEngineVersion: Flags.string({ char: "v", description: "Set the game engine version" }),
43
+ iosBundleId: Flags.string({ char: "i", description: "Set the iOS bundle ID" }),
44
+ androidPackageName: Flags.string({ char: "a", description: "Set the Android package name" })
45
+ };
46
+ async run() {
47
+ const { gameId, force, ...valueFlags } = this.flags;
48
+ const { semanticVersion, buildNumber, gameEngine, gameEngineVersion, iosBundleId, androidPackageName } = valueFlags;
49
+ if (semanticVersion && !isValidSemVer(semanticVersion))
50
+ throw new Error(`Invalid semantic version: ${semanticVersion}`);
51
+ if ((gameEngine || gameEngineVersion || iosBundleId || androidPackageName) && !force)
52
+ throw new Error("Use --force to set the restricted fields");
53
+ if (gameEngine && gameEngine !== GameEngine.GODOT) throw new Error(`Game engine ${gameEngine} not supported`);
54
+ let game = await this.getGame();
55
+ const update = {
56
+ details: {
57
+ ...game.details,
58
+ ...semanticVersion && { semanticVersion },
59
+ ...buildNumber && { buildNumber },
60
+ ...gameEngine && { gameEngine },
61
+ ...gameEngineVersion && { gameEngineVersion },
62
+ ...iosBundleId && { iosBundleId },
63
+ ...androidPackageName && { androidPackageName }
64
+ }
65
+ };
66
+ if (Object.keys(valueFlags).length > 0) {
67
+ game = await this.updateGame(update);
68
+ }
69
+ render(
70
+ /* @__PURE__ */ jsx(App, { children: /* @__PURE__ */ jsx(
71
+ StatusTable,
72
+ {
73
+ title: "Game Details",
74
+ statuses: {
75
+ "Game Engine": game.details?.gameEngine || "Please set!",
76
+ "Game Engine Version": game.details?.gameEngineVersion || "Please set!",
77
+ "iOS Bundle ID": game.details?.iosBundleId || "N/A",
78
+ "Android Package Name": game.details?.androidPackageName || "N/A",
79
+ "Semantic Version": game.details?.semanticVersion || "0.0.1",
80
+ "Build Number": game.details?.buildNumber || 1
81
+ }
82
+ }
83
+ ) })
84
+ );
85
+ return;
86
+ }
87
+ }
88
+
89
+ export { GameDetails as default };
@@ -0,0 +1,52 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { B as BaseAuthenticatedCommand, i as isCWDGodotGame, b as getProject, D as DEFAULT_SHIPPED_FILES_GLOBS, c as DEFAULT_IGNORED_FILES_GLOBS } from '../../baseGameCommand-xrD2WDDN.js';
3
+ import 'path';
4
+ import 'fs';
5
+ import '@expo/apple-utils/build/index.js';
6
+ import 'crypto';
7
+ import 'readline-sync';
8
+ import 'node:readline';
9
+ import 'react';
10
+ import 'axios';
11
+ import '@tanstack/react-query';
12
+ import 'socket.io-client';
13
+ import 'luxon';
14
+ import 'isomorphic-git';
15
+ import 'ini';
16
+ import 'deepmerge';
17
+
18
+ class GameExport extends BaseAuthenticatedCommand {
19
+ static args = {
20
+ game_id: Args.string({ description: 'The ID of the game to export (use "list" to get the ID)', required: true })
21
+ };
22
+ static description = "Downloads the shipthis.json file for a given game into the current directory.";
23
+ static examples = [
24
+ "<%= config.bin %> <%= command.id %> abcd1234",
25
+ "<%= config.bin %> <%= command.id %> abcd1234 --force"
26
+ ];
27
+ static flags = {
28
+ force: Flags.boolean({ char: "f" })
29
+ };
30
+ async run() {
31
+ const { args } = this;
32
+ if (!isCWDGodotGame()) {
33
+ return this.error("No Godot project detected. Please run this from a godot project directory.", { exit: 1 });
34
+ }
35
+ if (this.hasProjectConfig() && !this.flags.force) {
36
+ return this.error(
37
+ "This project has already been initialized. Use --force to overwrite the existing configuration.",
38
+ { exit: 1 }
39
+ );
40
+ }
41
+ const project = await getProject(args.game_id);
42
+ await this.setProjectConfig({
43
+ project,
44
+ shippedFilesGlobs: DEFAULT_SHIPPED_FILES_GLOBS,
45
+ ignoredFilesGlobs: DEFAULT_IGNORED_FILES_GLOBS
46
+ });
47
+ await this.config.runCommand("game:status");
48
+ this.exit(0);
49
+ }
50
+ }
51
+
52
+ export { GameExport as default };
@@ -0,0 +1,111 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { render } from 'ink';
3
+ import { Flags } from '@oclif/core';
4
+ import { A as App } from '../../../../App-DFPMSEZF.js';
5
+ import 'ink-spinner';
6
+ import { a as getInput } from '../../../../index-DKsVctbw.js';
7
+ import 'react';
8
+ import { d as BaseGameCommand, j as BetaGroup } from '../../../../baseGameCommand-xrD2WDDN.js';
9
+ import 'luxon';
10
+ import '@tanstack/react-query';
11
+ import { q as queryAppleApp } from '../../../../useAppleApp-BmwYu7qG.js';
12
+ import 'axios';
13
+ import 'fs';
14
+ import 'socket.io-client';
15
+ import 'string-length';
16
+ import 'strip-ansi';
17
+ import { R as RunWithSpinner } from '../../../../RunWithSpinner-BVXNWGD3.js';
18
+ import 'path';
19
+ import '@expo/apple-utils/build/index.js';
20
+ import 'crypto';
21
+ import 'readline-sync';
22
+ import 'node:readline';
23
+ import 'isomorphic-git';
24
+ import 'ini';
25
+ import 'deepmerge';
26
+
27
+ const TEST_GROUP_NAME = "ShipThis Test Group";
28
+ class GameIosAppAddTester extends BaseGameCommand {
29
+ static args = {};
30
+ static description = "Adds a test user to the game in App Store Connect.";
31
+ static examples = ["<%= config.bin %> <%= command.id %>"];
32
+ static flags = {
33
+ gameId: Flags.string({ char: "g", description: "The ID of the game" }),
34
+ email: Flags.string({ char: "e", description: "The email address of the tester" }),
35
+ firstName: Flags.string({ char: "f", description: "The first name of the tester" }),
36
+ lastName: Flags.string({ char: "l", description: "The last name of the tester" })
37
+ };
38
+ async run() {
39
+ const game = await this.getGame();
40
+ const authState = await this.refreshAppleAuthState();
41
+ const ctx = authState.context;
42
+ const { flags } = this;
43
+ const getEmail = async () => {
44
+ if (flags.email) return flags.email;
45
+ const question = `Please enter the email address of the tester: `;
46
+ const enteredEmail = await getInput(question);
47
+ if (!enteredEmail) {
48
+ this.error("No email address provided");
49
+ }
50
+ return enteredEmail;
51
+ };
52
+ const getFirstName = async () => {
53
+ if (flags.firstName) return flags.firstName;
54
+ const suggestedName = "John";
55
+ const question = `Please enter the first name of the tester, or press enter to use ${suggestedName}: `;
56
+ const enteredName = await getInput(question);
57
+ return enteredName || suggestedName;
58
+ };
59
+ const getLastName = async () => {
60
+ if (flags.lastName) return flags.lastName;
61
+ const suggestedName = "Doe";
62
+ const question = `Please enter the last name of the tester, or press enter to use ${suggestedName}: `;
63
+ const enteredName = await getInput(question);
64
+ return enteredName || suggestedName;
65
+ };
66
+ const email = await getEmail();
67
+ const firstName = await getFirstName();
68
+ const lastName = await getLastName();
69
+ console.warn("This command does not yet work. It fails with an assertion error.");
70
+ const addTestUser = async () => {
71
+ const { app } = await queryAppleApp({ ctx, iosBundleId: game.details?.iosBundleId });
72
+ if (!app) return this.error("No app found");
73
+ const groups = await BetaGroup.getAsync(ctx, {});
74
+ let shipThisGroup = groups.find(
75
+ (group) => group.attributes.name === TEST_GROUP_NAME && group.attributes.isInternalGroup
76
+ );
77
+ if (!shipThisGroup) {
78
+ shipThisGroup = await BetaGroup.createAsync(ctx, {
79
+ id: app.id,
80
+ name: TEST_GROUP_NAME,
81
+ isInternalGroup: true,
82
+ publicLinkEnabled: false,
83
+ publicLinkLimit: 1,
84
+ publicLinkLimitEnabled: false
85
+ });
86
+ }
87
+ await shipThisGroup.createBulkBetaTesterAssignmentsAsync([
88
+ {
89
+ email,
90
+ firstName,
91
+ lastName
92
+ }
93
+ ]);
94
+ };
95
+ const handleComplete = async () => {
96
+ };
97
+ render(
98
+ /* @__PURE__ */ jsx(App, { children: /* @__PURE__ */ jsx(
99
+ RunWithSpinner,
100
+ {
101
+ msgInProgress: "Adding test user...",
102
+ msgComplete: "Added test user",
103
+ executeMethod: addTestUser,
104
+ onComplete: handleComplete
105
+ }
106
+ ) })
107
+ );
108
+ }
109
+ }
110
+
111
+ export { GameIosAppAddTester as default };