eas-cli 16.23.0 → 16.24.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 (34) hide show
  1. package/README.md +87 -87
  2. package/build/commandUtils/new/commands.d.ts +4 -0
  3. package/build/commandUtils/new/commands.js +61 -0
  4. package/build/commandUtils/new/configs.d.ts +25 -0
  5. package/build/commandUtils/new/configs.js +136 -0
  6. package/build/commandUtils/new/projectFiles.d.ts +8 -0
  7. package/build/commandUtils/new/projectFiles.js +167 -0
  8. package/build/commandUtils/new/templates/.eas/workflows/create-development-builds.yml +21 -0
  9. package/build/commandUtils/new/templates/.eas/workflows/deploy-to-production.yml +68 -0
  10. package/build/commandUtils/new/templates/.eas/workflows/publish-preview-update.yml +12 -0
  11. package/build/commandUtils/new/templates/readme-additions.md +36 -0
  12. package/build/commandUtils/workflow/fetchLogs.d.ts +5 -1
  13. package/build/commandUtils/workflow/fetchLogs.js +23 -3
  14. package/build/commandUtils/workflow/inputs.d.ts +40 -0
  15. package/build/commandUtils/workflow/inputs.js +165 -0
  16. package/build/commandUtils/workflow/stateMachine.js +1 -1
  17. package/build/commandUtils/workflow/types.d.ts +1 -0
  18. package/build/commandUtils/workflow/types.js +1 -1
  19. package/build/commandUtils/workflow/utils.d.ts +15 -4
  20. package/build/commandUtils/workflow/utils.js +148 -10
  21. package/build/commands/project/new.d.ts +21 -17
  22. package/build/commands/project/new.js +62 -291
  23. package/build/commands/workflow/run.d.ts +0 -25
  24. package/build/commands/workflow/run.js +32 -230
  25. package/build/credentials/ios/types.d.ts +3 -0
  26. package/build/credentials/ios/types.js +35 -0
  27. package/build/graphql/generated.d.ts +80 -2
  28. package/build/graphql/types/Build.js +1 -0
  29. package/build/onboarding/installDependencies.d.ts +4 -2
  30. package/build/onboarding/installDependencies.js +5 -7
  31. package/build/onboarding/runCommand.d.ts +2 -1
  32. package/build/onboarding/runCommand.js +24 -22
  33. package/oclif.manifest.json +24 -6
  34. package/package.json +7 -6
@@ -41,20 +41,18 @@
41
41
  * ```
42
42
  */
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.parseWorkflowInputsFromYaml = exports.WorkflowDispatchInputZ = exports.parseJsonInputs = exports.maybeReadStdinAsync = exports.parseInputs = void 0;
45
44
  const tslib_1 = require("tslib");
46
45
  const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
47
46
  const core_1 = require("@oclif/core");
48
47
  const core_2 = require("@urql/core");
49
48
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
50
- const fs = tslib_1.__importStar(require("node:fs"));
51
49
  const path = tslib_1.__importStar(require("node:path"));
52
50
  const slash_1 = tslib_1.__importDefault(require("slash"));
53
- const YAML = tslib_1.__importStar(require("yaml"));
54
- const zod_1 = require("zod");
55
51
  const url_1 = require("../../build/utils/url");
56
52
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
57
53
  const flags_1 = require("../../commandUtils/flags");
54
+ const inputs_1 = require("../../commandUtils/workflow/inputs");
55
+ const utils_1 = require("../../commandUtils/workflow/utils");
58
56
  const generated_1 = require("../../graphql/generated");
59
57
  const WorkflowRevisionMutation_1 = require("../../graphql/mutations/WorkflowRevisionMutation");
60
58
  const WorkflowRunMutation_1 = require("../../graphql/mutations/WorkflowRunMutation");
@@ -64,7 +62,6 @@ const ora_1 = require("../../ora");
64
62
  const projectUtils_1 = require("../../project/projectUtils");
65
63
  const uploadAccountScopedFileAsync_1 = require("../../project/uploadAccountScopedFileAsync");
66
64
  const uploadAccountScopedProjectSourceAsync_1 = require("../../project/uploadAccountScopedProjectSourceAsync");
67
- const prompts_1 = require("../../prompts");
68
65
  const json_1 = require("../../utils/json");
69
66
  const promise_1 = require("../../utils/promise");
70
67
  const workflowFile_1 = require("../../utils/workflowFile");
@@ -82,7 +79,7 @@ class WorkflowRun extends EasCommand_1.default {
82
79
  default: false,
83
80
  allowNo: true,
84
81
  description: 'Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.',
85
- summary: 'Wait for workflow run to complete',
82
+ summary: 'Wait for workflow run to complete. Defaults to false. Cannot be used with the --json flag.',
86
83
  }),
87
84
  input: core_1.Flags.string({
88
85
  char: 'F',
@@ -106,6 +103,9 @@ class WorkflowRun extends EasCommand_1.default {
106
103
  async runAsync() {
107
104
  const { flags, args } = await this.parse(WorkflowRun);
108
105
  if (flags.json) {
106
+ if (flags.wait) {
107
+ throw new Error('Cannot use --json and --wait flags simultaneously.');
108
+ }
109
109
  (0, json_1.enableJsonOutput)();
110
110
  }
111
111
  const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, vcsClient, projectDir, } = await this.getContextAsync(WorkflowRun, {
@@ -179,22 +179,22 @@ class WorkflowRun extends EasCommand_1.default {
179
179
  }
180
180
  let inputs;
181
181
  // Check for stdin input
182
- const stdinData = await maybeReadStdinAsync();
182
+ const stdinData = await (0, utils_1.maybeReadStdinAsync)();
183
183
  const inputsFromFlags = [...(flags.input ?? [])];
184
184
  // Validate that both stdin and -F flags are not provided simultaneously
185
185
  if (stdinData && inputsFromFlags.length > 0) {
186
186
  throw new Error('Cannot use both stdin JSON input and -F flags simultaneously. Please use only one input method.');
187
187
  }
188
188
  if (stdinData) {
189
- inputs = parseJsonInputs(stdinData);
189
+ inputs = (0, inputs_1.parseJsonInputs)(stdinData);
190
190
  }
191
191
  else if (inputsFromFlags.length > 0) {
192
- inputs = parseInputs(inputsFromFlags);
192
+ inputs = (0, inputs_1.parseInputs)(inputsFromFlags);
193
193
  }
194
194
  // Parse workflow inputs from YAML and prompt for missing required inputs
195
- const inputSpecs = parseWorkflowInputsFromYaml(yamlConfig);
195
+ const inputSpecs = (0, inputs_1.parseWorkflowInputsFromYaml)(yamlConfig);
196
196
  if (!flags['non-interactive']) {
197
- inputs = await maybePromptForMissingInputsAsync({ inputSpecs, inputs: inputs ?? {} });
197
+ inputs = await (0, inputs_1.maybePromptForMissingInputsAsync)({ inputSpecs, inputs: inputs ?? {} });
198
198
  }
199
199
  if (inputs && Object.keys(inputs).length > 0) {
200
200
  log_1.default.addNewLineIfNone();
@@ -233,7 +233,7 @@ class WorkflowRun extends EasCommand_1.default {
233
233
  vcsClient,
234
234
  accountId: account.id,
235
235
  }));
236
- if (await fileExistsAsync(easJsonPath)) {
236
+ if (await (0, utils_1.fileExistsAsync)(easJsonPath)) {
237
237
  ({ fileBucketKey: easJsonBucketKey } = await (0, uploadAccountScopedFileAsync_1.uploadAccountScopedFileAsync)({
238
238
  graphqlClient,
239
239
  accountId: account.id,
@@ -244,7 +244,7 @@ class WorkflowRun extends EasCommand_1.default {
244
244
  else {
245
245
  log_1.default.warn(`⚠ No ${chalk_1.default.bold('eas.json')} found in the project directory. Running ${chalk_1.default.bold('type: build')} jobs will not work. Run ${chalk_1.default.bold('eas build:configure')} to configure your project for builds.`);
246
246
  }
247
- if (await fileExistsAsync(packageJsonPath)) {
247
+ if (await (0, utils_1.fileExistsAsync)(packageJsonPath)) {
248
248
  ({ fileBucketKey: packageJsonBucketKey } = await (0, uploadAccountScopedFileAsync_1.uploadAccountScopedFileAsync)({
249
249
  graphqlClient,
250
250
  accountId: account.id,
@@ -319,29 +319,39 @@ class WorkflowRun extends EasCommand_1.default {
319
319
  exports.default = WorkflowRun;
320
320
  async function waitForWorkflowRunToEndAsync(graphqlClient, { workflowRunId }) {
321
321
  log_1.default.log('Waiting for workflow run to complete. You can press Ctrl+C to exit.');
322
- const spinner = (0, ora_1.ora)('Currently waiting for workflow run to start.').start();
322
+ const spinner = (0, ora_1.ora)('').start();
323
+ spinner.prefixText = (0, chalk_1.default) `{bold.yellow Workflow run is waiting to start:}`;
323
324
  let failedFetchesCount = 0;
324
325
  while (true) {
325
326
  try {
326
- const workflowRun = await WorkflowRunQuery_1.WorkflowRunQuery.byIdAsync(graphqlClient, workflowRunId, {
327
+ const workflowRun = await WorkflowRunQuery_1.WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
327
328
  useCache: false,
328
329
  });
329
330
  failedFetchesCount = 0;
330
331
  switch (workflowRun.status) {
331
- case generated_1.WorkflowRunStatus.InProgress:
332
- spinner.start('Workflow run is in progress.');
332
+ case generated_1.WorkflowRunStatus.New:
333
+ break;
334
+ case generated_1.WorkflowRunStatus.InProgress: {
335
+ spinner.prefixText = (0, chalk_1.default) `{bold.green Workflow run is in progress:}`;
336
+ spinner.text = await (0, utils_1.infoForActiveWorkflowRunAsync)(graphqlClient, workflowRun, 5);
333
337
  break;
338
+ }
334
339
  case generated_1.WorkflowRunStatus.ActionRequired:
335
- spinner.warn('Workflow run is waiting for action.');
340
+ spinner.prefixText = (0, chalk_1.default) `{bold.yellow Workflow run is waiting for action:}`;
336
341
  break;
337
342
  case generated_1.WorkflowRunStatus.Canceled:
338
- spinner.warn('Workflow run has been canceled.');
343
+ spinner.prefixText = (0, chalk_1.default) `{bold.yellow Workflow has been canceled.}`;
344
+ spinner.stopAndPersist();
339
345
  return workflowRun;
340
- case generated_1.WorkflowRunStatus.Failure:
341
- spinner.fail('Workflow run has failed.');
346
+ case generated_1.WorkflowRunStatus.Failure: {
347
+ spinner.prefixText = (0, chalk_1.default) `{bold.red Workflow has failed.}`;
348
+ const failedInfo = await (0, utils_1.infoForFailedWorkflowRunAsync)(graphqlClient, workflowRun);
349
+ spinner.fail(failedInfo);
342
350
  return workflowRun;
351
+ }
343
352
  case generated_1.WorkflowRunStatus.Success:
344
- spinner.succeed('Workflow run completed successfully.');
353
+ spinner.prefixText = (0, chalk_1.default) `{bold.green Workflow has completed successfully.}`;
354
+ spinner.succeed('');
345
355
  return workflowRun;
346
356
  }
347
357
  }
@@ -356,211 +366,3 @@ async function waitForWorkflowRunToEndAsync(graphqlClient, { workflowRunId }) {
356
366
  await (0, promise_1.sleepAsync)(10 /* seconds */ * 1000 /* milliseconds */);
357
367
  }
358
368
  }
359
- async function fileExistsAsync(filePath) {
360
- return await fs.promises
361
- .access(filePath, fs.constants.F_OK)
362
- .then(() => true)
363
- .catch(() => false);
364
- }
365
- function parseInputs(inputFlags) {
366
- const inputs = {};
367
- for (const inputFlag of inputFlags) {
368
- const equalIndex = inputFlag.indexOf('=');
369
- if (equalIndex === -1) {
370
- throw new Error(`Invalid input format: ${inputFlag}. Expected key=value format.`);
371
- }
372
- const key = inputFlag.substring(0, equalIndex);
373
- const value = inputFlag.substring(equalIndex + 1);
374
- if (!key) {
375
- throw new Error(`Invalid input format: ${inputFlag}. Key cannot be empty.`);
376
- }
377
- inputs[key] = value;
378
- }
379
- return inputs;
380
- }
381
- exports.parseInputs = parseInputs;
382
- async function maybeReadStdinAsync() {
383
- // Check if there's data on stdin
384
- if (process.stdin.isTTY) {
385
- return null;
386
- }
387
- return await new Promise((resolve, reject) => {
388
- let data = '';
389
- process.stdin.setEncoding('utf8');
390
- process.stdin.on('readable', () => {
391
- let chunk;
392
- while ((chunk = process.stdin.read()) !== null) {
393
- data += chunk;
394
- }
395
- });
396
- process.stdin.on('end', () => {
397
- const trimmedData = data.trim();
398
- resolve(trimmedData || null);
399
- });
400
- process.stdin.on('error', err => {
401
- reject(err);
402
- });
403
- });
404
- }
405
- exports.maybeReadStdinAsync = maybeReadStdinAsync;
406
- function parseJsonInputs(jsonString) {
407
- try {
408
- const parsed = JSON.parse(jsonString);
409
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
410
- throw new Error('JSON input must be an object.');
411
- }
412
- return parsed;
413
- }
414
- catch (error) {
415
- throw new Error(`Invalid JSON input.`, { cause: error });
416
- }
417
- }
418
- exports.parseJsonInputs = parseJsonInputs;
419
- // `z.coerce.boolean()` does `Boolean(val)` under the hood,
420
- // which is not what we want. See:
421
- // https://github.com/colinhacks/zod/issues/2985#issuecomment-2230692578
422
- const booleanLike = zod_1.z.union([
423
- zod_1.z.boolean(),
424
- zod_1.z.codec(zod_1.z.number(), zod_1.z.boolean(), {
425
- decode: n => !!n,
426
- encode: b => (b ? 1 : 0),
427
- }),
428
- zod_1.z.stringbool({ truthy: ['true', 'True'], falsy: ['false', 'False'] }),
429
- ]);
430
- const stringLike = zod_1.z.codec(zod_1.z.union([
431
- // We're going to coerce numbers and strings into strings.
432
- zod_1.z.number(),
433
- zod_1.z.string(),
434
- // We do not allow other primitives, like:
435
- // - bigints, symbols - because YAML does not support them,
436
- // - booleans - because YAML accepts `True` and `true` as boolean input
437
- // and parses both as JS `true` -- if we stringified that,
438
- // we would lose the capital "T" which may not be what the user expects,
439
- // - nulls - user should do `"null"` or not pass the property at all.
440
- ]), zod_1.z.string(), {
441
- decode: value => {
442
- if (typeof value === 'string') {
443
- return value;
444
- }
445
- if (typeof value === 'number') {
446
- return String(value);
447
- }
448
- throw new Error(`Cannot convert ${typeof value} to string: ${value}`);
449
- },
450
- encode: value => value,
451
- });
452
- exports.WorkflowDispatchInputZ = zod_1.z
453
- .object({
454
- description: stringLike.optional().describe('Description of the input'),
455
- required: booleanLike.default(false).describe('Whether the input is required.'),
456
- })
457
- .and(zod_1.z.union([
458
- zod_1.z.object({
459
- type: zod_1.z.literal('string').default('string'),
460
- default: stringLike.optional().describe('Default value for the input'),
461
- }),
462
- zod_1.z.object({
463
- type: zod_1.z.literal('boolean'),
464
- default: booleanLike.optional().describe('Default value for the input'),
465
- }),
466
- zod_1.z.object({
467
- type: zod_1.z.literal('number'),
468
- default: zod_1.z.number().optional().describe('Default value for the input'),
469
- }),
470
- zod_1.z.object({
471
- type: zod_1.z.literal('choice'),
472
- default: stringLike.optional().describe('Default value for the input'),
473
- options: zod_1.z.array(stringLike).min(1).describe('Options for choice type inputs'),
474
- }),
475
- zod_1.z.object({
476
- type: zod_1.z.literal('environment'),
477
- default: zod_1.z.string().optional().describe('Default value for the input'),
478
- }),
479
- ]));
480
- function parseWorkflowInputsFromYaml(yamlConfig) {
481
- try {
482
- const parsed = YAML.parse(yamlConfig);
483
- return zod_1.z
484
- .record(zod_1.z.string(), exports.WorkflowDispatchInputZ)
485
- .default({})
486
- .parse(parsed?.on?.workflow_dispatch?.inputs);
487
- }
488
- catch (error) {
489
- log_1.default.warn('Failed to parse workflow inputs from YAML:', error);
490
- return {};
491
- }
492
- }
493
- exports.parseWorkflowInputsFromYaml = parseWorkflowInputsFromYaml;
494
- async function maybePromptForMissingInputsAsync({ inputSpecs, inputs, }) {
495
- const requiredInputs = Object.entries(inputSpecs).filter(([_, spec]) => spec.required);
496
- const missingRequiredInputs = requiredInputs.filter(([key]) => inputs[key] === undefined);
497
- if (missingRequiredInputs.length === 0) {
498
- return inputs;
499
- }
500
- log_1.default.addNewLineIfNone();
501
- log_1.default.log('Some required inputs are missing. Please provide them:');
502
- const nextInputs = { ...inputs };
503
- for (const [key, spec] of missingRequiredInputs) {
504
- const value = await promptForMissingInputAsync({ key, spec });
505
- nextInputs[key] = value;
506
- }
507
- return nextInputs;
508
- }
509
- async function promptForMissingInputAsync({ key, spec, }) {
510
- const message = spec.description ? `${key} (${spec.description})` : key;
511
- switch (spec.type) {
512
- case 'boolean': {
513
- const { value } = await (0, prompts_1.promptAsync)({
514
- type: 'confirm',
515
- name: 'value',
516
- message,
517
- initial: spec.default,
518
- });
519
- return value;
520
- }
521
- case 'number': {
522
- const { value } = await (0, prompts_1.promptAsync)({
523
- type: 'number',
524
- name: 'value',
525
- message,
526
- initial: spec.default,
527
- validate: (val) => {
528
- if (isNaN(val)) {
529
- return 'Please enter a valid number';
530
- }
531
- return true;
532
- },
533
- });
534
- return value;
535
- }
536
- case 'choice': {
537
- const { value } = await (0, prompts_1.promptAsync)({
538
- type: 'select',
539
- name: 'value',
540
- message,
541
- choices: spec.options.map(option => ({
542
- title: option,
543
- value: option,
544
- })),
545
- initial: spec.default,
546
- });
547
- return value;
548
- }
549
- case 'string':
550
- case 'environment': {
551
- const { value } = await (0, prompts_1.promptAsync)({
552
- type: 'text',
553
- name: 'value',
554
- message,
555
- initial: spec.default,
556
- validate: (val) => {
557
- if (spec.required && (!val || val.trim() === '')) {
558
- return 'This field is required';
559
- }
560
- return true;
561
- },
562
- });
563
- return value;
564
- }
565
- }
566
- }
@@ -1,5 +1,6 @@
1
1
  import { JSONObject } from '@expo/json-file';
2
2
  import type { XCBuildConfiguration } from 'xcode';
3
+ import { z } from 'zod';
3
4
  import { AccountFragment, CommonIosAppCredentialsFragment, IosAppBuildCredentialsFragment } from '../../graphql/generated';
4
5
  export interface App {
5
6
  account: AccountFragment;
@@ -23,3 +24,5 @@ export interface TargetCredentials {
23
24
  export type IosCredentials = Record<string, TargetCredentials>;
24
25
  export type IosAppBuildCredentialsMap = Record<string, IosAppBuildCredentialsFragment>;
25
26
  export type IosAppCredentialsMap = Record<string, CommonIosAppCredentialsFragment | null>;
27
+ export declare const booleanLike: z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodNumber, z.ZodBoolean>, z.ZodCodec<z.ZodString, z.ZodBoolean>]>;
28
+ export declare const stringLike: z.ZodCodec<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodString>;
@@ -1,2 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stringLike = exports.booleanLike = void 0;
4
+ const zod_1 = require("zod");
5
+ // `z.coerce.boolean()` does `Boolean(val)` under the hood,
6
+ // which is not what we want. See:
7
+ // https://github.com/colinhacks/zod/issues/2985#issuecomment-2230692578
8
+ exports.booleanLike = zod_1.z.union([
9
+ zod_1.z.boolean(),
10
+ zod_1.z.codec(zod_1.z.number(), zod_1.z.boolean(), {
11
+ decode: n => !!n,
12
+ encode: b => (b ? 1 : 0),
13
+ }),
14
+ zod_1.z.stringbool({ truthy: ['true', 'True'], falsy: ['false', 'False'] }),
15
+ ]);
16
+ exports.stringLike = zod_1.z.codec(zod_1.z.union([
17
+ // We're going to coerce numbers and strings into strings.
18
+ zod_1.z.number(),
19
+ zod_1.z.string(),
20
+ // We do not allow other primitives, like:
21
+ // - bigints, symbols - because YAML does not support them,
22
+ // - booleans - because YAML accepts `True` and `true` as boolean input
23
+ // and parses both as JS `true` -- if we stringified that,
24
+ // we would lose the capital "T" which may not be what the user expects,
25
+ // - nulls - user should do `"null"` or not pass the property at all.
26
+ ]), zod_1.z.string(), {
27
+ decode: value => {
28
+ if (typeof value === 'string') {
29
+ return value;
30
+ }
31
+ if (typeof value === 'number') {
32
+ return String(value);
33
+ }
34
+ throw new Error(`Cannot convert ${typeof value} to string: ${value}`);
35
+ },
36
+ encode: value => value,
37
+ });
@@ -230,6 +230,8 @@ export type Account = {
230
230
  userInvitations: Array<UserInvitation>;
231
231
  /** Actors associated with this account and permissions they hold */
232
232
  users: Array<UserPermission>;
233
+ /** Notification preferences of the viewer for this account */
234
+ viewerNotificationPreferences: Array<NotificationPreferenceItem>;
233
235
  /** Permission info for the viewer on this account */
234
236
  viewerUserPermission: UserPermission;
235
237
  /** @deprecated Build packs are no longer supported */
@@ -602,6 +604,20 @@ export type AccountMutationSetPushSecurityEnabledArgs = {
602
604
  accountID: Scalars['ID']['input'];
603
605
  pushSecurityEnabled: Scalars['Boolean']['input'];
604
606
  };
607
+ /** Account-level notification preference */
608
+ export type AccountNotificationPreference = NotificationPreference & {
609
+ __typename?: 'AccountNotificationPreference';
610
+ account: Account;
611
+ enabled: Scalars['Boolean']['output'];
612
+ event: NotificationEvent;
613
+ type: NotificationType;
614
+ };
615
+ export type AccountNotificationPreferenceInput = {
616
+ accountId: Scalars['ID']['input'];
617
+ enabled: Scalars['Boolean']['input'];
618
+ event: NotificationEvent;
619
+ type: NotificationType;
620
+ };
605
621
  export type AccountNotificationSubscriptionInput = {
606
622
  accountId: Scalars['ID']['input'];
607
623
  event: NotificationEvent;
@@ -1270,6 +1286,8 @@ export type App = Project & {
1270
1286
  username: Scalars['String']['output'];
1271
1287
  /** @deprecated No longer supported */
1272
1288
  users?: Maybe<Array<Maybe<User>>>;
1289
+ /** Notification preferences of the viewer for this app */
1290
+ viewerNotificationPreferences: Array<NotificationPreferenceItem>;
1273
1291
  /** Webhooks for an app */
1274
1292
  webhooks: Array<Webhook>;
1275
1293
  workerCustomDomain?: Maybe<WorkerCustomDomain>;
@@ -1654,6 +1672,20 @@ export type AppMutationSetResourceClassExperimentArgs = {
1654
1672
  appId: Scalars['ID']['input'];
1655
1673
  resourceClassExperiment?: InputMaybe<ResourceClassExperiment>;
1656
1674
  };
1675
+ /** App-level notification preference */
1676
+ export type AppNotificationPreference = NotificationPreference & {
1677
+ __typename?: 'AppNotificationPreference';
1678
+ app: App;
1679
+ enabled: Scalars['Boolean']['output'];
1680
+ event: NotificationEvent;
1681
+ type: NotificationType;
1682
+ };
1683
+ export type AppNotificationPreferenceInput = {
1684
+ appId: Scalars['ID']['input'];
1685
+ enabled: Scalars['Boolean']['input'];
1686
+ event: NotificationEvent;
1687
+ type: NotificationType;
1688
+ };
1657
1689
  export type AppNotificationSubscriptionInput = {
1658
1690
  appId: Scalars['ID']['input'];
1659
1691
  event: NotificationEvent;
@@ -4723,7 +4755,10 @@ export type MeMutation = {
4723
4755
  scheduleCurrentUserDeletion: BackgroundJobReceipt;
4724
4756
  /** Schedule deletion of a SSO user. Actor must be an owner on the SSO user's SSO account. */
4725
4757
  scheduleSSOUserDeletionAsSSOAccountOwner: BackgroundJobReceipt;
4726
- /** Send SMS OTP to a second factor device for use during device setup or during change confirmation */
4758
+ /**
4759
+ * Send SMS OTP to a second factor device for use during device setup or during change confirmation
4760
+ * @deprecated This method is no longer supported.
4761
+ */
4727
4762
  sendSMSOTPToSecondFactorDevice: SecondFactorBooleanResult;
4728
4763
  /**
4729
4764
  * Sets user preferences. This is a key-value store for user-specific settings. Provided values are
@@ -4826,6 +4861,25 @@ export declare enum NotificationEvent {
4826
4861
  Test = "TEST"
4827
4862
  }
4828
4863
  export type NotificationMetadata = BuildLimitThresholdExceededMetadata | BuildPlanCreditThresholdExceededMetadata | TestNotificationMetadata;
4864
+ /** Base interface for notification preferences */
4865
+ export type NotificationPreference = {
4866
+ enabled: Scalars['Boolean']['output'];
4867
+ event: NotificationEvent;
4868
+ type: NotificationType;
4869
+ };
4870
+ /** Union type representing either account-level or app-level notification preferences */
4871
+ export type NotificationPreferenceItem = AccountNotificationPreference | AppNotificationPreference;
4872
+ export type NotificationPreferenceMutation = {
4873
+ __typename?: 'NotificationPreferenceMutation';
4874
+ setAccountNotificationPreference: NotificationPreferenceItem;
4875
+ setAppNotificationPreference: NotificationPreferenceItem;
4876
+ };
4877
+ export type NotificationPreferenceMutationSetAccountNotificationPreferenceArgs = {
4878
+ input: AccountNotificationPreferenceInput;
4879
+ };
4880
+ export type NotificationPreferenceMutationSetAppNotificationPreferenceArgs = {
4881
+ input: AppNotificationPreferenceInput;
4882
+ };
4829
4883
  export type NotificationSubscription = {
4830
4884
  __typename?: 'NotificationSubscription';
4831
4885
  account?: Maybe<Account>;
@@ -5243,7 +5297,12 @@ export type RootMutation = {
5243
5297
  logRocketProject: LogRocketProjectMutation;
5244
5298
  /** Mutations that modify the currently authenticated User */
5245
5299
  me: MeMutation;
5246
- /** Mutations that modify a NotificationSubscription */
5300
+ /** Notification preference management */
5301
+ notificationPreference: NotificationPreferenceMutation;
5302
+ /**
5303
+ * Mutations that modify a NotificationSubscription
5304
+ * @deprecated Use notificationPreference mutation instead
5305
+ */
5247
5306
  notificationSubscription: NotificationSubscriptionMutation;
5248
5307
  /** Mutations that create, update, and delete Robots */
5249
5308
  robot: RobotMutation;
@@ -5547,6 +5606,7 @@ export type SsoUser = Actor & UserActor & {
5547
5606
  lastName?: Maybe<Scalars['String']['output']>;
5548
5607
  /** @deprecated No longer supported */
5549
5608
  location?: Maybe<Scalars['String']['output']>;
5609
+ /** @deprecated Use Account/App.viewerNotificationPreferences instead */
5550
5610
  notificationSubscriptions: Array<NotificationSubscription>;
5551
5611
  pinnedApps: Array<App>;
5552
5612
  pinnedDashboardViews: Array<PinnedDashboardView>;
@@ -5849,6 +5909,7 @@ export type Submission = ActivityTimelineProjectActivity & {
5849
5909
  id: Scalars['ID']['output'];
5850
5910
  initiatingActor?: Maybe<Actor>;
5851
5911
  iosConfig?: Maybe<IosSubmissionConfig>;
5912
+ jobRun?: Maybe<JobRun>;
5852
5913
  logFiles: Array<Scalars['String']['output']>;
5853
5914
  /** @deprecated Use logFiles instead */
5854
5915
  logsUrl?: Maybe<Scalars['String']['output']>;
@@ -6422,6 +6483,7 @@ export type User = Actor & UserActor & {
6422
6483
  lastName?: Maybe<Scalars['String']['output']>;
6423
6484
  /** @deprecated No longer supported */
6424
6485
  location?: Maybe<Scalars['String']['output']>;
6486
+ /** @deprecated Use Account/App.viewerNotificationPreferences instead */
6425
6487
  notificationSubscriptions: Array<NotificationSubscription>;
6426
6488
  /** Pending UserInvitations for this user. Only resolves for the viewer. */
6427
6489
  pendingUserInvitations: Array<UserInvitation>;
@@ -6521,6 +6583,7 @@ export type UserActor = {
6521
6583
  lastName?: Maybe<Scalars['String']['output']>;
6522
6584
  /** @deprecated No longer supported */
6523
6585
  location?: Maybe<Scalars['String']['output']>;
6586
+ /** @deprecated Use Account/App.viewerNotificationPreferences instead */
6524
6587
  notificationSubscriptions: Array<NotificationSubscription>;
6525
6588
  pinnedApps: Array<App>;
6526
6589
  preferences: UserPreferences;
@@ -11502,6 +11565,7 @@ export type CreateAndroidBuildMutation = {
11502
11565
  id: string;
11503
11566
  status: BuildStatus;
11504
11567
  platform: AppPlatform;
11568
+ logFiles: Array<string>;
11505
11569
  channel?: string | null;
11506
11570
  distribution?: DistributionType | null;
11507
11571
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -11601,6 +11665,7 @@ export type CreateIosBuildMutation = {
11601
11665
  id: string;
11602
11666
  status: BuildStatus;
11603
11667
  platform: AppPlatform;
11668
+ logFiles: Array<string>;
11604
11669
  channel?: string | null;
11605
11670
  distribution?: DistributionType | null;
11606
11671
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -11696,6 +11761,7 @@ export type UpdateBuildMetadataMutation = {
11696
11761
  id: string;
11697
11762
  status: BuildStatus;
11698
11763
  platform: AppPlatform;
11764
+ logFiles: Array<string>;
11699
11765
  channel?: string | null;
11700
11766
  distribution?: DistributionType | null;
11701
11767
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -11785,6 +11851,7 @@ export type RetryIosBuildMutation = {
11785
11851
  id: string;
11786
11852
  status: BuildStatus;
11787
11853
  platform: AppPlatform;
11854
+ logFiles: Array<string>;
11788
11855
  channel?: string | null;
11789
11856
  distribution?: DistributionType | null;
11790
11857
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -12069,6 +12136,7 @@ export type CreateLocalBuildMutation = {
12069
12136
  id: string;
12070
12137
  status: BuildStatus;
12071
12138
  platform: AppPlatform;
12139
+ logFiles: Array<string>;
12072
12140
  channel?: string | null;
12073
12141
  distribution?: DistributionType | null;
12074
12142
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -13096,6 +13164,7 @@ export type BuildsByIdQuery = {
13096
13164
  id: string;
13097
13165
  status: BuildStatus;
13098
13166
  platform: AppPlatform;
13167
+ logFiles: Array<string>;
13099
13168
  channel?: string | null;
13100
13169
  distribution?: DistributionType | null;
13101
13170
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -13184,6 +13253,7 @@ export type BuildsWithSubmissionsByIdQuery = {
13184
13253
  id: string;
13185
13254
  status: BuildStatus;
13186
13255
  platform: AppPlatform;
13256
+ logFiles: Array<string>;
13187
13257
  channel?: string | null;
13188
13258
  distribution?: DistributionType | null;
13189
13259
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -13307,6 +13377,7 @@ export type BuildsWithFingerprintByIdQuery = {
13307
13377
  id: string;
13308
13378
  status: BuildStatus;
13309
13379
  platform: AppPlatform;
13380
+ logFiles: Array<string>;
13310
13381
  channel?: string | null;
13311
13382
  distribution?: DistributionType | null;
13312
13383
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -13424,6 +13495,7 @@ export type ViewBuildsOnAppQuery = {
13424
13495
  id: string;
13425
13496
  status: BuildStatus;
13426
13497
  platform: AppPlatform;
13498
+ logFiles: Array<string>;
13427
13499
  channel?: string | null;
13428
13500
  distribution?: DistributionType | null;
13429
13501
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -14728,6 +14800,7 @@ export type WorkflowJobByIdQuery = {
14728
14800
  id: string;
14729
14801
  status: BuildStatus;
14730
14802
  platform: AppPlatform;
14803
+ logFiles: Array<string>;
14731
14804
  channel?: string | null;
14732
14805
  distribution?: DistributionType | null;
14733
14806
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -14897,6 +14970,7 @@ export type WorkflowRunByIdWithJobsQuery = {
14897
14970
  id: string;
14898
14971
  status: BuildStatus;
14899
14972
  platform: AppPlatform;
14973
+ logFiles: Array<string>;
14900
14974
  channel?: string | null;
14901
14975
  distribution?: DistributionType | null;
14902
14976
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -15148,6 +15222,7 @@ export type BuildFragment = {
15148
15222
  id: string;
15149
15223
  status: BuildStatus;
15150
15224
  platform: AppPlatform;
15225
+ logFiles: Array<string>;
15151
15226
  channel?: string | null;
15152
15227
  distribution?: DistributionType | null;
15153
15228
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -15227,6 +15302,7 @@ export type BuildWithSubmissionsFragment = {
15227
15302
  id: string;
15228
15303
  status: BuildStatus;
15229
15304
  platform: AppPlatform;
15305
+ logFiles: Array<string>;
15230
15306
  channel?: string | null;
15231
15307
  distribution?: DistributionType | null;
15232
15308
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -15341,6 +15417,7 @@ export type BuildWithFingerprintFragment = {
15341
15417
  id: string;
15342
15418
  status: BuildStatus;
15343
15419
  platform: AppPlatform;
15420
+ logFiles: Array<string>;
15344
15421
  channel?: string | null;
15345
15422
  distribution?: DistributionType | null;
15346
15423
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -15753,6 +15830,7 @@ export type WorkflowJobFragment = {
15753
15830
  id: string;
15754
15831
  status: BuildStatus;
15755
15832
  platform: AppPlatform;
15833
+ logFiles: Array<string>;
15756
15834
  channel?: string | null;
15757
15835
  distribution?: DistributionType | null;
15758
15836
  iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null;
@@ -31,6 +31,7 @@ exports.BuildFragmentNode = (0, graphql_tag_1.default) `
31
31
  id
32
32
  displayName
33
33
  }
34
+ logFiles
34
35
  project {
35
36
  __typename
36
37
  id