eas-cli 16.21.0 → 16.23.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 (56) hide show
  1. package/README.md +210 -209
  2. package/build/build/android/graphql.js +1 -2
  3. package/build/build/evaluateConfigWithEnvVarsAsync.js +5 -11
  4. package/build/build/ios/graphql.js +1 -2
  5. package/build/build/utils/environment.d.ts +1 -4
  6. package/build/build/utils/environment.js +7 -24
  7. package/build/commandUtils/EasCommand.d.ts +1 -2
  8. package/build/commandUtils/context/ContextField.d.ts +1 -2
  9. package/build/commandUtils/context/contextUtils/loadServerSideEnvironmentVariablesAsync.d.ts +1 -2
  10. package/build/commandUtils/context/contextUtils/loadServerSideEnvironmentVariablesAsync.js +3 -8
  11. package/build/commandUtils/flags.d.ts +3 -5
  12. package/build/commandUtils/flags.js +8 -22
  13. package/build/commandUtils/workflow/buildProfileUtils.d.ts +36 -0
  14. package/build/commandUtils/workflow/buildProfileUtils.js +210 -0
  15. package/build/commandUtils/workflow/creation.d.ts +20 -0
  16. package/build/commandUtils/workflow/creation.js +462 -0
  17. package/build/commandUtils/workflow/validation.d.ts +4 -0
  18. package/build/commandUtils/workflow/validation.js +8 -4
  19. package/build/commands/build/resign.d.ts +2 -3
  20. package/build/commands/deploy/index.d.ts +1 -2
  21. package/build/commands/env/create.d.ts +1 -2
  22. package/build/commands/env/create.js +12 -14
  23. package/build/commands/env/delete.d.ts +1 -2
  24. package/build/commands/env/delete.js +2 -6
  25. package/build/commands/env/exec.js +6 -7
  26. package/build/commands/env/get.d.ts +1 -2
  27. package/build/commands/env/get.js +4 -6
  28. package/build/commands/env/list.d.ts +1 -2
  29. package/build/commands/env/list.js +8 -6
  30. package/build/commands/env/pull.d.ts +1 -1
  31. package/build/commands/env/pull.js +8 -8
  32. package/build/commands/env/push.d.ts +6 -4
  33. package/build/commands/env/push.js +42 -30
  34. package/build/commands/env/update.d.ts +2 -3
  35. package/build/commands/env/update.js +7 -8
  36. package/build/commands/fingerprint/compare.d.ts +1 -2
  37. package/build/commands/fingerprint/compare.js +1 -1
  38. package/build/commands/fingerprint/generate.d.ts +1 -2
  39. package/build/commands/fingerprint/generate.js +1 -1
  40. package/build/commands/update/configure.d.ts +1 -1
  41. package/build/commands/update/configure.js +1 -1
  42. package/build/commands/update/index.d.ts +1 -2
  43. package/build/commands/update/index.js +1 -1
  44. package/build/commands/workflow/create.d.ts +4 -3
  45. package/build/commands/workflow/create.js +130 -56
  46. package/build/graphql/generated.d.ts +44 -0
  47. package/build/graphql/queries/EnvironmentVariablesQuery.d.ts +6 -6
  48. package/build/graphql/queries/EnvironmentVariablesQuery.js +15 -0
  49. package/build/graphql/types/Workflow.js +11 -0
  50. package/build/utils/prompts.d.ts +8 -5
  51. package/build/utils/prompts.js +69 -10
  52. package/build/utils/variableUtils.d.ts +1 -3
  53. package/build/utils/variableUtils.js +1 -6
  54. package/build/worker/assets.d.ts +1 -2
  55. package/oclif.manifest.json +43 -114
  56. package/package.json +4 -4
@@ -2,28 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WorkflowCreate = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const core_1 = require("@oclif/core");
5
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
7
  const promises_1 = tslib_1.__importDefault(require("fs/promises"));
7
8
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
9
  const path_1 = tslib_1.__importDefault(require("path"));
9
- const prompts_1 = tslib_1.__importDefault(require("prompts"));
10
10
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
11
- const flags_1 = require("../../commandUtils/flags");
11
+ const buildProfileUtils_1 = require("../../commandUtils/workflow/buildProfileUtils");
12
+ const creation_1 = require("../../commandUtils/workflow/creation");
13
+ const validation_1 = require("../../commandUtils/workflow/validation");
12
14
  const log_1 = tslib_1.__importDefault(require("../../log"));
15
+ const prompts_1 = require("../../prompts");
16
+ const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
13
17
  const workflowFile_1 = require("../../utils/workflowFile");
14
- const DEFAULT_WORKFLOW_NAME = 'workflow.yml';
15
- const HELLO_WORLD_TEMPLATE = `name: Hello World
16
-
17
- on:
18
- push:
19
- branches: ['*']
20
-
21
- jobs:
22
- hello_world:
23
- steps:
24
- - uses: eas/checkout
25
- - run: echo "Hello, World"
26
- `;
27
18
  class WorkflowCreate extends EasCommand_1.default {
28
19
  static description = 'create a new workflow configuration YAML file';
29
20
  static args = [
@@ -34,65 +25,148 @@ class WorkflowCreate extends EasCommand_1.default {
34
25
  },
35
26
  ];
36
27
  static flags = {
37
- ...flags_1.EASNonInteractiveFlag,
28
+ 'skip-validation': core_1.Flags.boolean({
29
+ description: 'If set, the workflow file will not be validated before being created',
30
+ default: false,
31
+ }),
38
32
  };
39
33
  static contextDefinition = {
34
+ ...this.ContextOptions.DynamicProjectConfig,
40
35
  ...this.ContextOptions.ProjectDir,
36
+ ...this.ContextOptions.LoggedIn,
41
37
  };
42
38
  async runAsync() {
43
39
  const { args: { name: argFileName }, flags, } = await this.parse(WorkflowCreate);
44
- const { projectDir } = await this.getContextAsync(WorkflowCreate, {
45
- nonInteractive: flags['non-interactive'],
46
- });
47
- let fileName = argFileName;
48
- if (!fileName) {
49
- const response = await (0, prompts_1.default)({
50
- type: 'text',
51
- name: 'fileName',
52
- message: 'What would you like to name your workflow file?',
53
- initial: DEFAULT_WORKFLOW_NAME,
54
- validate: value => {
55
- try {
56
- workflowFile_1.WorkflowFile.validateYamlExtension(value);
57
- return true;
40
+ try {
41
+ const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, projectDir, } = await this.getContextAsync(WorkflowCreate, {
42
+ nonInteractive: false,
43
+ withServerSideEnvironment: null,
44
+ });
45
+ const { exp: originalExpoConfig, projectId } = await getDynamicPrivateProjectConfigAsync();
46
+ let expoConfig = originalExpoConfig;
47
+ let workflowStarter;
48
+ while (!workflowStarter) {
49
+ workflowStarter = await chooseTemplateAsync();
50
+ switch (workflowStarter.name) {
51
+ case creation_1.WorkflowStarterName.BUILD:
52
+ case creation_1.WorkflowStarterName.DEPLOY:
53
+ case creation_1.WorkflowStarterName.UPDATE: {
54
+ const shouldProceed = await (0, buildProfileUtils_1.runBuildConfigureIfNeededAsync)({
55
+ projectDir,
56
+ expoConfig,
57
+ });
58
+ if (!shouldProceed) {
59
+ workflowStarter = undefined;
60
+ continue;
61
+ }
62
+ break;
58
63
  }
59
- catch (error) {
60
- return error instanceof Error ? error.message : 'Invalid file name';
64
+ default:
65
+ break;
66
+ }
67
+ switch (workflowStarter.name) {
68
+ case creation_1.WorkflowStarterName.DEPLOY:
69
+ case creation_1.WorkflowStarterName.UPDATE: {
70
+ const shouldProceed = await (0, buildProfileUtils_1.runUpdateConfigureIfNeededAsync)({
71
+ projectDir,
72
+ expoConfig,
73
+ });
74
+ if (!shouldProceed) {
75
+ workflowStarter = undefined;
76
+ continue;
77
+ }
78
+ // Need to refetch the Expo config because it may have changed
79
+ expoConfig = (await getDynamicPrivateProjectConfigAsync()).exp;
80
+ break;
61
81
  }
62
- },
63
- });
64
- if (!response.fileName) {
65
- log_1.default.warn('Workflow creation cancelled.');
66
- process.exit(0);
82
+ default:
83
+ break;
84
+ }
85
+ }
86
+ const { fileName, filePath } = await chooseFileNameAsync(argFileName, projectDir, workflowStarter);
87
+ // Customize the template if needed
88
+ workflowStarter = await (0, creation_1.customizeTemplateIfNeededAsync)(workflowStarter, projectDir, expoConfig);
89
+ log_1.default.debug(`Creating workflow file ${fileName} from template ${workflowStarter.name}`);
90
+ const yamlString = [
91
+ workflowStarter.header,
92
+ (0, validation_1.workflowContentsFromParsedYaml)(workflowStarter.template),
93
+ ].join('\n');
94
+ if (!flags['skip-validation']) {
95
+ await (0, validation_1.validateWorkflowFileAsync)({ yamlConfig: yamlString, filePath: fileName }, projectDir, graphqlClient, projectId);
96
+ }
97
+ await ensureWorkflowsDirectoryExistsAsync({ projectDir });
98
+ filePath && (await promises_1.default.writeFile(filePath, yamlString));
99
+ log_1.default.withTick(`Created ${chalk_1.default.bold(filePath)}`);
100
+ log_1.default.addNewLineIfNone();
101
+ log_1.default.log((0, creation_1.howToRunWorkflow)(fileName, workflowStarter));
102
+ // Next steps
103
+ if (workflowStarter.nextSteps && workflowStarter.nextSteps.length > 0) {
104
+ log_1.default.addNewLineIfNone();
105
+ log_1.default.log('Next steps:');
106
+ log_1.default.addNewLineIfNone();
107
+ log_1.default.log((0, formatFields_1.default)(workflowStarter.nextSteps.map((step, index) => ({
108
+ label: `${index + 1}.`,
109
+ value: step,
110
+ }))));
67
111
  }
68
- fileName = response.fileName;
69
- }
70
- try {
71
- await this.ensureWorkflowsDirectoryExistsAsync({ projectDir });
72
- await this.createWorkflowFileAsync({ fileName, projectDir });
73
112
  }
74
113
  catch (error) {
114
+ (0, validation_1.logWorkflowValidationErrors)(error);
75
115
  log_1.default.error('Failed to create workflow file.');
76
- throw error;
77
116
  }
78
117
  }
79
- async ensureWorkflowsDirectoryExistsAsync({ projectDir, }) {
118
+ }
119
+ exports.WorkflowCreate = WorkflowCreate;
120
+ async function ensureWorkflowsDirectoryExistsAsync({ projectDir, }) {
121
+ try {
122
+ await promises_1.default.access(path_1.default.join(projectDir, '.eas', 'workflows'));
123
+ }
124
+ catch {
125
+ await promises_1.default.mkdir(path_1.default.join(projectDir, '.eas', 'workflows'), { recursive: true });
126
+ log_1.default.withTick(`Created directory ${chalk_1.default.bold(path_1.default.join(projectDir, '.eas', 'workflows'))}`);
127
+ }
128
+ }
129
+ async function chooseTemplateAsync() {
130
+ const workflowStarter = (await (0, prompts_1.promptAsync)({
131
+ type: 'select',
132
+ name: 'starter',
133
+ message: 'Select a workflow template:',
134
+ choices: creation_1.workflowStarters.map(starter => ({
135
+ title: starter.displayName,
136
+ value: starter,
137
+ })),
138
+ })).starter;
139
+ return workflowStarter;
140
+ }
141
+ async function chooseFileNameAsync(initialValue, projectDir, workflowStarter) {
142
+ let fileName = initialValue;
143
+ let filePath = '';
144
+ while ((fileName?.length ?? 0) === 0) {
145
+ fileName = (await (0, prompts_1.promptAsync)({
146
+ type: 'text',
147
+ name: 'fileName',
148
+ message: 'What would you like to name your workflow file?',
149
+ initial: workflowStarter.defaultFileName,
150
+ })).fileName;
151
+ if (!fileName) {
152
+ fileName = undefined;
153
+ continue;
154
+ }
80
155
  try {
81
- await promises_1.default.access(path_1.default.join(projectDir, '.eas', 'workflows'));
156
+ workflowFile_1.WorkflowFile.validateYamlExtension(fileName);
82
157
  }
83
- catch {
84
- await promises_1.default.mkdir(path_1.default.join(projectDir, '.eas', 'workflows'), { recursive: true });
85
- log_1.default.withTick(`Created directory ${chalk_1.default.bold(path_1.default.join(projectDir, '.eas', 'workflows'))}`);
158
+ catch (error) {
159
+ log_1.default.error(error instanceof Error ? error.message : 'Invalid YAML file name extension');
160
+ fileName = undefined;
161
+ continue;
86
162
  }
87
- }
88
- async createWorkflowFileAsync({ fileName, projectDir, }) {
89
- workflowFile_1.WorkflowFile.validateYamlExtension(fileName);
90
- const filePath = path_1.default.join(projectDir, '.eas', 'workflows', fileName);
163
+ filePath = path_1.default.join(projectDir, '.eas', 'workflows', fileName);
91
164
  if (await fs_extra_1.default.pathExists(filePath)) {
92
- throw new Error(`Workflow file already exists: ${filePath}`);
165
+ log_1.default.error(`Workflow file already exists: ${filePath}`);
166
+ log_1.default.error('Please choose a different file name.');
167
+ log_1.default.newLine();
168
+ fileName = undefined;
93
169
  }
94
- await promises_1.default.writeFile(filePath, HELLO_WORLD_TEMPLATE);
95
- log_1.default.withTick(`Created ${chalk_1.default.bold(filePath)}`);
96
170
  }
171
+ return { fileName: fileName ?? '', filePath };
97
172
  }
98
- exports.WorkflowCreate = WorkflowCreate;
@@ -166,6 +166,7 @@ export type Account = {
166
166
  displayName?: Maybe<Scalars['String']['output']>;
167
167
  /** Environment secrets for an account */
168
168
  environmentSecrets: Array<EnvironmentSecret>;
169
+ environmentVariableEnvironments: Array<Scalars['EnvironmentVariableEnvironment']['output']>;
169
170
  /** Environment variables for an account */
170
171
  environmentVariables: Array<EnvironmentVariable>;
171
172
  /** Environment variables for an account with decrypted secret values */
@@ -1139,6 +1140,7 @@ export type App = Project & {
1139
1140
  devDomainName?: Maybe<AppDevDomainName>;
1140
1141
  /** Environment secrets for an app */
1141
1142
  environmentSecrets: Array<EnvironmentSecret>;
1143
+ environmentVariableEnvironments: Array<Scalars['EnvironmentVariableEnvironment']['output']>;
1142
1144
  /** Environment variables for an app */
1143
1145
  environmentVariables: Array<EnvironmentVariable>;
1144
1146
  /** Environment variables for an app with decrypted secret values */
@@ -12704,6 +12706,20 @@ export type AppByIdWorkflowsQuery = {
12704
12706
  fileName: string;
12705
12707
  createdAt: any;
12706
12708
  updatedAt: any;
12709
+ revisionsPaginated: {
12710
+ __typename?: 'WorkflowRevisionsConnection';
12711
+ edges: Array<{
12712
+ __typename?: 'WorkflowRevisionEdge';
12713
+ node: {
12714
+ __typename?: 'WorkflowRevision';
12715
+ id: string;
12716
+ blobSha: string;
12717
+ commitSha?: string | null;
12718
+ createdAt: any;
12719
+ yamlConfig: string;
12720
+ };
12721
+ }>;
12722
+ };
12707
12723
  }>;
12708
12724
  };
12709
12725
  };
@@ -13749,6 +13765,20 @@ export type EnvironmentSecretsByAppIdQuery = {
13749
13765
  };
13750
13766
  };
13751
13767
  };
13768
+ export type AppEnvironmentVariableEnvironmentsQueryVariables = Exact<{
13769
+ appId: Scalars['String']['input'];
13770
+ }>;
13771
+ export type AppEnvironmentVariableEnvironmentsQuery = {
13772
+ __typename?: 'RootQuery';
13773
+ app: {
13774
+ __typename?: 'AppQuery';
13775
+ byId: {
13776
+ __typename?: 'App';
13777
+ id: string;
13778
+ environmentVariableEnvironments: Array<any>;
13779
+ };
13780
+ };
13781
+ };
13752
13782
  export type EnvironmentVariablesIncludingSensitiveByAppIdQueryVariables = Exact<{
13753
13783
  appId: Scalars['String']['input'];
13754
13784
  filterNames?: InputMaybe<Array<Scalars['String']['input']> | Scalars['String']['input']>;
@@ -15670,6 +15700,20 @@ export type WorkflowFragment = {
15670
15700
  fileName: string;
15671
15701
  createdAt: any;
15672
15702
  updatedAt: any;
15703
+ revisionsPaginated: {
15704
+ __typename?: 'WorkflowRevisionsConnection';
15705
+ edges: Array<{
15706
+ __typename?: 'WorkflowRevisionEdge';
15707
+ node: {
15708
+ __typename?: 'WorkflowRevision';
15709
+ id: string;
15710
+ blobSha: string;
15711
+ commitSha?: string | null;
15712
+ createdAt: any;
15713
+ yamlConfig: string;
15714
+ };
15715
+ }>;
15716
+ };
15673
15717
  };
15674
15718
  export type WorkflowJobFragment = {
15675
15719
  __typename?: 'WorkflowJob';
@@ -1,35 +1,35 @@
1
- import { EnvironmentVariableEnvironment } from '../../build/utils/environment';
2
1
  import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
3
2
  import { EnvironmentVariableFragment } from '../generated';
4
3
  type EnvironmentVariableWithLinkedEnvironments = EnvironmentVariableFragment & {
5
- linkedEnvironments?: EnvironmentVariableEnvironment[] | null;
4
+ linkedEnvironments?: string[] | null;
6
5
  };
7
6
  export type EnvironmentVariableWithFileContent = EnvironmentVariableFragment & {
8
7
  valueWithFileContent?: string | null | undefined;
9
8
  };
10
9
  export declare const EnvironmentVariablesQuery: {
10
+ environmentVariableEnvironmentsAsync(graphqlClient: ExpoGraphqlClient, appId: string): Promise<string[]>;
11
11
  byAppIdWithSensitiveAsync(graphqlClient: ExpoGraphqlClient, { appId, environment, filterNames, includeFileContent, }: {
12
12
  appId: string;
13
- environment?: EnvironmentVariableEnvironment | undefined;
13
+ environment?: string | undefined;
14
14
  filterNames?: string[] | undefined;
15
15
  includeFileContent?: boolean | undefined;
16
16
  }): Promise<EnvironmentVariableWithFileContent[]>;
17
17
  byAppIdAsync(graphqlClient: ExpoGraphqlClient, { appId, environment, filterNames, includeFileContent, }: {
18
18
  appId: string;
19
- environment?: EnvironmentVariableEnvironment | undefined;
19
+ environment?: string | undefined;
20
20
  filterNames?: string[] | undefined;
21
21
  includeFileContent?: boolean | undefined;
22
22
  }): Promise<(EnvironmentVariableWithFileContent & EnvironmentVariableWithLinkedEnvironments)[]>;
23
23
  sharedAsync(graphqlClient: ExpoGraphqlClient, { appId, filterNames, environment, includeFileContent, }: {
24
24
  appId: string;
25
25
  filterNames?: string[] | undefined;
26
- environment?: EnvironmentVariableEnvironment | undefined;
26
+ environment?: string | undefined;
27
27
  includeFileContent?: boolean | undefined;
28
28
  }): Promise<(EnvironmentVariableWithFileContent & EnvironmentVariableWithLinkedEnvironments)[]>;
29
29
  sharedWithSensitiveAsync(graphqlClient: ExpoGraphqlClient, { appId, filterNames, environment, includeFileContent, }: {
30
30
  appId: string;
31
31
  filterNames?: string[] | undefined;
32
- environment?: EnvironmentVariableEnvironment | undefined;
32
+ environment?: string | undefined;
33
33
  includeFileContent?: boolean | undefined;
34
34
  }): Promise<EnvironmentVariableWithFileContent[]>;
35
35
  };
@@ -8,6 +8,21 @@ const client_1 = require("../client");
8
8
  const EnvironmentVariable_1 = require("../types/EnvironmentVariable");
9
9
  const EnvironmentVariableWithSecret_1 = require("../types/EnvironmentVariableWithSecret");
10
10
  exports.EnvironmentVariablesQuery = {
11
+ async environmentVariableEnvironmentsAsync(graphqlClient, appId) {
12
+ const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
13
+ .query((0, graphql_tag_1.default) `
14
+ query AppEnvironmentVariableEnvironments($appId: String!) {
15
+ app {
16
+ byId(appId: $appId) {
17
+ id
18
+ environmentVariableEnvironments
19
+ }
20
+ }
21
+ }
22
+ `, { appId }, { additionalTypenames: ['App'] })
23
+ .toPromise());
24
+ return data.app?.byId.environmentVariableEnvironments ?? [];
25
+ },
11
26
  async byAppIdWithSensitiveAsync(graphqlClient, { appId, environment, filterNames, includeFileContent = false, }) {
12
27
  const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
13
28
  .query((0, graphql_tag_1.default) `
@@ -10,5 +10,16 @@ exports.WorkflowFragmentNode = (0, graphql_tag_1.default) `
10
10
  fileName
11
11
  createdAt
12
12
  updatedAt
13
+ revisionsPaginated(first: 1) {
14
+ edges {
15
+ node {
16
+ id
17
+ blobSha
18
+ commitSha
19
+ createdAt
20
+ yamlConfig
21
+ }
22
+ }
23
+ }
13
24
  }
14
25
  `;
@@ -1,20 +1,23 @@
1
- import { EnvironmentVariableEnvironment } from '../build/utils/environment';
1
+ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
2
2
  import { EnvironmentSecretType, EnvironmentVariableVisibility } from '../graphql/generated';
3
3
  import { RequestedPlatform } from '../platform';
4
+ export declare function getProjectEnvironmentVariableEnvironmentsAsync(graphqlClient: ExpoGraphqlClient, projectId: string): Promise<string[]>;
4
5
  export declare function promptVariableTypeAsync(nonInteractive: boolean, initialType?: EnvironmentSecretType): Promise<EnvironmentSecretType>;
5
6
  export declare function parseVisibility(stringVisibility: 'plaintext' | 'sensitive' | 'secret'): EnvironmentVariableVisibility;
6
7
  export declare function promptVariableVisibilityAsync(nonInteractive: boolean, selectedVisibility?: EnvironmentVariableVisibility | null): Promise<EnvironmentVariableVisibility>;
7
8
  type EnvironmentPromptArgs = {
8
9
  nonInteractive: boolean;
9
- selectedEnvironments?: EnvironmentVariableEnvironment[];
10
- availableEnvironments?: EnvironmentVariableEnvironment[];
10
+ selectedEnvironments?: string[];
11
+ graphqlClient?: ExpoGraphqlClient;
12
+ projectId?: string;
13
+ canEnterCustomEnvironment?: boolean;
11
14
  };
12
15
  export declare function promptVariableEnvironmentAsync(input: EnvironmentPromptArgs & {
13
16
  multiple: true;
14
- }): Promise<EnvironmentVariableEnvironment[]>;
17
+ }): Promise<string[]>;
15
18
  export declare function promptVariableEnvironmentAsync(input: EnvironmentPromptArgs & {
16
19
  multiple?: false;
17
- }): Promise<EnvironmentVariableEnvironment>;
20
+ }): Promise<string>;
18
21
  export declare function promptVariableValueAsync({ nonInteractive, required, hidden, filePath, initial, }: {
19
22
  nonInteractive: boolean;
20
23
  required?: boolean;
@@ -1,12 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.promptPlatformAsync = exports.promptVariableNameAsync = exports.promptVariableValueAsync = exports.promptVariableEnvironmentAsync = exports.promptVariableVisibilityAsync = exports.parseVisibility = exports.promptVariableTypeAsync = void 0;
3
+ exports.promptPlatformAsync = exports.promptVariableNameAsync = exports.promptVariableValueAsync = exports.promptVariableEnvironmentAsync = exports.promptVariableVisibilityAsync = exports.parseVisibility = exports.promptVariableTypeAsync = exports.getProjectEnvironmentVariableEnvironmentsAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
6
  const environment_1 = require("../build/utils/environment");
7
7
  const generated_1 = require("../graphql/generated");
8
+ const EnvironmentVariablesQuery_1 = require("../graphql/queries/EnvironmentVariablesQuery");
8
9
  const platform_1 = require("../platform");
9
10
  const prompts_1 = require("../prompts");
11
+ const DEFAULT_ENVIRONMENTS = Object.values(environment_1.DefaultEnvironment);
12
+ async function getProjectEnvironmentVariableEnvironmentsAsync(graphqlClient, projectId) {
13
+ try {
14
+ const environments = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.environmentVariableEnvironmentsAsync(graphqlClient, projectId);
15
+ return environments;
16
+ }
17
+ catch {
18
+ throw new Error('Failed to fetch available environments');
19
+ }
20
+ }
21
+ exports.getProjectEnvironmentVariableEnvironmentsAsync = getProjectEnvironmentVariableEnvironmentsAsync;
22
+ const CUSTOM_ENVIRONMENT_VALUE = '~~CUSTOM~~';
10
23
  async function promptVariableTypeAsync(nonInteractive, initialType) {
11
24
  if (nonInteractive) {
12
25
  throw new Error('The `--type` flag must be set when running in `--non-interactive` mode.');
@@ -39,6 +52,23 @@ function parseVisibility(stringVisibility) {
39
52
  }
40
53
  }
41
54
  exports.parseVisibility = parseVisibility;
55
+ async function promptCustomEnvironmentAsync() {
56
+ const { customEnvironment } = await (0, prompts_1.promptAsync)({
57
+ type: 'text',
58
+ name: 'customEnvironment',
59
+ message: 'Enter custom environment name:',
60
+ validate: (value) => {
61
+ if (!value || value.trim() === '') {
62
+ return 'Environment name cannot be empty';
63
+ }
64
+ if (!value.match(/^[a-zA-Z0-9_-]+$/)) {
65
+ return 'Environment name may only contain letters, numbers, underscores, and hyphens';
66
+ }
67
+ return true;
68
+ },
69
+ });
70
+ return customEnvironment;
71
+ }
42
72
  async function promptVariableVisibilityAsync(nonInteractive, selectedVisibility) {
43
73
  if (nonInteractive) {
44
74
  throw new Error('The `--visibility` flag must be set when running in `--non-interactive` mode.');
@@ -62,26 +92,55 @@ async function promptVariableVisibilityAsync(nonInteractive, selectedVisibility)
62
92
  ]);
63
93
  }
64
94
  exports.promptVariableVisibilityAsync = promptVariableVisibilityAsync;
65
- async function promptVariableEnvironmentAsync({ nonInteractive, selectedEnvironments, multiple = false, availableEnvironments, }) {
95
+ async function promptVariableEnvironmentAsync({ nonInteractive, selectedEnvironments, multiple = false, canEnterCustomEnvironment = false, graphqlClient, projectId, }) {
66
96
  if (nonInteractive) {
67
97
  throw new Error('The `--environment` flag must be set when running in `--non-interactive` mode.');
68
98
  }
99
+ let allEnvironments = DEFAULT_ENVIRONMENTS;
100
+ if (graphqlClient && projectId) {
101
+ const projectEnvironments = await getProjectEnvironmentVariableEnvironmentsAsync(graphqlClient, projectId);
102
+ allEnvironments = [...new Set([...DEFAULT_ENVIRONMENTS, ...projectEnvironments])];
103
+ }
69
104
  if (!multiple) {
70
- return await (0, prompts_1.selectAsync)('Select environment:', (availableEnvironments ?? Object.values(environment_1.EnvironmentVariableEnvironment)).map(environment => ({
71
- title: environment.toLocaleLowerCase(),
105
+ const choices = allEnvironments.map(environment => ({
106
+ title: environment,
72
107
  value: environment,
73
- })));
108
+ }));
109
+ if (canEnterCustomEnvironment) {
110
+ choices.push({
111
+ title: 'Other (enter custom environment)',
112
+ value: CUSTOM_ENVIRONMENT_VALUE,
113
+ });
114
+ }
115
+ const selectedEnvironment = await (0, prompts_1.selectAsync)('Select environment:', choices);
116
+ if (selectedEnvironment === CUSTOM_ENVIRONMENT_VALUE) {
117
+ return await promptCustomEnvironmentAsync();
118
+ }
119
+ return selectedEnvironment;
120
+ }
121
+ const choices = allEnvironments.map(environment => ({
122
+ title: environment,
123
+ value: environment,
124
+ selected: selectedEnvironments?.includes(environment),
125
+ }));
126
+ if (canEnterCustomEnvironment) {
127
+ choices.push({
128
+ title: 'Other (enter custom environment)',
129
+ value: CUSTOM_ENVIRONMENT_VALUE,
130
+ selected: false,
131
+ });
74
132
  }
75
133
  const { environments } = await (0, prompts_1.promptAsync)({
76
134
  message: 'Select environment:',
77
135
  name: 'environments',
78
136
  type: 'multiselect',
79
- choices: Object.values(environment_1.EnvironmentVariableEnvironment).map(environment => ({
80
- title: environment.toLocaleLowerCase(),
81
- value: environment,
82
- selected: selectedEnvironments?.includes(environment),
83
- })),
137
+ choices,
84
138
  });
139
+ if (environments?.includes(CUSTOM_ENVIRONMENT_VALUE)) {
140
+ const customEnvironment = await promptCustomEnvironmentAsync();
141
+ const filteredEnvironments = environments.filter((env) => env !== CUSTOM_ENVIRONMENT_VALUE);
142
+ return [...filteredEnvironments, customEnvironment];
143
+ }
85
144
  return environments;
86
145
  }
87
146
  exports.promptVariableEnvironmentAsync = promptVariableEnvironmentAsync;
@@ -1,8 +1,6 @@
1
- import { EnvironmentVariableEnvironment } from '../build/utils/environment';
2
1
  import { EnvironmentVariableFragment } from '../graphql/generated';
3
2
  import { EnvironmentVariableWithFileContent } from '../graphql/queries/EnvironmentVariablesQuery';
4
- export declare function isEnvironment(environment: string): environment is EnvironmentVariableEnvironment;
5
3
  export declare function formatVariableName(variable: EnvironmentVariableFragment): string;
6
4
  export declare function formatVariableValue(variable: EnvironmentVariableWithFileContent): string;
7
- export declare function performForEnvironmentsAsync(environments: EnvironmentVariableEnvironment[] | null, fun: (environment: EnvironmentVariableEnvironment | undefined) => Promise<any>): Promise<any[]>;
5
+ export declare function performForEnvironmentsAsync(environments: string[] | null, fun: (environment: string | undefined) => Promise<any>): Promise<any[]>;
8
6
  export declare function formatVariable(variable: EnvironmentVariableWithFileContent): string;
@@ -1,15 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatVariable = exports.performForEnvironmentsAsync = exports.formatVariableValue = exports.formatVariableName = exports.isEnvironment = void 0;
3
+ exports.formatVariable = exports.performForEnvironmentsAsync = exports.formatVariableValue = exports.formatVariableName = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const dateformat_1 = tslib_1.__importDefault(require("dateformat"));
6
6
  const formatFields_1 = tslib_1.__importDefault(require("./formatFields"));
7
- const environment_1 = require("../build/utils/environment");
8
7
  const generated_1 = require("../graphql/generated");
9
- function isEnvironment(environment) {
10
- return Object.values(environment_1.EnvironmentVariableEnvironment).includes(environment);
11
- }
12
- exports.isEnvironment = isEnvironment;
13
8
  function formatVariableName(variable) {
14
9
  const name = variable.name;
15
10
  const scope = variable.scope === generated_1.EnvironmentVariableScope.Project ? 'project' : 'shared';
@@ -1,6 +1,5 @@
1
1
  /// <reference types="node" />
2
2
  import { GzipOptions } from 'minizlib';
3
- import { EnvironmentVariableEnvironment } from '../build/utils/environment';
4
3
  import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
5
4
  interface AssetMapOptions {
6
5
  maxFileSize: number;
@@ -36,7 +35,7 @@ export interface CreateManifestResult {
36
35
  interface CreateManifestParams {
37
36
  projectId: string;
38
37
  projectDir: string;
39
- environment?: EnvironmentVariableEnvironment;
38
+ environment?: string;
40
39
  }
41
40
  /** Creates a manifest configuration sent up for deployment */
42
41
  export declare function createManifestAsync(params: CreateManifestParams, graphqlClient: ExpoGraphqlClient): Promise<CreateManifestResult>;