eas-cli 16.13.4 → 16.14.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.
@@ -7,54 +7,6 @@ const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
7
7
  const client_1 = require("../client");
8
8
  const EnvironmentVariable_1 = require("../types/EnvironmentVariable");
9
9
  exports.EnvironmentVariableMutation = {
10
- async linkSharedEnvironmentVariableAsync(graphqlClient, environmentVariableId, appId, environment) {
11
- const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
12
- .mutation((0, graphql_tag_1.default) `
13
- mutation LinkSharedEnvironmentVariable(
14
- $appId: ID!
15
- $environment: EnvironmentVariableEnvironment
16
- $environmentVariableId: ID!
17
- ) {
18
- environmentVariable {
19
- linkSharedEnvironmentVariable(
20
- appId: $appId
21
- environmentVariableId: $environmentVariableId
22
- environment: $environment
23
- ) {
24
- id
25
- ...EnvironmentVariableFragment
26
- }
27
- }
28
- }
29
- ${(0, graphql_1.print)(EnvironmentVariable_1.EnvironmentVariableFragmentNode)}
30
- `, { appId, environment, environmentVariableId })
31
- .toPromise());
32
- return data.environmentVariable.linkSharedEnvironmentVariable;
33
- },
34
- async unlinkSharedEnvironmentVariableAsync(graphqlClient, environmentVariableId, appId, environment) {
35
- const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
36
- .mutation((0, graphql_tag_1.default) `
37
- mutation UnlinkSharedEnvironmentVariable(
38
- $appId: ID!
39
- $environment: EnvironmentVariableEnvironment
40
- $environmentVariableId: ID!
41
- ) {
42
- environmentVariable {
43
- unlinkSharedEnvironmentVariable(
44
- appId: $appId
45
- environmentVariableId: $environmentVariableId
46
- environment: $environment
47
- ) {
48
- id
49
- ...EnvironmentVariableFragment
50
- }
51
- }
52
- }
53
- ${(0, graphql_1.print)(EnvironmentVariable_1.EnvironmentVariableFragmentNode)}
54
- `, { appId, environment, environmentVariableId })
55
- .toPromise());
56
- return data.environmentVariable.unlinkSharedEnvironmentVariable;
57
- },
58
10
  async createSharedVariableAsync(graphqlClient, input, accountId) {
59
11
  const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
60
12
  .mutation((0, graphql_tag_1.default) `
@@ -39,6 +39,7 @@ exports.UpdateFragmentNode = (0, graphql_tag_1.default) `
39
39
  rolloutPercentage
40
40
  rolloutControlUpdate {
41
41
  id
42
+ group
42
43
  }
43
44
  fingerprint {
44
45
  id
@@ -644,6 +644,7 @@ async function getRuntimeToUpdateRolloutInfoGroupMappingAsync(graphqlClient, { a
644
644
  }
645
645
  exports.getRuntimeToUpdateRolloutInfoGroupMappingAsync = getRuntimeToUpdateRolloutInfoGroupMappingAsync;
646
646
  async function getUpdateRolloutInfoGroupAsync(graphqlClient, { appId, branchName, rolloutPercentage, runtimeVersion, platforms, }) {
647
+ // note that this could return control updates in different update groups if the update groups only have a single platform
647
648
  return Object.fromEntries(await Promise.all(platforms.map(async (platform) => {
648
649
  const updateIdForPlatform = await BranchQuery_1.BranchQuery.getLatestUpdateIdOnBranchAsync(graphqlClient, {
649
650
  appId,
@@ -0,0 +1,5 @@
1
+ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
2
+ import { BackgroundJobReceiptDataFragment } from '../graphql/generated';
3
+ export declare function scheduleUpdateGroupDeletionAsync(graphqlClient: ExpoGraphqlClient, { group, }: {
4
+ group: string;
5
+ }): Promise<BackgroundJobReceiptDataFragment>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scheduleUpdateGroupDeletionAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
6
+ const client_1 = require("../graphql/client");
7
+ const BackgroundJobReceipt_1 = require("../graphql/types/BackgroundJobReceipt");
8
+ async function scheduleUpdateGroupDeletionAsync(graphqlClient, { group, }) {
9
+ const result = await (0, client_1.withErrorHandlingAsync)(graphqlClient
10
+ .mutation((0, graphql_tag_1.default) `
11
+ mutation ScheduleUpdateGroupDeletion($group: ID!) {
12
+ update {
13
+ scheduleUpdateGroupDeletion(group: $group) {
14
+ id
15
+ ...BackgroundJobReceiptData
16
+ }
17
+ }
18
+ }
19
+ ${BackgroundJobReceipt_1.BackgroundJobReceiptNode}
20
+ `, { group })
21
+ .toPromise());
22
+ return result.update.scheduleUpdateGroupDeletion;
23
+ }
24
+ exports.scheduleUpdateGroupDeletionAsync = scheduleUpdateGroupDeletionAsync;
@@ -1,8 +1,10 @@
1
1
  import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
2
2
  import { PaginatedQueryOptions } from '../commandUtils/pagination';
3
- import { UpdateFragment } from '../graphql/generated';
3
+ import { RuntimeFragment, UpdateFragment } from '../graphql/generated';
4
+ import { UpdatePublishPlatform } from '../project/publish';
4
5
  export declare const UPDATES_LIMIT = 50;
5
6
  export declare const UPDATE_GROUPS_LIMIT = 25;
7
+ export declare const RUNTIME_VERSIONS_LIMIT = 25;
6
8
  export declare function listAndRenderUpdateGroupsOnAppAsync(graphqlClient: ExpoGraphqlClient, { projectId, paginatedQueryOptions, }: {
7
9
  projectId: string;
8
10
  paginatedQueryOptions: PaginatedQueryOptions;
@@ -12,8 +14,18 @@ export declare function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient: Ex
12
14
  branchName: string;
13
15
  paginatedQueryOptions: PaginatedQueryOptions;
14
16
  }): Promise<void>;
17
+ export declare function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(graphqlClient: ExpoGraphqlClient, { projectId, branchName, paginatedQueryOptions, }: {
18
+ projectId: string;
19
+ branchName: string;
20
+ paginatedQueryOptions: PaginatedQueryOptions;
21
+ }): Promise<Record<UpdatePublishPlatform, UpdateFragment[] | undefined>>;
15
22
  export declare function selectUpdateGroupOnBranchAsync(graphqlClient: ExpoGraphqlClient, { projectId, branchName, paginatedQueryOptions, }: {
16
23
  projectId: string;
17
24
  branchName: string;
18
25
  paginatedQueryOptions: PaginatedQueryOptions;
19
26
  }): Promise<UpdateFragment[]>;
27
+ export declare function selectRuntimeOnBranchAsync(graphqlClient: ExpoGraphqlClient, { appId, branchName, batchSize, }: {
28
+ appId: string;
29
+ branchName: string;
30
+ batchSize?: number;
31
+ }): Promise<RuntimeFragment | null>;
@@ -1,17 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.selectUpdateGroupOnBranchAsync = exports.listAndRenderUpdateGroupsOnBranchAsync = exports.listAndRenderUpdateGroupsOnAppAsync = exports.UPDATE_GROUPS_LIMIT = exports.UPDATES_LIMIT = void 0;
3
+ exports.selectRuntimeOnBranchAsync = exports.selectUpdateGroupOnBranchAsync = exports.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync = exports.listAndRenderUpdateGroupsOnBranchAsync = exports.listAndRenderUpdateGroupsOnAppAsync = exports.RUNTIME_VERSIONS_LIMIT = exports.UPDATE_GROUPS_LIMIT = exports.UPDATES_LIMIT = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const utils_1 = require("./utils");
8
+ const generated_1 = require("../graphql/generated");
9
+ const RuntimeQuery_1 = require("../graphql/queries/RuntimeQuery");
8
10
  const UpdateQuery_1 = require("../graphql/queries/UpdateQuery");
9
11
  const log_1 = tslib_1.__importDefault(require("../log"));
10
12
  const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
11
13
  const json_1 = require("../utils/json");
12
14
  const queries_1 = require("../utils/queries");
15
+ const relay_1 = require("../utils/relay");
13
16
  exports.UPDATES_LIMIT = 50;
14
17
  exports.UPDATE_GROUPS_LIMIT = 25;
18
+ exports.RUNTIME_VERSIONS_LIMIT = 25;
15
19
  async function listAndRenderUpdateGroupsOnAppAsync(graphqlClient, { projectId, paginatedQueryOptions, }) {
16
20
  if (paginatedQueryOptions.nonInteractive) {
17
21
  const updateGroups = await queryUpdateGroupsOnAppAsync(graphqlClient, {
@@ -66,6 +70,41 @@ async function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, { projectId
66
70
  }
67
71
  }
68
72
  exports.listAndRenderUpdateGroupsOnBranchAsync = listAndRenderUpdateGroupsOnBranchAsync;
73
+ async function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
74
+ if (paginatedQueryOptions.nonInteractive) {
75
+ throw new Error('Unable to select an update in non-interactive mode.');
76
+ }
77
+ const runtimeVersion = await selectRuntimeOnBranchAsync(graphqlClient, {
78
+ appId: projectId,
79
+ branchName,
80
+ });
81
+ if (!runtimeVersion) {
82
+ throw new Error('No runtime version selected.');
83
+ }
84
+ return {
85
+ ios: (await queryUpdateGroupsOnBranchAsync(graphqlClient, {
86
+ appId: projectId,
87
+ branchName,
88
+ limit: 1,
89
+ offset: 0,
90
+ filter: {
91
+ runtimeVersions: [runtimeVersion.version],
92
+ platform: generated_1.AppPlatform.Ios,
93
+ },
94
+ }))[0],
95
+ android: (await queryUpdateGroupsOnBranchAsync(graphqlClient, {
96
+ appId: projectId,
97
+ branchName,
98
+ limit: 1,
99
+ offset: 0,
100
+ filter: {
101
+ runtimeVersions: [runtimeVersion.version],
102
+ platform: generated_1.AppPlatform.Android,
103
+ },
104
+ }))[0],
105
+ };
106
+ }
107
+ exports.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync = selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync;
69
108
  async function selectUpdateGroupOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
70
109
  if (paginatedQueryOptions.nonInteractive) {
71
110
  throw new Error('Unable to select an update in non-interactive mode.');
@@ -140,3 +179,25 @@ function renderUpdateGroupsOnApp({ updateGroups, paginatedQueryOptions: { json }
140
179
  }))
141
180
  .join(`\n\n${chalk_1.default.dim('———')}\n\n`));
142
181
  }
182
+ async function selectRuntimeOnBranchAsync(graphqlClient, { appId, branchName, batchSize = 5, }) {
183
+ const queryAsync = async (queryParams) => {
184
+ return await RuntimeQuery_1.RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
185
+ appId,
186
+ name: branchName,
187
+ first: queryParams.first,
188
+ after: queryParams.after,
189
+ last: queryParams.last,
190
+ before: queryParams.before,
191
+ });
192
+ };
193
+ const getTitleAsync = async (runtime) => {
194
+ return runtime.version;
195
+ };
196
+ return await (0, relay_1.selectPaginatedAsync)({
197
+ queryAsync,
198
+ getTitleAsync,
199
+ printedType: 'target runtime',
200
+ pageSize: batchSize,
201
+ });
202
+ }
203
+ exports.selectRuntimeOnBranchAsync = selectRuntimeOnBranchAsync;
@@ -1,6 +1,7 @@
1
1
  import { ExpoConfig } from '@expo/config';
2
2
  import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
3
3
  import { UpdateFragment } from '../graphql/generated';
4
+ import { UpdatePublishPlatform } from '../project/publish';
4
5
  import { CodeSigningInfo } from '../utils/code-signing';
5
6
  export type UpdateToRepublish = {
6
7
  groupId: string;
@@ -27,3 +28,29 @@ export declare function republishAsync({ graphqlClient, app, updatesToPublish, t
27
28
  json?: boolean;
28
29
  rolloutPercentage?: number;
29
30
  }): Promise<void>;
31
+ type GetUpdateOrAskForUpdatesOptions = {
32
+ nonInteractive: boolean;
33
+ json: boolean;
34
+ groupId?: string;
35
+ branchName?: string;
36
+ channelName?: string;
37
+ };
38
+ export declare function getUpdateGroupAsync(graphqlClient: ExpoGraphqlClient, groupId: string): Promise<UpdateToRepublish[]>;
39
+ type AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions = {
40
+ nonInteractive: boolean;
41
+ json: boolean;
42
+ branchName?: string;
43
+ channelName?: string;
44
+ };
45
+ export declare function askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(graphqlClient: ExpoGraphqlClient, projectId: string, options: AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions): Promise<Record<UpdatePublishPlatform, UpdateToRepublish[] | undefined>>;
46
+ export declare function getUpdateGroupOrAskForUpdateGroupAsync(graphqlClient: ExpoGraphqlClient, projectId: string, options: GetUpdateOrAskForUpdatesOptions): Promise<UpdateToRepublish[]>;
47
+ type GetOrAskUpdateMessageOptions = {
48
+ updateMessage?: string;
49
+ nonInteractive: boolean;
50
+ json: boolean;
51
+ };
52
+ /**
53
+ * Get or ask the user for the update (group) message for the republish
54
+ */
55
+ export declare function getOrAskUpdateMessageAsync(updateGroup: UpdateToRepublish[], options: GetOrAskUpdateMessageOptions): Promise<string>;
56
+ export {};
@@ -1,16 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.republishAsync = void 0;
3
+ exports.getOrAskUpdateMessageAsync = exports.getUpdateGroupOrAskForUpdateGroupAsync = exports.askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync = exports.getUpdateGroupAsync = exports.republishAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
7
+ const getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1 = require("./getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync");
8
+ const queries_1 = require("./queries");
9
+ const utils_1 = require("./utils");
10
+ const queries_2 = require("../branch/queries");
7
11
  const url_1 = require("../build/utils/url");
12
+ const queries_3 = require("../channel/queries");
13
+ const pagination_1 = require("../commandUtils/pagination");
8
14
  const fetch_1 = tslib_1.__importDefault(require("../fetch"));
9
15
  const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
16
+ const UpdateQuery_1 = require("../graphql/queries/UpdateQuery");
10
17
  const log_1 = tslib_1.__importStar(require("../log"));
11
18
  const ora_1 = require("../ora");
12
19
  const projectUtils_1 = require("../project/projectUtils");
13
20
  const publish_1 = require("../project/publish");
21
+ const prompts_1 = require("../prompts");
14
22
  const code_signing_1 = require("../utils/code-signing");
15
23
  const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
16
24
  const json_1 = require("../utils/json");
@@ -174,3 +182,236 @@ async function republishAsync({ graphqlClient, app, updatesToPublish, targetBran
174
182
  ]));
175
183
  }
176
184
  exports.republishAsync = republishAsync;
185
+ async function getUpdateGroupAsync(graphqlClient, groupId) {
186
+ const updateGroup = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
187
+ groupId,
188
+ });
189
+ return updateGroup.map(update => ({
190
+ ...update,
191
+ groupId: update.group,
192
+ branchId: update.branch.id,
193
+ branchName: update.branch.name,
194
+ }));
195
+ }
196
+ exports.getUpdateGroupAsync = getUpdateGroupAsync;
197
+ async function askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(graphqlClient, projectId, options) {
198
+ if (options.nonInteractive) {
199
+ throw new Error('Must supply --group when in non-interactive mode');
200
+ }
201
+ if (options.branchName) {
202
+ return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
203
+ ...options,
204
+ branchName: options.branchName,
205
+ projectId,
206
+ });
207
+ }
208
+ if (options.channelName) {
209
+ return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, {
210
+ ...options,
211
+ channelName: options.channelName,
212
+ projectId,
213
+ });
214
+ }
215
+ const { choice } = await (0, prompts_1.promptAsync)({
216
+ type: 'select',
217
+ message: 'Find update by branch or channel?',
218
+ name: 'choice',
219
+ choices: [
220
+ { title: 'Branch', value: 'branch' },
221
+ { title: 'Channel', value: 'channel' },
222
+ ],
223
+ });
224
+ if (choice === 'channel') {
225
+ const { name } = await (0, queries_3.selectChannelOnAppAsync)(graphqlClient, {
226
+ projectId,
227
+ selectionPromptTitle: 'Select a channel to view',
228
+ paginatedQueryOptions: {
229
+ json: options.json,
230
+ nonInteractive: options.nonInteractive,
231
+ offset: 0,
232
+ },
233
+ });
234
+ return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, {
235
+ ...options,
236
+ channelName: name,
237
+ projectId,
238
+ });
239
+ }
240
+ else if (choice === 'branch') {
241
+ const { name } = await (0, queries_2.selectBranchOnAppAsync)(graphqlClient, {
242
+ projectId,
243
+ promptTitle: 'Select branch from which to choose update',
244
+ displayTextForListItem: updateBranch => ({
245
+ title: updateBranch.name,
246
+ }),
247
+ // discard limit and offset because this query is not their intended target
248
+ paginatedQueryOptions: {
249
+ json: options.json,
250
+ nonInteractive: options.nonInteractive,
251
+ offset: 0,
252
+ },
253
+ });
254
+ return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
255
+ ...options,
256
+ branchName: name,
257
+ projectId,
258
+ });
259
+ }
260
+ else {
261
+ throw new Error('Must choose update via channel or branch');
262
+ }
263
+ }
264
+ exports.askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync = askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync;
265
+ async function getUpdateGroupOrAskForUpdateGroupAsync(graphqlClient, projectId, options) {
266
+ if (options.groupId) {
267
+ return await getUpdateGroupAsync(graphqlClient, options.groupId);
268
+ }
269
+ if (options.nonInteractive) {
270
+ throw new Error('Must supply --group when in non-interactive mode');
271
+ }
272
+ if (options.branchName) {
273
+ return await askUpdatesFromBranchNameAsync(graphqlClient, {
274
+ ...options,
275
+ branchName: options.branchName,
276
+ projectId,
277
+ });
278
+ }
279
+ if (options.channelName) {
280
+ return await askUpdatesFromChannelNameAsync(graphqlClient, {
281
+ ...options,
282
+ channelName: options.channelName,
283
+ projectId,
284
+ });
285
+ }
286
+ const { choice } = await (0, prompts_1.promptAsync)({
287
+ type: 'select',
288
+ message: 'Find update by branch or channel?',
289
+ name: 'choice',
290
+ choices: [
291
+ { title: 'Branch', value: 'branch' },
292
+ { title: 'Channel', value: 'channel' },
293
+ ],
294
+ });
295
+ if (choice === 'channel') {
296
+ const { name } = await (0, queries_3.selectChannelOnAppAsync)(graphqlClient, {
297
+ projectId,
298
+ selectionPromptTitle: 'Select a channel to view',
299
+ paginatedQueryOptions: {
300
+ json: options.json,
301
+ nonInteractive: options.nonInteractive,
302
+ offset: 0,
303
+ },
304
+ });
305
+ return await askUpdatesFromChannelNameAsync(graphqlClient, {
306
+ ...options,
307
+ channelName: name,
308
+ projectId,
309
+ });
310
+ }
311
+ else if (choice === 'branch') {
312
+ const { name } = await (0, queries_2.selectBranchOnAppAsync)(graphqlClient, {
313
+ projectId,
314
+ promptTitle: 'Select branch from which to choose update',
315
+ displayTextForListItem: updateBranch => ({
316
+ title: updateBranch.name,
317
+ }),
318
+ // discard limit and offset because this query is not their intended target
319
+ paginatedQueryOptions: {
320
+ json: options.json,
321
+ nonInteractive: options.nonInteractive,
322
+ offset: 0,
323
+ },
324
+ });
325
+ return await askUpdatesFromBranchNameAsync(graphqlClient, {
326
+ ...options,
327
+ branchName: name,
328
+ projectId,
329
+ });
330
+ }
331
+ else {
332
+ throw new Error('Must choose update via channel or branch');
333
+ }
334
+ }
335
+ exports.getUpdateGroupOrAskForUpdateGroupAsync = getUpdateGroupOrAskForUpdateGroupAsync;
336
+ async function askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
337
+ const publishPlatformToLatestUpdateGroup = await (0, queries_1.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync)(graphqlClient, {
338
+ projectId,
339
+ branchName,
340
+ paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
341
+ });
342
+ return {
343
+ ios: publishPlatformToLatestUpdateGroup.ios?.map(update => ({
344
+ ...update,
345
+ groupId: update.group,
346
+ branchId: update.branch.id,
347
+ branchName: update.branch.name,
348
+ })),
349
+ android: publishPlatformToLatestUpdateGroup.android?.map(update => ({
350
+ ...update,
351
+ groupId: update.group,
352
+ branchId: update.branch.id,
353
+ branchName: update.branch.name,
354
+ })),
355
+ };
356
+ }
357
+ async function askUpdatesFromBranchNameAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
358
+ const updateGroup = await (0, queries_1.selectUpdateGroupOnBranchAsync)(graphqlClient, {
359
+ projectId,
360
+ branchName,
361
+ paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
362
+ });
363
+ return updateGroup.map(update => ({
364
+ ...update,
365
+ groupId: update.group,
366
+ branchId: update.branch.id,
367
+ branchName: update.branch.name,
368
+ }));
369
+ }
370
+ async function askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, { projectId, channelName, json, nonInteractive, }) {
371
+ const { branchName } = await (0, getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1.getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)(graphqlClient, projectId, channelName);
372
+ return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
373
+ projectId,
374
+ branchName,
375
+ json,
376
+ nonInteractive,
377
+ });
378
+ }
379
+ async function askUpdatesFromChannelNameAsync(graphqlClient, { projectId, channelName, json, nonInteractive, }) {
380
+ const { branchName } = await (0, getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1.getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)(graphqlClient, projectId, channelName);
381
+ return await askUpdatesFromBranchNameAsync(graphqlClient, {
382
+ projectId,
383
+ branchName,
384
+ json,
385
+ nonInteractive,
386
+ });
387
+ }
388
+ /**
389
+ * Get or ask the user for the update (group) message for the republish
390
+ */
391
+ async function getOrAskUpdateMessageAsync(updateGroup, options) {
392
+ if (options.updateMessage) {
393
+ return sanitizeUpdateMessage(options.updateMessage);
394
+ }
395
+ if (options.nonInteractive || options.json) {
396
+ throw new Error('Must supply --message when in non-interactive mode');
397
+ }
398
+ // This command only uses a single update group to republish, meaning these values are always identical
399
+ const oldGroupId = updateGroup[0].groupId;
400
+ const oldUpdateMessage = updateGroup[0].message;
401
+ const { updateMessage } = await (0, prompts_1.promptAsync)({
402
+ type: 'text',
403
+ name: 'updateMessage',
404
+ message: 'Provide an update message.',
405
+ initial: `Republish "${oldUpdateMessage}" - group: ${oldGroupId}`,
406
+ validate: (value) => (value ? true : 'Update message may not be empty.'),
407
+ });
408
+ return sanitizeUpdateMessage(updateMessage);
409
+ }
410
+ exports.getOrAskUpdateMessageAsync = getOrAskUpdateMessageAsync;
411
+ function sanitizeUpdateMessage(updateMessage) {
412
+ if (updateMessage !== (0, utils_1.truncateString)(updateMessage, 1024)) {
413
+ log_1.default.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
414
+ return (0, utils_1.truncateString)(updateMessage, 1024);
415
+ }
416
+ return updateMessage;
417
+ }
@@ -0,0 +1,18 @@
1
+ import { ExpoConfig } from '@expo/config';
2
+ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
3
+ import { UpdatePublishPlatform } from '../project/publish';
4
+ import { CodeSigningInfo } from '../utils/code-signing';
5
+ export declare function publishRollBackToEmbeddedUpdateAsync({ graphqlClient, projectId, exp, updateMessage, branch, codeSigningInfo, platforms, runtimeVersion, json, }: {
6
+ graphqlClient: ExpoGraphqlClient;
7
+ projectId: string;
8
+ exp: ExpoConfig;
9
+ updateMessage: string | undefined;
10
+ branch: {
11
+ name: string;
12
+ id: string;
13
+ };
14
+ codeSigningInfo: CodeSigningInfo | undefined;
15
+ platforms: UpdatePublishPlatform[];
16
+ runtimeVersion: string;
17
+ json: boolean;
18
+ }): Promise<void>;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishRollBackToEmbeddedUpdateAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
6
+ const utils_1 = require("./utils");
7
+ const url_1 = require("../build/utils/url");
8
+ const fetch_1 = tslib_1.__importDefault(require("../fetch"));
9
+ const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
10
+ const log_1 = tslib_1.__importStar(require("../log"));
11
+ const ora_1 = require("../ora");
12
+ const projectUtils_1 = require("../project/projectUtils");
13
+ const publish_1 = require("../project/publish");
14
+ const code_signing_1 = require("../utils/code-signing");
15
+ const uniqBy_1 = tslib_1.__importDefault(require("../utils/expodash/uniqBy"));
16
+ const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
17
+ const json_1 = require("../utils/json");
18
+ async function publishRollBackToEmbeddedUpdateAsync({ graphqlClient, projectId, exp, updateMessage, branch, codeSigningInfo, platforms, runtimeVersion, json, }) {
19
+ const runtimeToPlatformsAndFingerprintInfoMapping = (0, publish_1.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects)(platforms.map(platform => ({
20
+ platform,
21
+ runtimeVersionInfo: {
22
+ runtimeVersion,
23
+ expoUpdatesRuntimeFingerprint: null,
24
+ expoUpdatesRuntimeFingerprintHash: null,
25
+ },
26
+ })));
27
+ let newUpdates;
28
+ const publishSpinner = (0, ora_1.ora)('Publishing...').start();
29
+ try {
30
+ newUpdates = await publishRollbacksAsync({
31
+ graphqlClient,
32
+ updateMessage,
33
+ branchId: branch.id,
34
+ codeSigningInfo,
35
+ runtimeToPlatformsAndFingerprintInfoMapping,
36
+ platforms,
37
+ });
38
+ publishSpinner.succeed('Published!');
39
+ }
40
+ catch (e) {
41
+ publishSpinner.fail('Failed to publish updates');
42
+ throw e;
43
+ }
44
+ if (json) {
45
+ (0, json_1.printJsonOnlyOutput)((0, utils_1.getUpdateJsonInfosForUpdates)(newUpdates));
46
+ }
47
+ else {
48
+ log_1.default.addNewLineIfNone();
49
+ for (const runtime of (0, uniqBy_1.default)(runtimeToPlatformsAndFingerprintInfoMapping, version => version.runtimeVersion)) {
50
+ const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
51
+ if (newUpdatesForRuntimeVersion.length === 0) {
52
+ throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
53
+ }
54
+ const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
55
+ const newAndroidUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'android');
56
+ const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
57
+ const updateGroupId = newUpdatesForRuntimeVersion[0].group;
58
+ const projectName = exp.slug;
59
+ const accountName = (await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId)).name;
60
+ const updateGroupUrl = (0, url_1.getUpdateGroupUrl)(accountName, projectName, updateGroupId);
61
+ const updateGroupLink = (0, log_1.link)(updateGroupUrl, { dim: false });
62
+ log_1.default.log((0, formatFields_1.default)([
63
+ { label: 'Branch', value: branch.name },
64
+ { label: 'Runtime version', value: runtime.runtimeVersion },
65
+ { label: 'Platform', value: platforms.join(', ') },
66
+ { label: 'Update group ID', value: updateGroupId },
67
+ ...(newAndroidUpdate ? [{ label: 'Android update ID', value: newAndroidUpdate.id }] : []),
68
+ ...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
69
+ { label: 'Message', value: updateMessage ?? '' },
70
+ { label: 'EAS Dashboard', value: updateGroupLink },
71
+ ]));
72
+ log_1.default.addNewLineIfNone();
73
+ }
74
+ }
75
+ }
76
+ exports.publishRollBackToEmbeddedUpdateAsync = publishRollBackToEmbeddedUpdateAsync;
77
+ async function publishRollbacksAsync({ graphqlClient, updateMessage, branchId, codeSigningInfo, runtimeToPlatformsAndFingerprintInfoMapping, platforms, }) {
78
+ const rollbackInfoGroups = Object.fromEntries(platforms.map(platform => [platform, true]));
79
+ // Sort the updates into different groups based on their platform specific runtime versions
80
+ const updateGroups = runtimeToPlatformsAndFingerprintInfoMapping.map(({ runtimeVersion, platforms }) => {
81
+ const localRollbackInfoGroup = Object.fromEntries(platforms.map(platform => [platform, rollbackInfoGroups[platform]]));
82
+ return {
83
+ branchId,
84
+ rollBackToEmbeddedInfoGroup: localRollbackInfoGroup,
85
+ runtimeVersion,
86
+ message: updateMessage,
87
+ awaitingCodeSigningInfo: !!codeSigningInfo,
88
+ };
89
+ });
90
+ const newUpdates = await PublishMutation_1.PublishMutation.publishUpdateGroupAsync(graphqlClient, updateGroups);
91
+ if (codeSigningInfo) {
92
+ log_1.default.log('🔒 Signing roll back');
93
+ const updatesTemp = [...newUpdates];
94
+ const updateGroupsAndTheirUpdates = updateGroups.map(updateGroup => {
95
+ const newUpdates = updatesTemp.splice(0, Object.keys((0, nullthrows_1.default)(updateGroup.rollBackToEmbeddedInfoGroup)).length);
96
+ return {
97
+ updateGroup,
98
+ newUpdates,
99
+ };
100
+ });
101
+ await Promise.all(updateGroupsAndTheirUpdates.map(async ({ newUpdates }) => {
102
+ await Promise.all(newUpdates.map(async (newUpdate) => {
103
+ const response = await (0, fetch_1.default)(newUpdate.manifestPermalink, {
104
+ method: 'GET',
105
+ headers: { accept: 'multipart/mixed' },
106
+ });
107
+ const directiveBody = (0, nullthrows_1.default)(await (0, code_signing_1.getDirectiveBodyAsync)(response));
108
+ (0, code_signing_1.checkDirectiveBodyAgainstUpdateInfoGroup)(directiveBody);
109
+ const directiveSignature = (0, code_signing_1.signBody)(directiveBody, codeSigningInfo);
110
+ await PublishMutation_1.PublishMutation.setCodeSigningInfoAsync(graphqlClient, newUpdate.id, {
111
+ alg: codeSigningInfo.codeSigningMetadata.alg,
112
+ keyid: codeSigningInfo.codeSigningMetadata.keyid,
113
+ sig: directiveSignature,
114
+ });
115
+ }));
116
+ }));
117
+ }
118
+ return newUpdates;
119
+ }