eas-cli 12.5.1 → 12.5.3

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 (45) hide show
  1. package/README.md +66 -62
  2. package/build/build/build.js +4 -4
  3. package/build/commandUtils/flags.d.ts +10 -0
  4. package/build/commandUtils/flags.js +15 -8
  5. package/build/commands/env/create.d.ts +4 -1
  6. package/build/commands/env/create.js +133 -74
  7. package/build/commands/env/delete.d.ts +2 -2
  8. package/build/commands/env/delete.js +37 -26
  9. package/build/commands/env/exec.js +2 -1
  10. package/build/commands/env/get.d.ts +2 -2
  11. package/build/commands/env/get.js +44 -28
  12. package/build/commands/env/link.d.ts +4 -2
  13. package/build/commands/env/link.js +53 -14
  14. package/build/commands/env/list.d.ts +2 -2
  15. package/build/commands/env/list.js +59 -42
  16. package/build/commands/env/pull.js +1 -1
  17. package/build/commands/env/unlink.d.ts +3 -2
  18. package/build/commands/env/unlink.js +48 -21
  19. package/build/commands/env/update.d.ts +6 -2
  20. package/build/commands/env/update.js +134 -70
  21. package/build/commands/update/index.js +0 -1
  22. package/build/commands/worker/deploy.js +31 -11
  23. package/build/graphql/generated.d.ts +103 -15
  24. package/build/graphql/mutations/EnvironmentVariableMutation.d.ts +13 -22
  25. package/build/graphql/mutations/EnvironmentVariableMutation.js +18 -2
  26. package/build/graphql/queries/EnvironmentVariablesQuery.d.ts +24 -11
  27. package/build/graphql/queries/EnvironmentVariablesQuery.js +40 -17
  28. package/build/graphql/types/EnvironmentVariable.js +3 -1
  29. package/build/graphql/types/EnvironmentVariableWithSecret.d.ts +1 -0
  30. package/build/graphql/types/EnvironmentVariableWithSecret.js +18 -0
  31. package/build/prompts.d.ts +1 -0
  32. package/build/prompts.js +2 -0
  33. package/build/update/republish.js +1 -0
  34. package/build/utils/prompts.d.ts +16 -3
  35. package/build/utils/prompts.js +52 -8
  36. package/build/utils/variableUtils.d.ts +6 -0
  37. package/build/utils/variableUtils.js +62 -0
  38. package/build/worker/assets.d.ts +6 -1
  39. package/build/worker/assets.js +1 -2
  40. package/build/worker/upload.d.ts +1 -0
  41. package/build/worker/upload.js +25 -1
  42. package/oclif.manifest.json +98 -41
  43. package/package.json +3 -3
  44. package/build/utils/formatVariable.d.ts +0 -2
  45. package/build/utils/formatVariable.js +0 -16
@@ -3,7 +3,10 @@ var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
5
  const core_1 = require("@oclif/core");
6
+ const assert_1 = tslib_1.__importDefault(require("assert"));
6
7
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
9
+ const path_1 = tslib_1.__importDefault(require("path"));
7
10
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
8
11
  const flags_1 = require("../../commandUtils/flags");
9
12
  const generated_1 = require("../../graphql/generated");
@@ -13,10 +16,11 @@ const log_1 = tslib_1.__importDefault(require("../../log"));
13
16
  const projectUtils_1 = require("../../project/projectUtils");
14
17
  const prompts_1 = require("../../prompts");
15
18
  const prompts_2 = require("../../utils/prompts");
19
+ const variableUtils_1 = require("../../utils/variableUtils");
16
20
  class EnvironmentVariableUpdate extends EasCommand_1.default {
17
21
  async runAsync() {
18
22
  const { flags } = await this.parse(_a);
19
- let { name, value, scope, 'non-interactive': nonInteractive, environment, visibility, } = this.validateFlags(flags);
23
+ const { name, value: rawValue, scope, 'variable-name': currentName, 'variable-environment': currentEnvironment, 'non-interactive': nonInteractive, environment: environments, type, visibility, } = this.validateFlags(flags);
20
24
  const { privateProjectConfig: { projectId }, loggedIn: { graphqlClient }, } = await this.getContextAsync(_a, {
21
25
  nonInteractive,
22
26
  });
@@ -24,107 +28,167 @@ class EnvironmentVariableUpdate extends EasCommand_1.default {
24
28
  (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId),
25
29
  (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId),
26
30
  ]);
31
+ let selectedVariable;
32
+ let existingVariables = [];
33
+ const suffix = scope === generated_1.EnvironmentVariableScope.Project
34
+ ? `on project ${projectDisplayName}`
35
+ : `on account ${ownerAccount.name}`;
27
36
  if (scope === generated_1.EnvironmentVariableScope.Project) {
28
- if (!environment) {
29
- environment = await (0, prompts_2.promptVariableEnvironmentAsync)(nonInteractive);
30
- }
31
- const existingVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.byAppIdAsync(graphqlClient, {
37
+ existingVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.byAppIdAsync(graphqlClient, {
32
38
  appId: projectId,
33
- environment,
39
+ environment: currentEnvironment,
40
+ filterNames: currentName ? [currentName] : undefined,
34
41
  });
35
- if (!name) {
36
- name = await (0, prompts_1.selectAsync)('Select variable', existingVariables.map(variable => ({
37
- title: variable.name,
38
- value: variable.name,
39
- })));
40
- }
41
- const existingVariable = existingVariables.find(variable => variable.name === name);
42
- if (!existingVariable) {
43
- throw new Error(`Variable with name ${name} does not exist on project ${projectDisplayName}`);
44
- }
45
- if (!value) {
46
- value = await (0, prompts_2.promptVariableValueAsync)({
47
- nonInteractive,
48
- required: false,
49
- initial: existingVariable.value,
50
- });
51
- if (!value || value.length === 0) {
52
- value = '';
53
- }
54
- }
55
- const variable = await EnvironmentVariableMutation_1.EnvironmentVariableMutation.createForAppAsync(graphqlClient, {
56
- name,
57
- value,
58
- environment,
59
- visibility,
60
- overwrite: true,
61
- }, projectId);
62
- if (!variable) {
63
- throw new Error(`Could not update variable with name ${name} on project ${projectDisplayName}`);
64
- }
65
- log_1.default.withTick(`Updated variable ${chalk_1.default.bold(name)} on project ${chalk_1.default.bold(projectDisplayName)}.`);
66
42
  }
67
- else if (scope === generated_1.EnvironmentVariableScope.Shared) {
68
- const sharedVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.sharedAsync(graphqlClient, {
43
+ if (scope === generated_1.EnvironmentVariableScope.Shared) {
44
+ existingVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.sharedAsync(graphqlClient, {
69
45
  appId: projectId,
46
+ environment: currentEnvironment,
47
+ filterNames: currentName ? [currentName] : undefined,
70
48
  });
49
+ }
50
+ if (existingVariables.length === 0) {
51
+ throw new Error(`Variable with name ${currentName} ${currentEnvironment ? `in environment ${currentEnvironment}` : ''} does not exist ${suffix}.`);
52
+ }
53
+ else if (existingVariables.length > 1) {
54
+ selectedVariable = await (0, prompts_1.selectAsync)('Select variable', existingVariables.map(variable => ({
55
+ title: (0, variableUtils_1.formatVariableName)(variable),
56
+ value: variable,
57
+ })));
58
+ }
59
+ else {
60
+ selectedVariable = existingVariables[0];
61
+ }
62
+ (0, assert_1.default)(selectedVariable, 'Variable must be selected');
63
+ const { name: newName, value: newValue, environment: newEnvironments, visibility: newVisibility, type: newType, } = await this.promptForMissingFlagsAsync(selectedVariable, {
64
+ name,
65
+ value: rawValue,
66
+ environment: environments,
67
+ visibility,
68
+ 'non-interactive': nonInteractive,
69
+ type,
70
+ });
71
+ const variable = await EnvironmentVariableMutation_1.EnvironmentVariableMutation.updateAsync(graphqlClient, {
72
+ id: selectedVariable.id,
73
+ name: newName,
74
+ value: newValue,
75
+ environments: newEnvironments,
76
+ type: newType,
77
+ visibility: newVisibility,
78
+ });
79
+ if (!variable) {
80
+ throw new Error(`Could not update variable with name ${name} ${suffix}`);
81
+ }
82
+ log_1.default.withTick(`Updated variable ${chalk_1.default.bold(selectedVariable.name)} ${suffix}.`);
83
+ }
84
+ validateFlags(flags) {
85
+ if (flags['non-interactive']) {
86
+ if (!flags['variable-name']) {
87
+ throw new Error('Current name is required in non-interactive mode. Run the command with --variable-name flag.');
88
+ }
89
+ if (flags['type'] && !flags['value']) {
90
+ throw new Error('Value is required when type is set. Run the command with --value flag.');
91
+ }
92
+ }
93
+ return flags;
94
+ }
95
+ async promptForMissingFlagsAsync(selectedVariable, { name, value, environment: environments, visibility, 'non-interactive': nonInteractive, type, ...rest }) {
96
+ let newType;
97
+ if (type === 'file') {
98
+ newType = generated_1.EnvironmentSecretType.FileBase64;
99
+ }
100
+ else if (type === 'string') {
101
+ newType = generated_1.EnvironmentSecretType.String;
102
+ }
103
+ if (!nonInteractive) {
71
104
  if (!name) {
72
- name = await (0, prompts_1.selectAsync)('Select variable', sharedVariables.map(variable => ({
73
- title: variable.name,
74
- value: variable.name,
75
- })));
105
+ name = await (0, prompts_2.promptVariableNameAsync)(nonInteractive, selectedVariable.name);
106
+ if (!name || name.length === 0) {
107
+ name = undefined;
108
+ }
76
109
  }
77
- const existingVariable = sharedVariables.find(variable => variable.name === name);
78
- if (!existingVariable) {
79
- throw new Error("Variable with this name doesn't exist on this account. Use a different name.");
110
+ log_1.default.log(selectedVariable.type, generated_1.EnvironmentSecretType.String === selectedVariable.type, generated_1.EnvironmentSecretType.FileBase64 === selectedVariable.type);
111
+ if (!type && !value && !nonInteractive) {
112
+ newType = await (0, prompts_2.promptVariableTypeAsync)(nonInteractive, selectedVariable.type);
113
+ if (!newType || newType === selectedVariable.type) {
114
+ newType = undefined;
115
+ }
80
116
  }
81
117
  if (!value) {
82
118
  value = await (0, prompts_2.promptVariableValueAsync)({
83
119
  nonInteractive,
84
120
  required: false,
85
- initial: existingVariable.value,
121
+ initial: (newType ?? selectedVariable.type) === generated_1.EnvironmentSecretType.FileBase64
122
+ ? undefined
123
+ : selectedVariable.value,
86
124
  });
87
- if (!value || value.length === 0) {
88
- value = '';
125
+ if (!value || value.length === 0 || value === selectedVariable.value) {
126
+ value = undefined;
89
127
  }
90
128
  }
91
- const variable = await EnvironmentVariableMutation_1.EnvironmentVariableMutation.createSharedVariableAsync(graphqlClient, {
92
- name,
93
- value,
94
- visibility,
95
- overwrite: true,
96
- }, ownerAccount.id);
97
- if (!variable) {
98
- throw new Error(`Could not update variable with name ${name} on account ${ownerAccount.name}`);
129
+ let environmentFilePath;
130
+ if (newType === generated_1.EnvironmentSecretType.FileBase64 && value) {
131
+ environmentFilePath = path_1.default.resolve(value);
132
+ if (!(await fs_extra_1.default.pathExists(environmentFilePath))) {
133
+ throw new Error(`File "${value}" does not exist`);
134
+ }
99
135
  }
100
- log_1.default.withTick(`Updated shared variable ${chalk_1.default.bold(name)} on account ${chalk_1.default.bold(ownerAccount.name)}.`);
101
- }
102
- }
103
- validateFlags(flags) {
104
- if (flags['non-interactive']) {
105
- if (!flags.name) {
106
- throw new Error('Variable name is required in non-interactive mode. Run the command with --name flag.');
136
+ value = environmentFilePath ? await fs_extra_1.default.readFile(environmentFilePath, 'base64') : value;
137
+ if (!environments || environments.length === 0) {
138
+ environments = await (0, prompts_2.promptVariableEnvironmentAsync)({
139
+ nonInteractive,
140
+ multiple: true,
141
+ selectedEnvironments: selectedVariable.environments ?? [],
142
+ });
143
+ if (!environments ||
144
+ environments.length === 0 ||
145
+ environments === selectedVariable.environments) {
146
+ environments = undefined;
147
+ }
107
148
  }
108
- if (flags.scope === generated_1.EnvironmentVariableScope.Project && !flags.environment) {
109
- throw new Error('Environment is required when updating project-wide variable in non-interactive mode. Run the command with --environment flag.');
149
+ if (!visibility) {
150
+ visibility = await (0, prompts_2.promptVariableVisibilityAsync)(nonInteractive, selectedVariable.visibility);
151
+ if (!visibility || visibility === selectedVariable.visibility) {
152
+ visibility = undefined;
153
+ }
110
154
  }
111
155
  }
112
- return flags;
156
+ return {
157
+ name,
158
+ value,
159
+ environment: environments,
160
+ visibility,
161
+ scope: rest.scope ?? generated_1.EnvironmentVariableScope.Project,
162
+ 'non-interactive': nonInteractive,
163
+ type: newType,
164
+ ...rest,
165
+ };
113
166
  }
114
167
  }
115
168
  _a = EnvironmentVariableUpdate;
116
169
  EnvironmentVariableUpdate.description = 'update an environment variable on the current project or owner account';
117
170
  EnvironmentVariableUpdate.hidden = true;
118
171
  EnvironmentVariableUpdate.flags = {
172
+ 'variable-name': core_1.Flags.string({
173
+ description: 'Current name of the variable',
174
+ }),
175
+ 'variable-environment': core_1.Flags.enum({
176
+ ...flags_1.EasEnvironmentFlagParameters,
177
+ description: 'Current environment of the variable to update',
178
+ }),
119
179
  name: core_1.Flags.string({
120
- description: 'Name of the variable',
180
+ description: 'New name of the variable',
121
181
  }),
122
182
  value: core_1.Flags.string({
123
- description: 'Text value or the variable',
183
+ description: 'New value or the variable',
184
+ }),
185
+ type: core_1.Flags.enum({
186
+ description: 'The type of variable',
187
+ options: ['string', 'file'],
124
188
  }),
125
189
  ...flags_1.EASVariableVisibilityFlag,
126
190
  ...flags_1.EASVariableScopeFlag,
127
- ...flags_1.EASEnvironmentFlag,
191
+ ...flags_1.EASMultiEnvironmentFlag,
128
192
  ...flags_1.EASNonInteractiveFlag,
129
193
  };
130
194
  EnvironmentVariableUpdate.contextDefinition = {
@@ -426,7 +426,6 @@ UpdatePublish.flags = {
426
426
  'rollout-percentage': core_1.Flags.integer({
427
427
  description: `Percentage of users this update should be immediately available to. Users not in the rollout will be served the previous latest update on the branch, even if that update is itself being rolled out. The specified number must be an integer between 1 and 100. When not specified, this defaults to 100.`,
428
428
  required: false,
429
- hidden: true,
430
429
  min: 0,
431
430
  max: 100,
432
431
  }),
@@ -43,6 +43,19 @@ class WorkerDeploy extends EasCommand_1.default {
43
43
  }
44
44
  }
45
45
  }
46
+ async function finalizeDeployAsync(deployParams) {
47
+ const finalizeDeployUrl = new URL('/deploy/finalize', deployParams.baseURL);
48
+ finalizeDeployUrl.searchParams.set('token', deployParams.token);
49
+ const result = await (0, upload_1.callUploadApiAsync)(finalizeDeployUrl, {
50
+ method: 'POST',
51
+ headers: {
52
+ accept: 'application/json',
53
+ },
54
+ });
55
+ if (!result || typeof result !== 'object' || !('success' in result) || !result.success) {
56
+ throw new Error('Deploy failed: Incomplete asset uploads. Please try again');
57
+ }
58
+ }
46
59
  async function uploadTarballAsync(tarPath, uploadUrl) {
47
60
  const { response } = await (0, upload_1.uploadAsync)({
48
61
  url: uploadUrl,
@@ -64,24 +77,30 @@ class WorkerDeploy extends EasCommand_1.default {
64
77
  if (!json.success || !json.result || typeof json.result !== 'object') {
65
78
  throw new Error(json.message ? `Upload failed: ${json.message}` : 'Upload failed!');
66
79
  }
67
- return json.result;
80
+ const { id, fullName, token } = json.result;
81
+ if (typeof token !== 'string') {
82
+ throw new Error('Upload failed: API failed to return a deployment token');
83
+ }
84
+ else if (typeof id !== 'string') {
85
+ throw new Error('Upload failed: API failed to return a deployment identifier');
86
+ }
87
+ else if (typeof fullName !== 'string') {
88
+ throw new Error('Upload failed: API failed to return a script name');
89
+ }
90
+ const baseURL = new URL('/', uploadUrl).toString();
91
+ return { id, fullName, baseURL, token };
68
92
  }
69
93
  }
70
- async function uploadAssetsAsync(assetMap, uploads) {
71
- if (typeof uploads !== 'object' || !uploads) {
72
- return;
73
- }
74
- // TODO(@kitten): Batch and upload multiple files in parallel
94
+ async function uploadAssetsAsync(assetMap, deployParams) {
75
95
  const uploadParams = [];
76
96
  const assetPath = projectDist.type === 'server' ? projectDist.clientPath : projectDist.path;
77
97
  if (!assetPath) {
78
98
  return;
79
99
  }
80
100
  for await (const asset of WorkerAssets.listAssetMapFilesAsync(assetPath, assetMap)) {
81
- const uploadURL = uploads[asset.normalizedPath];
82
- if (uploadURL) {
83
- uploadParams.push({ url: uploadURL, filePath: asset.path });
84
- }
101
+ const uploadURL = new URL(`/asset/${asset.sha512}`, deployParams.baseURL);
102
+ uploadURL.searchParams.set('token', deployParams.token);
103
+ uploadParams.push({ url: uploadURL.toString(), filePath: asset.path });
85
104
  }
86
105
  const progress = {
87
106
  total: uploadParams.length,
@@ -147,7 +166,8 @@ class WorkerDeploy extends EasCommand_1.default {
147
166
  progress.fail('Failed to create deployment');
148
167
  throw error;
149
168
  }
150
- await uploadAssetsAsync(assetMap, deployResult.uploads);
169
+ await uploadAssetsAsync(assetMap, deployResult);
170
+ await finalizeDeployAsync(deployResult);
151
171
  let deploymentAlias = null;
152
172
  if (flags.aliasName) {
153
173
  progress = (0, ora_1.ora)((0, chalk_1.default) `Assigning alias {bold ${flags.aliasName}} to deployment`).start();