eas-cli 13.4.1 → 14.0.0

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 (211) hide show
  1. package/README.md +73 -73
  2. package/build/ApiV2Error.js +5 -1
  3. package/build/analytics/AnalyticsManager.js +5 -4
  4. package/build/api.js +1 -0
  5. package/build/branch/actions/SelectBranch.js +1 -0
  6. package/build/branch/queries.d.ts +3 -3
  7. package/build/branch/queries.js +7 -5
  8. package/build/build/validate.js +6 -3
  9. package/build/channel/actions/SelectChannel.js +1 -0
  10. package/build/channel/queries.d.ts +0 -1
  11. package/build/channel/queries.js +11 -16
  12. package/build/commandUtils/EasCommand.js +100 -90
  13. package/build/commandUtils/builds.d.ts +1 -0
  14. package/build/commandUtils/builds.js +3 -0
  15. package/build/commandUtils/context/contextUtils/findProjectDirAndVerifyProjectSetupAsync.js +1 -1
  16. package/build/commandUtils/context/contextUtils/getProjectIdAsync.js +0 -2
  17. package/build/commandUtils/gating/FeatureGateEnvOverrides.js +1 -1
  18. package/build/commandUtils/gating/FeatureGating.js +2 -0
  19. package/build/commands/account/login.js +16 -18
  20. package/build/commands/account/logout.js +6 -8
  21. package/build/commands/account/view.js +8 -10
  22. package/build/commands/analytics.js +2 -2
  23. package/build/commands/branch/create.js +18 -20
  24. package/build/commands/branch/delete.js +17 -19
  25. package/build/commands/branch/list.js +11 -13
  26. package/build/commands/branch/publish.js +2 -2
  27. package/build/commands/branch/rename.js +18 -20
  28. package/build/commands/branch/view.js +19 -21
  29. package/build/commands/build/cancel.js +22 -24
  30. package/build/commands/build/configure.js +15 -17
  31. package/build/commands/build/delete.js +22 -24
  32. package/build/commands/build/index.js +81 -83
  33. package/build/commands/build/inspect.js +42 -44
  34. package/build/commands/build/internal.js +32 -34
  35. package/build/commands/build/list.js +58 -60
  36. package/build/commands/build/resign.js +36 -38
  37. package/build/commands/build/run.js +36 -38
  38. package/build/commands/build/version/get.js +21 -23
  39. package/build/commands/build/version/set.js +20 -22
  40. package/build/commands/build/version/sync.js +20 -22
  41. package/build/commands/build/view.js +12 -14
  42. package/build/commands/channel/create.js +17 -19
  43. package/build/commands/channel/delete.js +18 -20
  44. package/build/commands/channel/edit.js +20 -22
  45. package/build/commands/channel/list.js +12 -14
  46. package/build/commands/channel/pause.js +20 -22
  47. package/build/commands/channel/resume.js +20 -22
  48. package/build/commands/channel/rollout.js +74 -76
  49. package/build/commands/channel/view.js +18 -20
  50. package/build/commands/config.js +21 -23
  51. package/build/commands/credentials/configure-build.js +21 -23
  52. package/build/commands/credentials/index.js +13 -15
  53. package/build/commands/device/create.js +6 -8
  54. package/build/commands/device/delete.js +12 -14
  55. package/build/commands/device/list.js +12 -14
  56. package/build/commands/device/rename.js +13 -15
  57. package/build/commands/device/view.js +8 -10
  58. package/build/commands/diagnostics.js +6 -8
  59. package/build/commands/env/create.js +39 -41
  60. package/build/commands/env/delete.js +25 -27
  61. package/build/commands/env/exec.js +22 -24
  62. package/build/commands/env/get.js +26 -28
  63. package/build/commands/env/link.js +27 -29
  64. package/build/commands/env/list.js +27 -29
  65. package/build/commands/env/pull.js +23 -25
  66. package/build/commands/env/push.js +21 -23
  67. package/build/commands/env/unlink.js +23 -25
  68. package/build/commands/env/update.js +38 -40
  69. package/build/commands/fingerprint/compare.d.ts +28 -0
  70. package/build/commands/fingerprint/compare.js +324 -0
  71. package/build/commands/metadata/lint.js +18 -20
  72. package/build/commands/metadata/pull.js +15 -17
  73. package/build/commands/metadata/push.js +15 -17
  74. package/build/commands/open.js +6 -8
  75. package/build/commands/project/info.js +6 -8
  76. package/build/commands/project/init.js +26 -30
  77. package/build/commands/project/onboarding.js +10 -12
  78. package/build/commands/secret/create.js +30 -32
  79. package/build/commands/secret/delete.js +14 -16
  80. package/build/commands/secret/list.js +7 -9
  81. package/build/commands/secret/push.js +23 -25
  82. package/build/commands/submit/internal.js +23 -25
  83. package/build/commands/submit.js +54 -56
  84. package/build/commands/update/configure.js +18 -20
  85. package/build/commands/update/delete.js +16 -18
  86. package/build/commands/update/edit.js +25 -27
  87. package/build/commands/update/index.js +65 -67
  88. package/build/commands/update/list.js +21 -23
  89. package/build/commands/update/republish.js +45 -47
  90. package/build/commands/update/roll-back-to-embedded.d.ts +2 -1
  91. package/build/commands/update/roll-back-to-embedded.js +92 -84
  92. package/build/commands/update/rollback.js +7 -7
  93. package/build/commands/update/view.js +16 -18
  94. package/build/commands/webhook/create.js +20 -22
  95. package/build/commands/webhook/delete.js +17 -19
  96. package/build/commands/webhook/list.js +14 -16
  97. package/build/commands/webhook/update.js +23 -25
  98. package/build/commands/webhook/view.js +13 -15
  99. package/build/commands/worker/alias.js +30 -32
  100. package/build/commands/worker/deploy.js +38 -40
  101. package/build/commands/workflow/create.js +16 -18
  102. package/build/commands/workflow/run.js +13 -15
  103. package/build/commands/workflow/validate.js +18 -20
  104. package/build/credentials/android/AndroidCredentialsProvider.js +3 -1
  105. package/build/credentials/android/actions/AssignFcm.js +1 -0
  106. package/build/credentials/android/actions/AssignGoogleServiceAccountKeyForFcmV1.js +1 -0
  107. package/build/credentials/android/actions/AssignGoogleServiceAccountKeyForSubmissions.js +1 -0
  108. package/build/credentials/android/actions/CreateFcm.js +1 -0
  109. package/build/credentials/android/actions/CreateGoogleServiceAccountKey.js +1 -0
  110. package/build/credentials/android/actions/CreateKeystore.js +1 -0
  111. package/build/credentials/android/actions/DownloadKeystore.js +2 -0
  112. package/build/credentials/android/actions/RemoveFcm.js +1 -0
  113. package/build/credentials/android/actions/RemoveGoogleServiceAccountKey.js +2 -0
  114. package/build/credentials/android/actions/RemoveKeystore.js +1 -0
  115. package/build/credentials/android/actions/SetUpBuildCredentials.js +1 -0
  116. package/build/credentials/android/actions/SetUpBuildCredentialsFromCredentialsJson.js +1 -0
  117. package/build/credentials/android/actions/SetUpGoogleServiceAccountKeyForFcmV1.js +1 -0
  118. package/build/credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions.js +1 -0
  119. package/build/credentials/android/actions/UseExistingGoogleServiceAccountKey.js +1 -0
  120. package/build/credentials/context.js +14 -5
  121. package/build/credentials/errors.js +1 -0
  122. package/build/credentials/ios/IosCredentialsProvider.js +3 -1
  123. package/build/credentials/ios/actions/AssignAscApiKey.js +1 -0
  124. package/build/credentials/ios/actions/AssignPushKey.js +1 -0
  125. package/build/credentials/ios/actions/ConfigureProvisioningProfile.js +4 -0
  126. package/build/credentials/ios/actions/CreateAscApiKey.js +1 -0
  127. package/build/credentials/ios/actions/CreateDistributionCertificate.js +1 -0
  128. package/build/credentials/ios/actions/CreateProvisioningProfile.js +3 -0
  129. package/build/credentials/ios/actions/CreatePushKey.js +1 -0
  130. package/build/credentials/ios/actions/RemoveAscApiKey.js +2 -0
  131. package/build/credentials/ios/actions/RemoveDistributionCertificate.js +3 -0
  132. package/build/credentials/ios/actions/RemoveProvisioningProfile.js +2 -0
  133. package/build/credentials/ios/actions/RemovePushKey.js +2 -0
  134. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +1 -0
  135. package/build/credentials/ios/actions/SetUpAscApiKey.js +9 -7
  136. package/build/credentials/ios/actions/SetUpBuildCredentials.js +1 -0
  137. package/build/credentials/ios/actions/SetUpBuildCredentialsFromCredentialsJson.js +3 -0
  138. package/build/credentials/ios/actions/SetUpDistributionCertificate.js +3 -0
  139. package/build/credentials/ios/actions/SetUpInternalProvisioningProfile.js +1 -0
  140. package/build/credentials/ios/actions/SetUpProvisioningProfile.js +3 -0
  141. package/build/credentials/ios/actions/SetUpPushKey.js +1 -0
  142. package/build/credentials/ios/actions/SetUpTargetBuildCredentials.js +1 -0
  143. package/build/credentials/ios/actions/SetUpTargetBuildCredentialsFromCredentialsJson.js +3 -0
  144. package/build/credentials/ios/actions/UpdateCredentialsJson.js +3 -0
  145. package/build/credentials/ios/appstore/AppStoreApi.js +2 -0
  146. package/build/credentials/manager/CheckBuildProfileFlagAgainstEasJson.js +3 -0
  147. package/build/credentials/manager/CreateAndroidBuildCredentials.js +1 -0
  148. package/build/credentials/manager/ManageAndroid.js +2 -0
  149. package/build/credentials/manager/ManageIos.js +2 -0
  150. package/build/credentials/manager/SelectAndroidBuildCredentials.js +2 -0
  151. package/build/credentials/manager/SelectBuildProfileFromEasJson.js +2 -0
  152. package/build/credentials/manager/SelectIosDistributionTypeGraphqlFromBuildProfile.js +1 -0
  153. package/build/credentials/manager/SelectPlatform.js +7 -0
  154. package/build/credentials/manager/SetDefaultAndroidKeystore.js +1 -0
  155. package/build/credentials/manager/SetUpAndroidBuildCredentials.js +1 -0
  156. package/build/credentials/manager/SetUpBuildCredentialsCommandAction.js +9 -0
  157. package/build/credentials/manager/SetUpIosBuildCredentials.js +1 -0
  158. package/build/devices/actions/create/action.js +4 -0
  159. package/build/devices/manager.js +4 -0
  160. package/build/fetch.js +1 -0
  161. package/build/graphql/generated.d.ts +179 -3
  162. package/build/graphql/generated.js +8 -3
  163. package/build/graphql/mutations/AppMutation.d.ts +0 -2
  164. package/build/graphql/queries/BuildQuery.d.ts +4 -1
  165. package/build/graphql/queries/BuildQuery.js +19 -0
  166. package/build/graphql/types/Build.d.ts +1 -0
  167. package/build/graphql/types/Build.js +15 -1
  168. package/build/graphql/types/Fingerprint.d.ts +1 -0
  169. package/build/graphql/types/Fingerprint.js +12 -0
  170. package/build/log.js +2 -2
  171. package/build/metadata/apple/config/reader.js +1 -0
  172. package/build/metadata/apple/config/writer.js +1 -0
  173. package/build/metadata/apple/tasks/age-rating.js +1 -4
  174. package/build/metadata/apple/tasks/app-info.js +1 -4
  175. package/build/metadata/apple/tasks/app-review-detail.js +1 -4
  176. package/build/metadata/apple/tasks/app-version.js +2 -1
  177. package/build/metadata/errors.js +5 -0
  178. package/build/project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync.d.ts +0 -2
  179. package/build/project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync.js +0 -1
  180. package/build/project/projectUtils.d.ts +1 -2
  181. package/build/project/projectUtils.js +1 -14
  182. package/build/rollout/actions/CreateRollout.d.ts +9 -10
  183. package/build/rollout/actions/CreateRollout.js +2 -0
  184. package/build/rollout/actions/EditRollout.d.ts +2 -3
  185. package/build/rollout/actions/EditRollout.js +2 -0
  186. package/build/rollout/actions/EndRollout.d.ts +4 -6
  187. package/build/rollout/actions/EndRollout.js +2 -0
  188. package/build/rollout/actions/ManageRollout.d.ts +2 -3
  189. package/build/rollout/actions/ManageRollout.js +2 -0
  190. package/build/rollout/actions/NonInteractiveRollout.d.ts +6 -27
  191. package/build/rollout/actions/NonInteractiveRollout.js +1 -0
  192. package/build/rollout/actions/RolloutMainMenu.d.ts +6 -7
  193. package/build/rollout/actions/RolloutMainMenu.js +1 -0
  194. package/build/rollout/actions/SelectRuntime.d.ts +6 -20
  195. package/build/rollout/actions/SelectRuntime.js +3 -0
  196. package/build/submit/BaseSubmitter.js +4 -0
  197. package/build/submit/android/AndroidSubmitCommand.js +1 -0
  198. package/build/submit/ios/IosSubmitCommand.js +1 -0
  199. package/build/update/configure.js +2 -1
  200. package/build/update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync.js +3 -3
  201. package/build/user/SessionManager.js +2 -0
  202. package/build/utils/fingerprint.d.ts +97 -0
  203. package/build/utils/fingerprint.js +5 -0
  204. package/build/utils/fingerprintCli.d.ts +5 -7
  205. package/build/utils/fingerprintCli.js +11 -1
  206. package/build/utils/fingerprintDiff.d.ts +33 -0
  207. package/build/utils/fingerprintDiff.js +122 -0
  208. package/build/vcs/clients/git.js +2 -1
  209. package/build/vcs/local.js +2 -1
  210. package/oclif.manifest.json +51 -7
  211. package/package.json +15 -13
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectBuildToCompareAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const eas_build_job_1 = require("@expo/eas-build-job");
6
+ const core_1 = require("@oclif/core");
7
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const builds_1 = require("../../commandUtils/builds");
10
+ const flags_1 = require("../../commandUtils/flags");
11
+ const generated_1 = require("../../graphql/generated");
12
+ const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
13
+ const log_1 = tslib_1.__importDefault(require("../../log"));
14
+ const ora_1 = require("../../ora");
15
+ const projectUtils_1 = require("../../project/projectUtils");
16
+ const workflow_1 = require("../../project/workflow");
17
+ const prompts_1 = require("../../prompts");
18
+ const fingerprintCli_1 = require("../../utils/fingerprintCli");
19
+ const fingerprintDiff_1 = require("../../utils/fingerprintDiff");
20
+ const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
21
+ const json_1 = require("../../utils/json");
22
+ class FingerprintCompare extends EasCommand_1.default {
23
+ static description = 'compare fingerprints of the current project, builds and updates';
24
+ static hidden = true;
25
+ static flags = {
26
+ 'build-id': core_1.Flags.string({
27
+ aliases: ['buildId'],
28
+ description: 'Compare the fingerprint with the build with the specified ID',
29
+ }),
30
+ ...flags_1.EasNonInteractiveAndJsonFlags,
31
+ };
32
+ static contextDefinition = {
33
+ ...this.ContextOptions.ProjectId,
34
+ ...this.ContextOptions.ProjectConfig,
35
+ ...this.ContextOptions.LoggedIn,
36
+ ...this.ContextOptions.Vcs,
37
+ };
38
+ async runAsync() {
39
+ const { flags } = await this.parse(FingerprintCompare);
40
+ const { json: jsonFlag, 'non-interactive': nonInteractive, buildId: buildIdFromArg } = flags;
41
+ const { projectId, privateProjectConfig: { projectDir }, loggedIn: { graphqlClient }, vcsClient, } = await this.getContextAsync(FingerprintCompare, {
42
+ nonInteractive,
43
+ withServerSideEnvironment: null,
44
+ });
45
+ if (jsonFlag) {
46
+ (0, json_1.enableJsonOutput)();
47
+ }
48
+ const displayName = await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId);
49
+ let buildId = buildIdFromArg;
50
+ if (!buildId) {
51
+ if (nonInteractive) {
52
+ throw new Error('Build ID must be provided in non-interactive mode');
53
+ }
54
+ buildId = await selectBuildToCompareAsync(graphqlClient, projectId, displayName, {
55
+ filters: { hasFingerprint: true },
56
+ });
57
+ if (!buildId) {
58
+ return;
59
+ }
60
+ }
61
+ log_1.default.log(`Comparing fingerprints of the current project and build ${buildId}…`);
62
+ const buildWithFingerprint = await BuildQuery_1.BuildQuery.withFingerprintByIdAsync(graphqlClient, buildId);
63
+ const fingerprintDebugUrl = buildWithFingerprint.fingerprint?.debugInfoUrl;
64
+ if (!fingerprintDebugUrl) {
65
+ log_1.default.error('A fingerprint for the build could not be found.');
66
+ return;
67
+ }
68
+ const fingerprintResponse = await fetch(fingerprintDebugUrl);
69
+ const fingerprint = (await fingerprintResponse.json());
70
+ const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir, vcsClient);
71
+ const buildPlatform = buildWithFingerprint.platform;
72
+ const workflow = workflows[appPlatformToPlatform(buildPlatform)];
73
+ const projectFingerprint = await (0, fingerprintCli_1.createFingerprintAsync)(projectDir, {
74
+ workflow,
75
+ platforms: [appPlatformToString(buildPlatform)],
76
+ debug: true,
77
+ env: undefined,
78
+ });
79
+ if (!projectFingerprint) {
80
+ log_1.default.error('Project fingerprints can only be computed for projects with SDK 52 or higher');
81
+ return;
82
+ }
83
+ if (fingerprint.hash === projectFingerprint.hash) {
84
+ log_1.default.log(`✅ Project fingerprint matches build`);
85
+ return;
86
+ }
87
+ else {
88
+ log_1.default.log(`🔄 Project fingerprint differs from build`);
89
+ }
90
+ const fingerprintDiffs = (0, fingerprintCli_1.diffFingerprint)(projectDir, fingerprint, projectFingerprint);
91
+ if (!fingerprintDiffs) {
92
+ log_1.default.error('Fingerprint diffs can only be computed for projects with SDK 52 or higher');
93
+ return;
94
+ }
95
+ const filePathDiffs = fingerprintDiffs.filter(diff => {
96
+ let sourceType;
97
+ if (diff.op === 'added') {
98
+ sourceType = diff.addedSource.type;
99
+ }
100
+ else if (diff.op === 'removed') {
101
+ sourceType = diff.removedSource.type;
102
+ }
103
+ else if (diff.op === 'changed') {
104
+ sourceType = diff.beforeSource.type;
105
+ }
106
+ return sourceType === 'dir' || sourceType === 'file';
107
+ });
108
+ if (filePathDiffs.length > 0) {
109
+ log_1.default.newLine();
110
+ log_1.default.log('📁 Paths with native dependencies:');
111
+ }
112
+ const fields = [];
113
+ for (const diff of filePathDiffs) {
114
+ const field = getDiffFilePathFields(diff);
115
+ if (!field) {
116
+ throw new Error(`Unsupported diff: ${JSON.stringify(diff)}`);
117
+ }
118
+ fields.push(field);
119
+ }
120
+ log_1.default.log((0, formatFields_1.default)(fields, {
121
+ labelFormat: label => ` ${chalk_1.default.dim(label)}:`,
122
+ }));
123
+ const contentDiffs = fingerprintDiffs.filter(diff => {
124
+ let sourceType;
125
+ if (diff.op === 'added') {
126
+ sourceType = diff.addedSource.type;
127
+ }
128
+ else if (diff.op === 'removed') {
129
+ sourceType = diff.removedSource.type;
130
+ }
131
+ else if (diff.op === 'changed') {
132
+ sourceType = diff.beforeSource.type;
133
+ }
134
+ return sourceType === 'contents';
135
+ });
136
+ for (const diff of contentDiffs) {
137
+ printContentDiff(diff);
138
+ }
139
+ }
140
+ }
141
+ exports.default = FingerprintCompare;
142
+ function printContentDiff(diff) {
143
+ if (diff.op === 'added') {
144
+ const sourceType = diff.addedSource.type;
145
+ if (sourceType === 'contents') {
146
+ printContentSource({
147
+ op: diff.op,
148
+ sourceType,
149
+ contentsId: diff.addedSource.id,
150
+ contentsAfter: diff.addedSource.contents,
151
+ });
152
+ }
153
+ }
154
+ else if (diff.op === 'removed') {
155
+ const sourceType = diff.removedSource.type;
156
+ if (sourceType === 'contents') {
157
+ printContentSource({
158
+ op: diff.op,
159
+ sourceType,
160
+ contentsId: diff.removedSource.id,
161
+ contentsBefore: diff.removedSource.contents,
162
+ });
163
+ }
164
+ }
165
+ else if (diff.op === 'changed') {
166
+ const sourceType = diff.beforeSource.type;
167
+ if (sourceType === 'contents') {
168
+ if (diff.afterSource.type !== 'contents') {
169
+ throw new Error(`Changed fingerprint source types must be the same, received ${diff.beforeSource.type}, ${diff.afterSource.type}`);
170
+ }
171
+ printContentSource({
172
+ op: diff.op,
173
+ sourceType: diff.beforeSource.type, // before and after source types should be the same
174
+ contentsId: diff.beforeSource.id, // before and after content ids should be the same
175
+ contentsBefore: diff.beforeSource.contents,
176
+ contentsAfter: diff.afterSource.contents,
177
+ });
178
+ }
179
+ }
180
+ }
181
+ function getDiffFilePathFields(diff) {
182
+ if (diff.op === 'added') {
183
+ const sourceType = diff.addedSource.type;
184
+ if (sourceType !== 'contents') {
185
+ return getFilePathSourceFields({
186
+ op: diff.op,
187
+ sourceType,
188
+ filePath: diff.addedSource.filePath,
189
+ });
190
+ }
191
+ }
192
+ else if (diff.op === 'removed') {
193
+ const sourceType = diff.removedSource.type;
194
+ if (sourceType !== 'contents') {
195
+ return getFilePathSourceFields({
196
+ op: diff.op,
197
+ sourceType,
198
+ filePath: diff.removedSource.filePath,
199
+ });
200
+ }
201
+ }
202
+ else if (diff.op === 'changed') {
203
+ const sourceType = diff.beforeSource.type;
204
+ if (sourceType !== 'contents') {
205
+ return getFilePathSourceFields({
206
+ op: diff.op,
207
+ sourceType: diff.beforeSource.type, // before and after source types should be the same
208
+ filePath: diff.beforeSource.filePath, // before and after filePaths should be the same
209
+ });
210
+ }
211
+ }
212
+ return null;
213
+ }
214
+ function getFilePathSourceFields({ op, sourceType, filePath, }) {
215
+ if (sourceType === 'dir') {
216
+ if (op === 'added') {
217
+ return { label: 'new directory', value: filePath };
218
+ }
219
+ else if (op === 'removed') {
220
+ return { label: 'removed directory', value: filePath };
221
+ }
222
+ else if (op === 'changed') {
223
+ return { label: 'modified directory', value: filePath };
224
+ }
225
+ }
226
+ else if (sourceType === 'file') {
227
+ if (op === 'added') {
228
+ return { label: 'new file', value: filePath };
229
+ }
230
+ else if (op === 'removed') {
231
+ return { label: 'removed file', value: filePath };
232
+ }
233
+ else if (op === 'changed') {
234
+ return { label: 'modified file', value: filePath };
235
+ }
236
+ }
237
+ throw new Error(`Unsupported source and op: ${sourceType}, ${op}`);
238
+ }
239
+ const PRETTY_CONTENT_ID = {
240
+ 'expoAutolinkingConfig:ios': 'Expo autolinking config (iOS)',
241
+ 'expoAutolinkingConfig:android': 'Expo autolinking config (Android)',
242
+ 'packageJson:scripts': 'package.json scripts',
243
+ expoConfig: 'Expo config',
244
+ };
245
+ function printContentSource({ op, contentsBefore, contentsAfter, contentsId, }) {
246
+ log_1.default.newLine();
247
+ const prettyContentId = PRETTY_CONTENT_ID[contentsId] ?? contentsId;
248
+ if (op === 'added') {
249
+ log_1.default.log(`${chalk_1.default.dim('📝 New content')}: ${prettyContentId}`);
250
+ }
251
+ else if (op === 'removed') {
252
+ log_1.default.log(`${chalk_1.default.dim('📝 Removed content')}: ${prettyContentId}`);
253
+ }
254
+ else if (op === 'changed') {
255
+ log_1.default.log(`${chalk_1.default.dim('📝 Modified content')}: ${prettyContentId}`);
256
+ }
257
+ printContentsDiff(contentsBefore ?? '', contentsAfter ?? '');
258
+ }
259
+ function printContentsDiff(contents1, contents2) {
260
+ const stringifiedContents1 = Buffer.isBuffer(contents1) ? contents1.toString() : contents1;
261
+ const stringifiedContents2 = Buffer.isBuffer(contents2) ? contents2.toString() : contents2;
262
+ const isStr1JSON = isJSON(stringifiedContents1);
263
+ const isStr2JSON = isJSON(stringifiedContents2);
264
+ const prettifiedContents1 = isStr1JSON
265
+ ? JSON.stringify(JSON.parse(stringifiedContents1), null, 2)
266
+ : stringifiedContents1;
267
+ const prettifiedContents2 = isStr2JSON
268
+ ? JSON.stringify(JSON.parse(stringifiedContents2), null, 2)
269
+ : stringifiedContents2;
270
+ (0, fingerprintDiff_1.abridgedDiff)(prettifiedContents1, prettifiedContents2, 0);
271
+ }
272
+ function isJSON(str) {
273
+ try {
274
+ JSON.parse(str);
275
+ return true;
276
+ }
277
+ catch {
278
+ return false;
279
+ }
280
+ }
281
+ function appPlatformToPlatform(platform) {
282
+ switch (platform) {
283
+ case generated_1.AppPlatform.Android:
284
+ return eas_build_job_1.Platform.ANDROID;
285
+ case generated_1.AppPlatform.Ios:
286
+ return eas_build_job_1.Platform.IOS;
287
+ default:
288
+ throw new Error(`Unsupported platform: ${platform}`);
289
+ }
290
+ }
291
+ function appPlatformToString(platform) {
292
+ switch (platform) {
293
+ case generated_1.AppPlatform.Android:
294
+ return 'android';
295
+ case generated_1.AppPlatform.Ios:
296
+ return 'ios';
297
+ default:
298
+ throw new Error(`Unsupported platform: ${platform}`);
299
+ }
300
+ }
301
+ async function selectBuildToCompareAsync(graphqlClient, projectId, projectDisplayName, { filters, } = {}) {
302
+ const spinner = (0, ora_1.ora)().start('Fetching builds…');
303
+ let builds;
304
+ try {
305
+ builds = await (0, builds_1.fetchBuildsAsync)({ graphqlClient, projectId, filters });
306
+ spinner.stop();
307
+ }
308
+ catch (error) {
309
+ spinner.fail(`Something went wrong and we couldn't fetch the builds for the project ${projectDisplayName}.`);
310
+ throw error;
311
+ }
312
+ if (builds.length === 0) {
313
+ log_1.default.warn(`No fingerprints have been computed for builds of project ${projectDisplayName}.`);
314
+ return null;
315
+ }
316
+ else {
317
+ const build = await (0, prompts_1.selectAsync)('Which build do you want to compare?', builds.map(build => ({
318
+ title: (0, builds_1.formatBuild)(build),
319
+ value: build.id,
320
+ })));
321
+ return build;
322
+ }
323
+ }
324
+ exports.selectBuildToCompareAsync = selectBuildToCompareAsync;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -12,9 +11,25 @@ const errors_1 = require("../../metadata/errors");
12
11
  const json_1 = require("../../utils/json");
13
12
  const profiles_1 = require("../../utils/profiles");
14
13
  class MetadataLint extends EasCommand_1.default {
14
+ static description = 'validate the local store configuration';
15
+ static flags = {
16
+ json: core_1.Flags.boolean({
17
+ description: 'Enable JSON output, non-JSON messages will be printed to stderr',
18
+ default: false,
19
+ }),
20
+ profile: core_1.Flags.string({
21
+ description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
22
+ }),
23
+ };
24
+ static contextDefinition = {
25
+ // The metadata lint command is created to integrate in other dev tooling, like vscode-expo.
26
+ // These integrations might spam this command, so we avoid communicating with our services here.
27
+ // Note that this is an exception and you should normally use `ProjectConfig` instead.
28
+ ...this.ContextOptions.ProjectDir,
29
+ };
15
30
  async runAsync() {
16
- const { flags } = await this.parse(_a);
17
- const { projectDir } = await this.getContextAsync(_a, {
31
+ const { flags } = await this.parse(MetadataLint);
32
+ const { projectDir } = await this.getContextAsync(MetadataLint, {
18
33
  nonInteractive: true,
19
34
  });
20
35
  if (flags.json) {
@@ -55,21 +70,4 @@ class MetadataLint extends EasCommand_1.default {
55
70
  }
56
71
  }
57
72
  }
58
- _a = MetadataLint;
59
- MetadataLint.description = 'validate the local store configuration';
60
- MetadataLint.flags = {
61
- json: core_1.Flags.boolean({
62
- description: 'Enable JSON output, non-JSON messages will be printed to stderr',
63
- default: false,
64
- }),
65
- profile: core_1.Flags.string({
66
- description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
67
- }),
68
- };
69
- MetadataLint.contextDefinition = {
70
- // The metadata lint command is created to integrate in other dev tooling, like vscode-expo.
71
- // These integrations might spam this command, so we avoid communicating with our services here.
72
- // Note that this is an exception and you should normally use `ProjectConfig` instead.
73
- ..._a.ContextOptions.ProjectDir,
74
- };
75
73
  exports.default = MetadataLint;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -15,10 +14,23 @@ const download_1 = require("../../metadata/download");
15
14
  const errors_1 = require("../../metadata/errors");
16
15
  const profiles_1 = require("../../utils/profiles");
17
16
  class MetadataPull extends EasCommand_1.default {
17
+ static description = 'generate the local store configuration from the app stores';
18
+ static flags = {
19
+ profile: core_1.Flags.string({
20
+ char: 'e',
21
+ description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
22
+ }),
23
+ };
24
+ static contextDefinition = {
25
+ ...this.ContextOptions.ProjectConfig,
26
+ ...this.ContextOptions.LoggedIn,
27
+ ...this.ContextOptions.Analytics,
28
+ ...this.ContextOptions.Vcs,
29
+ };
18
30
  async runAsync() {
19
31
  log_1.default.warn('EAS Metadata is in beta and subject to breaking changes.');
20
- const { flags } = await this.parse(_a);
21
- const { loggedIn: { actor, graphqlClient }, privateProjectConfig: { exp, projectId, projectDir }, analytics, vcsClient, } = await this.getContextAsync(_a, {
32
+ const { flags } = await this.parse(MetadataPull);
33
+ const { loggedIn: { actor, graphqlClient }, privateProjectConfig: { exp, projectId, projectDir }, analytics, vcsClient, } = await this.getContextAsync(MetadataPull, {
22
34
  nonInteractive: false,
23
35
  withServerSideEnvironment: null,
24
36
  });
@@ -66,18 +78,4 @@ class MetadataPull extends EasCommand_1.default {
66
78
  }
67
79
  }
68
80
  }
69
- _a = MetadataPull;
70
- MetadataPull.description = 'generate the local store configuration from the app stores';
71
- MetadataPull.flags = {
72
- profile: core_1.Flags.string({
73
- char: 'e',
74
- description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
75
- }),
76
- };
77
- MetadataPull.contextDefinition = {
78
- ..._a.ContextOptions.ProjectConfig,
79
- ..._a.ContextOptions.LoggedIn,
80
- ..._a.ContextOptions.Analytics,
81
- ..._a.ContextOptions.Vcs,
82
- };
83
81
  exports.default = MetadataPull;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -13,10 +12,23 @@ const errors_1 = require("../../metadata/errors");
13
12
  const upload_1 = require("../../metadata/upload");
14
13
  const profiles_1 = require("../../utils/profiles");
15
14
  class MetadataPush extends EasCommand_1.default {
15
+ static description = 'sync the local store configuration to the app stores';
16
+ static flags = {
17
+ profile: core_1.Flags.string({
18
+ char: 'e',
19
+ description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
20
+ }),
21
+ };
22
+ static contextDefinition = {
23
+ ...this.ContextOptions.ProjectConfig,
24
+ ...this.ContextOptions.LoggedIn,
25
+ ...this.ContextOptions.Analytics,
26
+ ...this.ContextOptions.Vcs,
27
+ };
16
28
  async runAsync() {
17
29
  log_1.default.warn('EAS Metadata is in beta and subject to breaking changes.');
18
- const { flags } = await this.parse(_a);
19
- const { loggedIn: { actor, graphqlClient }, privateProjectConfig: { exp, projectId, projectDir }, analytics, vcsClient, } = await this.getContextAsync(_a, {
30
+ const { flags } = await this.parse(MetadataPush);
31
+ const { loggedIn: { actor, graphqlClient }, privateProjectConfig: { exp, projectId, projectDir }, analytics, vcsClient, } = await this.getContextAsync(MetadataPush, {
20
32
  nonInteractive: false,
21
33
  withServerSideEnvironment: null,
22
34
  });
@@ -60,18 +72,4 @@ ${(0, log_1.learnMore)(appleLink, { learnMoreMessage: 'See the changes in App St
60
72
  }
61
73
  }
62
74
  }
63
- _a = MetadataPush;
64
- MetadataPush.description = 'sync the local store configuration to the app stores';
65
- MetadataPush.flags = {
66
- profile: core_1.Flags.string({
67
- char: 'e',
68
- description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
69
- }),
70
- };
71
- MetadataPush.contextDefinition = {
72
- ..._a.ContextOptions.ProjectConfig,
73
- ..._a.ContextOptions.LoggedIn,
74
- ..._a.ContextOptions.Analytics,
75
- ..._a.ContextOptions.Vcs,
76
- };
77
75
  exports.default = MetadataPush;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const better_opn_1 = tslib_1.__importDefault(require("better-opn"));
@@ -8,9 +7,14 @@ const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand
8
7
  const ora_1 = require("../ora");
9
8
  const projectUtils_1 = require("../project/projectUtils");
10
9
  class Open extends EasCommand_1.default {
10
+ static description = 'open the project page in a web browser';
11
+ static contextDefinition = {
12
+ ...this.ContextOptions.ProjectConfig,
13
+ ...this.ContextOptions.LoggedIn,
14
+ };
11
15
  async runAsync() {
12
16
  // this command is interactive by nature (only really run by humans in a terminal)
13
- const { privateProjectConfig: { projectId, exp }, loggedIn: { graphqlClient }, } = await this.getContextAsync(_a, {
17
+ const { privateProjectConfig: { projectId, exp }, loggedIn: { graphqlClient }, } = await this.getContextAsync(Open, {
14
18
  nonInteractive: false,
15
19
  withServerSideEnvironment: null,
16
20
  });
@@ -34,10 +38,4 @@ class Open extends EasCommand_1.default {
34
38
  }
35
39
  }
36
40
  }
37
- _a = Open;
38
- Open.description = 'open the project page in a web browser';
39
- Open.contextDefinition = {
40
- ..._a.ContextOptions.ProjectConfig,
41
- ..._a.ContextOptions.LoggedIn,
42
- };
43
41
  exports.default = Open;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
@@ -23,8 +22,13 @@ async function projectInfoByIdAsync(graphqlClient, appId) {
23
22
  return data;
24
23
  }
25
24
  class ProjectInfo extends EasCommand_1.default {
25
+ static description = 'information about the current project';
26
+ static contextDefinition = {
27
+ ...this.ContextOptions.ProjectId,
28
+ ...this.ContextOptions.LoggedIn,
29
+ };
26
30
  async runAsync() {
27
- const { projectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(_a, {
31
+ const { projectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(ProjectInfo, {
28
32
  nonInteractive: true,
29
33
  });
30
34
  const { app } = await projectInfoByIdAsync(graphqlClient, projectId);
@@ -38,10 +42,4 @@ class ProjectInfo extends EasCommand_1.default {
38
42
  ]));
39
43
  }
40
44
  }
41
- _a = ProjectInfo;
42
- ProjectInfo.description = 'information about the current project';
43
- ProjectInfo.contextDefinition = {
44
- ..._a.ContextOptions.ProjectId,
45
- ..._a.ContextOptions.LoggedIn,
46
- };
47
45
  exports.default = ProjectInfo;
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  const tslib_1 = require("tslib");
5
4
  const config_1 = require("@expo/config");
@@ -17,9 +16,23 @@ const log_1 = tslib_1.__importStar(require("../../log"));
17
16
  const ora_1 = require("../../ora");
18
17
  const expoConfig_1 = require("../../project/expoConfig");
19
18
  const fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1 = require("../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync");
20
- const projectUtils_1 = require("../../project/projectUtils");
21
19
  const prompts_1 = require("../../prompts");
22
20
  class ProjectInit extends EasCommand_1.default {
21
+ static description = 'create or link an EAS project';
22
+ static aliases = ['init'];
23
+ static flags = {
24
+ id: core_1.Flags.string({
25
+ description: 'ID of the EAS project to link',
26
+ }),
27
+ force: core_1.Flags.boolean({
28
+ description: 'Whether to create a new project/link an existing project without additional prompts or overwrite any existing project ID when running with --id flag',
29
+ }),
30
+ ...flags_1.EASNonInteractiveFlag,
31
+ };
32
+ static contextDefinition = {
33
+ ...this.ContextOptions.LoggedIn,
34
+ ...this.ContextOptions.ProjectDir,
35
+ };
23
36
  static async saveProjectIdAndLogSuccessAsync(projectDir, projectId) {
24
37
  await (0, getProjectIdAsync_1.saveProjectIdToAppConfigAsync)(projectDir, projectId);
25
38
  log_1.default.withTick(`Project successfully linked (ID: ${chalk_1.default.bold(projectId)}) (modified app.json)`);
@@ -114,12 +127,12 @@ class ProjectInit extends EasCommand_1.default {
114
127
  return;
115
128
  }
116
129
  if (!existingProjectId) {
117
- await _a.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
130
+ await ProjectInit.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
118
131
  return;
119
132
  }
120
133
  if (projectId !== existingProjectId) {
121
134
  if (force) {
122
- await _a.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
135
+ await ProjectInit.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
123
136
  return;
124
137
  }
125
138
  if (nonInteractive) {
@@ -131,7 +144,7 @@ class ProjectInit extends EasCommand_1.default {
131
144
  if (!confirm) {
132
145
  throw new Error('Aborting');
133
146
  }
134
- await _a.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
147
+ await ProjectInit.saveProjectIdAndLogSuccessAsync(projectDir, projectId);
135
148
  }
136
149
  }
137
150
  static async initializeWithExplicitIDAsync(projectId, projectDir, { force, nonInteractive }) {
@@ -167,7 +180,7 @@ class ProjectInit extends EasCommand_1.default {
167
180
  log_1.default.log(`Using default account ${accountName} for non-interactive and force mode`);
168
181
  }
169
182
  else {
170
- const choices = _a.getAccountChoices(actor, accountNamesWhereUserHasSufficientPermissionsToCreateApp);
183
+ const choices = ProjectInit.getAccountChoices(actor, accountNamesWhereUserHasSufficientPermissionsToCreateApp);
171
184
  accountName = (await (0, prompts_1.promptAsync)({
172
185
  type: 'select',
173
186
  name: 'account',
@@ -194,7 +207,7 @@ class ProjectInit extends EasCommand_1.default {
194
207
  throw new Error(`Project ID configuration canceled. Re-run the command to select a different account/project.`);
195
208
  }
196
209
  }
197
- await _a.saveProjectIdAndLogSuccessAsync(projectDir, existingProjectIdOnServer);
210
+ await ProjectInit.saveProjectIdAndLogSuccessAsync(projectDir, existingProjectIdOnServer);
198
211
  return existingProjectIdOnServer;
199
212
  }
200
213
  if (!accountNamesWhereUserHasSufficientPermissionsToCreateApp.has(accountName)) {
@@ -220,7 +233,6 @@ class ProjectInit extends EasCommand_1.default {
220
233
  createdProjectId = await AppMutation_1.AppMutation.createAppAsync(graphqlClient, {
221
234
  accountId: account.id,
222
235
  projectName,
223
- privacy: (0, projectUtils_1.toAppPrivacy)(exp.privacy) ?? generated_1.AppPrivacy.Public,
224
236
  });
225
237
  spinner.succeed(`Created ${chalk_1.default.bold(projectLink)}`);
226
238
  }
@@ -228,7 +240,7 @@ class ProjectInit extends EasCommand_1.default {
228
240
  spinner.fail();
229
241
  throw err;
230
242
  }
231
- await _a.saveProjectIdAndLogSuccessAsync(projectDir, createdProjectId);
243
+ await ProjectInit.saveProjectIdAndLogSuccessAsync(projectDir, createdProjectId);
232
244
  return createdProjectId;
233
245
  }
234
246
  static getAccountChoices(actor, namesWithSufficientPermissions) {
@@ -278,42 +290,26 @@ class ProjectInit extends EasCommand_1.default {
278
290
  }));
279
291
  }
280
292
  async runAsync() {
281
- const { flags: { id: idArgument, force, 'non-interactive': nonInteractive }, } = await this.parse(_a);
282
- const { loggedIn: { actor, graphqlClient }, projectDir, } = await this.getContextAsync(_a, { nonInteractive });
293
+ const { flags: { id: idArgument, force, 'non-interactive': nonInteractive }, } = await this.parse(ProjectInit);
294
+ const { loggedIn: { actor, graphqlClient }, projectDir, } = await this.getContextAsync(ProjectInit, { nonInteractive });
283
295
  let idForConsistency;
284
296
  if (idArgument) {
285
- await _a.initializeWithExplicitIDAsync(idArgument, projectDir, {
297
+ await ProjectInit.initializeWithExplicitIDAsync(idArgument, projectDir, {
286
298
  force,
287
299
  nonInteractive,
288
300
  });
289
301
  idForConsistency = idArgument;
290
302
  }
291
303
  else {
292
- idForConsistency = await _a.initializeWithoutExplicitIDAsync(graphqlClient, actor, projectDir, {
304
+ idForConsistency = await ProjectInit.initializeWithoutExplicitIDAsync(graphqlClient, actor, projectDir, {
293
305
  force,
294
306
  nonInteractive,
295
307
  });
296
308
  }
297
- await _a.ensureOwnerSlugConsistencyAsync(graphqlClient, idForConsistency, projectDir, {
309
+ await ProjectInit.ensureOwnerSlugConsistencyAsync(graphqlClient, idForConsistency, projectDir, {
298
310
  force,
299
311
  nonInteractive,
300
312
  });
301
313
  }
302
314
  }
303
- _a = ProjectInit;
304
- ProjectInit.description = 'create or link an EAS project';
305
- ProjectInit.aliases = ['init'];
306
- ProjectInit.flags = {
307
- id: core_1.Flags.string({
308
- description: 'ID of the EAS project to link',
309
- }),
310
- force: core_1.Flags.boolean({
311
- description: 'Whether to create a new project/link an existing project without additional prompts or overwrite any existing project ID when running with --id flag',
312
- }),
313
- ...flags_1.EASNonInteractiveFlag,
314
- };
315
- ProjectInit.contextDefinition = {
316
- ..._a.ContextOptions.LoggedIn,
317
- ..._a.ContextOptions.ProjectDir,
318
- };
319
315
  exports.default = ProjectInit;