eas-cli 12.0.0 → 12.1.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 +60 -60
  2. package/build/build/build.js +8 -45
  3. package/build/build/evaluateConfigWithEnvVarsAsync.d.ts +2 -1
  4. package/build/build/evaluateConfigWithEnvVarsAsync.js +31 -9
  5. package/build/build/graphql.d.ts +2 -1
  6. package/build/build/graphql.js +13 -2
  7. package/build/build/runBuildAndSubmit.js +1 -1
  8. package/build/commands/build/resign.js +1 -0
  9. package/build/commands/build/version/get.js +1 -0
  10. package/build/commands/build/version/set.js +1 -0
  11. package/build/commands/build/version/sync.js +1 -0
  12. package/build/commands/config.js +1 -0
  13. package/build/commands/update/index.js +22 -5
  14. package/build/commands/update/roll-back-to-embedded.js +6 -6
  15. package/build/commands/worker/deploy.d.ts +15 -0
  16. package/build/commands/worker/deploy.js +181 -0
  17. package/build/graphql/generated.d.ts +301 -53
  18. package/build/graphql/generated.js +72 -12
  19. package/build/project/maybeUploadFingerprintAsync.d.ts +15 -0
  20. package/build/project/maybeUploadFingerprintAsync.js +57 -0
  21. package/build/project/publish.d.ts +16 -11
  22. package/build/project/publish.js +33 -30
  23. package/build/project/resolveRuntimeVersionAsync.d.ts +13 -0
  24. package/build/project/resolveRuntimeVersionAsync.js +21 -17
  25. package/build/worker/assets.d.ts +25 -0
  26. package/build/worker/assets.js +110 -0
  27. package/build/worker/deployment.d.ts +6 -0
  28. package/build/worker/deployment.js +57 -0
  29. package/build/worker/mutations.d.ts +11 -0
  30. package/build/worker/mutations.js +45 -0
  31. package/build/worker/upload.d.ts +20 -0
  32. package/build/worker/upload.js +141 -0
  33. package/oclif.manifest.json +22 -1
  34. package/package.json +5 -2
@@ -4,25 +4,36 @@ exports.evaluateConfigWithEnvVarsAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const generated_1 = require("../graphql/generated");
6
6
  const EnvironmentVariablesQuery_1 = require("../graphql/queries/EnvironmentVariablesQuery");
7
- const log_1 = tslib_1.__importDefault(require("../log"));
7
+ const log_1 = tslib_1.__importStar(require("../log"));
8
8
  function isEnvironment(env) {
9
- return Object.values(generated_1.EnvironmentVariableEnvironment).includes(env.toUpperCase());
9
+ return Object.values(generated_1.EnvironmentVariableEnvironment).includes(env);
10
10
  }
11
- async function evaluateConfigWithEnvVarsAsync({ flags, buildProfile, graphqlClient, getProjectConfig, opts, }) {
11
+ async function evaluateConfigWithEnvVarsAsync({ flags, buildProfile, buildProfileName, graphqlClient, getProjectConfig, opts, }) {
12
12
  if (!graphqlClient) {
13
13
  log_1.default.warn('An Expo user account is required to fetch environment variables.');
14
14
  const config = await getProjectConfig(opts);
15
15
  return { env: buildProfile.env ?? {}, ...config };
16
16
  }
17
17
  const { projectId } = await getProjectConfig({ env: buildProfile.env, ...opts });
18
- const env = await resolveEnvVarsAsync({ flags, buildProfile, graphqlClient, projectId });
18
+ const env = await resolveEnvVarsAsync({
19
+ flags,
20
+ buildProfile,
21
+ buildProfileName,
22
+ graphqlClient,
23
+ projectId,
24
+ });
19
25
  const config = await getProjectConfig({ ...opts, env });
20
26
  return { env, ...config };
21
27
  }
22
28
  exports.evaluateConfigWithEnvVarsAsync = evaluateConfigWithEnvVarsAsync;
23
- async function resolveEnvVarsAsync({ flags, buildProfile, graphqlClient, projectId, }) {
24
- const environment = flags.environment ?? buildProfile.environment ?? process.env.EAS_CURRENT_ENVIRONMENT;
29
+ async function resolveEnvVarsAsync({ flags, buildProfile, buildProfileName, graphqlClient, projectId, }) {
30
+ const environment = flags.environment ??
31
+ buildProfile.environment?.toUpperCase() ??
32
+ process.env.EAS_CURRENT_ENVIRONMENT;
25
33
  if (!environment || !isEnvironment(environment)) {
34
+ log_1.default.log(`Loaded "env" configuration for the "${buildProfileName}" profile: ${buildProfile.env && Object.keys(buildProfile.env).length > 0
35
+ ? Object.keys(buildProfile.env).join(', ')
36
+ : 'no environment variables specified'}. ${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/variables/')}`);
26
37
  return { ...buildProfile.env };
27
38
  }
28
39
  try {
@@ -30,13 +41,24 @@ async function resolveEnvVarsAsync({ flags, buildProfile, graphqlClient, project
30
41
  appId: projectId,
31
42
  environment,
32
43
  });
33
- const envVars = Object.fromEntries(environmentVariables
44
+ const serverEnvVars = Object.fromEntries(environmentVariables
34
45
  .filter(({ name, value }) => name && value)
35
46
  .map(({ name, value }) => [name, value]));
36
- return { ...envVars, ...buildProfile.env };
47
+ const envVarsWithSource = {
48
+ ...Object.fromEntries(Object.keys(serverEnvVars).map(key => [key, 'EAS server'])),
49
+ ...(buildProfile.env
50
+ ? Object.fromEntries(Object.keys(buildProfile.env).map(key => [key, 'build profile']))
51
+ : null),
52
+ };
53
+ log_1.default.log(`Loaded "env" configuration for the "${buildProfileName}" profile and "${environment.toLowerCase()}" environment: ${Object.keys(envVarsWithSource).length > 0
54
+ ? Object.keys(envVarsWithSource)
55
+ .map(key => `${key} (source: ${envVarsWithSource[key]})`)
56
+ .join('\n')
57
+ : 'no environment variables specified'}\n${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/variables/')}`);
58
+ return { ...serverEnvVars, ...buildProfile.env };
37
59
  }
38
60
  catch (e) {
39
- log_1.default.error('Failed to pull env variables for environment ${environment} from EAS servers');
61
+ log_1.default.error(`Failed to pull env variables for environment ${environment} from EAS servers`);
40
62
  log_1.default.error(e);
41
63
  log_1.default.error('This can possibly be a bug in EAS/EAS CLI. Report it here: https://github.com/expo/eas-cli/issues');
42
64
  return { ...buildProfile.env };
@@ -1,8 +1,9 @@
1
1
  import { ArchiveSource, BuildMode, BuildTrigger, Metadata, Workflow } from '@expo/eas-build-job';
2
2
  import { LoggerLevel } from '@expo/logger';
3
- import { BuildIosEnterpriseProvisioning, BuildMetadataInput, BuildWorkflow, BuildMode as GraphQLBuildMode, BuildTrigger as GraphQLBuildTrigger, ProjectArchiveSourceInput, WorkerLoggerLevel } from '../graphql/generated';
3
+ import { BuildIosEnterpriseProvisioning, BuildMetadataInput, BuildWorkflow, FingerprintSourceInput, BuildMode as GraphQLBuildMode, BuildTrigger as GraphQLBuildTrigger, ProjectArchiveSourceInput, WorkerLoggerLevel } from '../graphql/generated';
4
4
  export declare function transformProjectArchive(archiveSource: ArchiveSource): ProjectArchiveSourceInput;
5
5
  export declare function transformMetadata(metadata: Metadata): BuildMetadataInput;
6
+ export declare function transformFingerprintSource(fingerprintSource: NonNullable<Metadata['fingerprintSource']>): FingerprintSourceInput | null;
6
7
  export declare function transformWorkflow(workflow: Workflow): BuildWorkflow;
7
8
  export declare function transformIosEnterpriseProvisioning(enterpriseProvisioning: Metadata['iosEnterpriseProvisioning']): BuildIosEnterpriseProvisioning;
8
9
  export declare function transformBuildMode(buildMode: BuildMode): GraphQLBuildMode;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loggerLevelToGraphQLWorkerLoggerLevel = exports.transformBuildTrigger = exports.transformBuildMode = exports.transformIosEnterpriseProvisioning = exports.transformWorkflow = exports.transformMetadata = exports.transformProjectArchive = void 0;
3
+ exports.loggerLevelToGraphQLWorkerLoggerLevel = exports.transformBuildTrigger = exports.transformBuildMode = exports.transformIosEnterpriseProvisioning = exports.transformWorkflow = exports.transformFingerprintSource = exports.transformMetadata = exports.transformProjectArchive = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const eas_build_job_1 = require("@expo/eas-build-job");
6
6
  const logger_1 = require("@expo/logger");
@@ -28,7 +28,7 @@ exports.transformProjectArchive = transformProjectArchive;
28
28
  function transformMetadata(metadata) {
29
29
  return {
30
30
  ...metadata,
31
- fingerprintSource: metadata.fingerprintSource,
31
+ fingerprintSource: metadata.fingerprintSource && transformFingerprintSource(metadata.fingerprintSource),
32
32
  credentialsSource: metadata.credentialsSource && transformCredentialsSource(metadata.credentialsSource),
33
33
  distribution: metadata.distribution && transformDistribution(metadata.distribution),
34
34
  workflow: metadata.workflow && transformWorkflow(metadata.workflow),
@@ -37,6 +37,17 @@ function transformMetadata(metadata) {
37
37
  };
38
38
  }
39
39
  exports.transformMetadata = transformMetadata;
40
+ function transformFingerprintSource(fingerprintSource) {
41
+ if (fingerprintSource.type !== eas_build_job_1.FingerprintSourceType.GCS) {
42
+ return null;
43
+ }
44
+ return {
45
+ type: generated_1.FingerprintSourceType.Gcs,
46
+ bucketKey: fingerprintSource.bucketKey,
47
+ isDebugFingerprint: fingerprintSource.isDebugFingerprint,
48
+ };
49
+ }
50
+ exports.transformFingerprintSource = transformFingerprintSource;
40
51
  function transformCredentialsSource(credentialsSource) {
41
52
  if (credentialsSource === 'local') {
42
53
  return generated_1.BuildCredentialsSource.Local;
@@ -100,11 +100,11 @@ async function runBuildAndSubmitAsync(graphqlClient, analytics, vcsClient, proje
100
100
  const { env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
101
101
  flags,
102
102
  buildProfile: buildProfile.profile,
103
+ buildProfileName: buildProfile.profileName,
103
104
  graphqlClient,
104
105
  getProjectConfig: getDynamicPrivateProjectConfigAsync,
105
106
  opts: { env: buildProfile.profile.env },
106
107
  });
107
- log_1.default.log(`Loaded "env" configuration for the "${buildProfile.profileName}" profile: ${env ? Object.keys(env).join(', ') : 'no environment variables specified'}. ${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/variables/')}`);
108
108
  const { build: maybeBuild, buildCtx } = await prepareAndStartBuildAsync({
109
109
  projectDir,
110
110
  flags,
@@ -56,6 +56,7 @@ class BuildResign extends EasCommand_1.default {
56
56
  const { exp, projectId, env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
57
57
  flags,
58
58
  buildProfile,
59
+ buildProfileName: flags.targetProfile ?? 'production',
59
60
  graphqlClient,
60
61
  getProjectConfig: getDynamicPrivateProjectConfigAsync,
61
62
  opts: { env: buildProfile.env },
@@ -46,6 +46,7 @@ class BuildVersionGetView extends EasCommand_1.default {
46
46
  const { exp, projectId, env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
47
47
  flags,
48
48
  buildProfile: profile,
49
+ buildProfileName: flags.profile ?? 'production',
49
50
  graphqlClient,
50
51
  getProjectConfig: getDynamicPrivateProjectConfigAsync,
51
52
  opts: { env: profile.env },
@@ -34,6 +34,7 @@ class BuildVersionSetView extends EasCommand_1.default {
34
34
  const { exp, projectId, env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
35
35
  flags,
36
36
  buildProfile: profile,
37
+ buildProfileName: flags.profile ?? 'production',
37
38
  graphqlClient,
38
39
  getProjectConfig: getDynamicPrivateProjectConfigAsync,
39
40
  opts: { env: profile.env },
@@ -45,6 +45,7 @@ class BuildVersionSyncView extends EasCommand_1.default {
45
45
  const { exp, projectId, env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
46
46
  flags,
47
47
  buildProfile: profileInfo.profile,
48
+ buildProfileName: profileInfo.profileName,
48
49
  graphqlClient,
49
50
  getProjectConfig: getDynamicPrivateProjectConfigAsync,
50
51
  opts: { env: profileInfo.profile.env },
@@ -64,6 +64,7 @@ class Config extends EasCommand_1.default {
64
64
  const { exp: appConfig } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
65
65
  flags,
66
66
  buildProfile: profile,
67
+ buildProfileName: profileName,
67
68
  graphqlClient,
68
69
  getProjectConfig: getDynamicPublicProjectConfigAsync,
69
70
  opts: { env: profile.env },
@@ -7,6 +7,7 @@ const core_1 = require("@oclif/core");
7
7
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
8
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
9
9
  const queries_1 = require("../../branch/queries");
10
+ const graphql_1 = require("../../build/graphql");
10
11
  const repository_1 = require("../../build/utils/repository");
11
12
  const url_1 = require("../../build/utils/url");
12
13
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
@@ -17,6 +18,7 @@ const generated_1 = require("../../graphql/generated");
17
18
  const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
18
19
  const log_1 = tslib_1.__importStar(require("../../log"));
19
20
  const ora_1 = require("../../ora");
21
+ const maybeUploadFingerprintAsync_1 = require("../../project/maybeUploadFingerprintAsync");
20
22
  const projectUtils_1 = require("../../project/projectUtils");
21
23
  const publish_1 = require("../../project/publish");
22
24
  const workflow_1 = require("../../project/workflow");
@@ -182,7 +184,7 @@ class UpdatePublish extends EasCommand_1.default {
182
184
  throw e;
183
185
  }
184
186
  const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir, vcsClient);
185
- const runtimeVersions = await (0, publish_1.getRuntimeVersionObjectAsync)({
187
+ const runtimeVersionInfoObjects = await (0, publish_1.getRuntimeVersionInfoObjectsAsync)({
186
188
  exp,
187
189
  platforms: realizedPlatforms,
188
190
  projectDir,
@@ -192,23 +194,35 @@ class UpdatePublish extends EasCommand_1.default {
192
194
  },
193
195
  env: undefined,
194
196
  });
195
- const runtimeToPlatformMapping = (0, publish_1.getRuntimeToPlatformMappingFromRuntimeVersions)(runtimeVersions);
197
+ const runtimeToPlatformsAndFingerprintInfoMapping = (0, publish_1.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects)(runtimeVersionInfoObjects);
196
198
  const { branchId } = await (0, queries_1.ensureBranchExistsAsync)(graphqlClient, {
197
199
  appId: projectId,
198
200
  branchName,
199
201
  });
202
+ const runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMapping = await Promise.all(runtimeToPlatformsAndFingerprintInfoMapping.map(async (info) => {
203
+ return {
204
+ ...info,
205
+ fingerprintSource: info.fingerprint
206
+ ? (await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
207
+ runtimeVersion: info.runtimeVersion,
208
+ fingerprint: info.fingerprint,
209
+ graphqlClient,
210
+ })).fingerprintSource ?? null
211
+ : null,
212
+ };
213
+ }));
200
214
  const runtimeVersionToRolloutInfoGroup = rolloutPercentage !== undefined
201
215
  ? await (0, publish_1.getRuntimeToUpdateRolloutInfoGroupMappingAsync)(graphqlClient, {
202
216
  appId: projectId,
203
217
  branchName,
204
218
  rolloutPercentage,
205
- runtimeToPlatformMapping,
219
+ runtimeToPlatformsAndFingerprintInfoMapping,
206
220
  })
207
221
  : undefined;
208
222
  const gitCommitHash = await vcsClient.getCommitHashAsync();
209
223
  const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
210
224
  // Sort the updates into different groups based on their platform specific runtime versions
211
- const updateGroups = runtimeToPlatformMapping.map(({ runtimeVersion, platforms }) => {
225
+ const updateGroups = runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMapping.map(({ runtimeVersion, platforms, fingerprintSource }) => {
212
226
  const localUpdateInfoGroup = Object.fromEntries(platforms.map(platform => [
213
227
  platform,
214
228
  unsortedUpdateInfoGroups[platform],
@@ -226,6 +240,9 @@ class UpdatePublish extends EasCommand_1.default {
226
240
  branchId,
227
241
  updateInfoGroup: localUpdateInfoGroup,
228
242
  rolloutInfoGroup: localRolloutInfoGroup,
243
+ runtimeFingerprintSource: fingerprintSource
244
+ ? (0, graphql_1.transformFingerprintSource)(fingerprintSource)
245
+ : null,
229
246
  runtimeVersion,
230
247
  message: updateMessage,
231
248
  gitCommitHash,
@@ -283,7 +300,7 @@ class UpdatePublish extends EasCommand_1.default {
283
300
  log_1.default.log('👉 Since multiple runtime versions are defined, multiple update groups have been published.');
284
301
  }
285
302
  log_1.default.addNewLineIfNone();
286
- for (const runtime of (0, uniqBy_1.default)(runtimeVersions, version => version.runtimeVersion)) {
303
+ for (const runtime of (0, uniqBy_1.default)(runtimeToPlatformsAndFingerprintInfoMapping, version => version.runtimeVersion)) {
287
304
  const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
288
305
  if (newUpdatesForRuntimeVersion.length === 0) {
289
306
  throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
@@ -75,7 +75,7 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
75
75
  const gitCommitHash = await vcsClient.getCommitHashAsync();
76
76
  const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
77
77
  const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir, vcsClient);
78
- const runtimeVersions = await (0, publish_1.getRuntimeVersionObjectAsync)({
78
+ const runtimeVersionInfoObjects = await (0, publish_1.getRuntimeVersionInfoObjectsAsync)({
79
79
  exp,
80
80
  platforms: realizedPlatforms,
81
81
  projectDir,
@@ -85,6 +85,7 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
85
85
  },
86
86
  env: undefined,
87
87
  });
88
+ const runtimeToPlatformsAndFingerprintInfoMapping = (0, publish_1.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects)(runtimeVersionInfoObjects);
88
89
  let newUpdates;
89
90
  const publishSpinner = (0, ora_1.ora)('Publishing...').start();
90
91
  try {
@@ -95,7 +96,7 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
95
96
  updateMessage,
96
97
  branchId,
97
98
  codeSigningInfo,
98
- runtimeVersions,
99
+ runtimeToPlatformsAndFingerprintInfoMapping,
99
100
  realizedPlatforms,
100
101
  });
101
102
  publishSpinner.succeed('Published!');
@@ -113,7 +114,7 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
113
114
  log_1.default.log('👉 Since multiple runtime versions are defined, multiple update groups have been published.');
114
115
  }
115
116
  log_1.default.addNewLineIfNone();
116
- for (const runtime of (0, uniqBy_1.default)(runtimeVersions, version => version.runtimeVersion)) {
117
+ for (const runtime of (0, uniqBy_1.default)(runtimeToPlatformsAndFingerprintInfoMapping, version => version.runtimeVersion)) {
117
118
  const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
118
119
  if (newUpdatesForRuntimeVersion.length === 0) {
119
120
  throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
@@ -150,11 +151,10 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
150
151
  }
151
152
  }
152
153
  }
153
- async publishRollbacksAsync({ graphqlClient, isGitWorkingTreeDirty, gitCommitHash, updateMessage, branchId, codeSigningInfo, runtimeVersions, realizedPlatforms, }) {
154
- const runtimeToPlatformMapping = (0, publish_1.getRuntimeToPlatformMappingFromRuntimeVersions)(runtimeVersions);
154
+ async publishRollbacksAsync({ graphqlClient, isGitWorkingTreeDirty, gitCommitHash, updateMessage, branchId, codeSigningInfo, runtimeToPlatformsAndFingerprintInfoMapping, realizedPlatforms, }) {
155
155
  const rollbackInfoGroups = Object.fromEntries(realizedPlatforms.map(platform => [platform, true]));
156
156
  // Sort the updates into different groups based on their platform specific runtime versions
157
- const updateGroups = runtimeToPlatformMapping.map(({ runtimeVersion, platforms }) => {
157
+ const updateGroups = runtimeToPlatformsAndFingerprintInfoMapping.map(({ runtimeVersion, platforms }) => {
158
158
  const localRollbackInfoGroup = Object.fromEntries(platforms.map(platform => [platform, rollbackInfoGroups[platform]]));
159
159
  return {
160
160
  branchId,
@@ -0,0 +1,15 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class WorkerDeploy extends EasCommand {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static hidden: boolean;
6
+ static state: string;
7
+ static flags: {};
8
+ static contextDefinition: {
9
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
10
+ projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
11
+ getDynamicPublicProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPublicProjectConfigContextField;
12
+ getDynamicPrivateProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPrivateProjectConfigContextField;
13
+ };
14
+ runAsync(): Promise<void>;
15
+ }
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
7
+ const path = tslib_1.__importStar(require("node:path"));
8
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const log_1 = tslib_1.__importDefault(require("../../log"));
10
+ const ora_1 = require("../../ora");
11
+ const progress_1 = require("../../utils/progress");
12
+ const WorkerAssets = tslib_1.__importStar(require("../../worker/assets"));
13
+ const deployment_1 = require("../../worker/deployment");
14
+ const upload_1 = require("../../worker/upload");
15
+ const isDirectory = (directoryPath) => node_fs_1.default.promises
16
+ .stat(directoryPath)
17
+ .then(stat => stat.isDirectory())
18
+ .catch(() => false);
19
+ class WorkerDeploy extends EasCommand_1.default {
20
+ async runAsync() {
21
+ log_1.default.warn('EAS Worker Deployments are in beta and subject to breaking changes.');
22
+ const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, } = await this.getContextAsync(_a, {
23
+ nonInteractive: true,
24
+ });
25
+ const { projectId, projectDir, exp } = await getDynamicPrivateProjectConfigAsync();
26
+ const distPath = path.resolve(projectDir, 'dist');
27
+ let distServerPath;
28
+ let distClientPath;
29
+ if (exp.web?.output === 'static') {
30
+ distClientPath = distPath;
31
+ distServerPath = null;
32
+ if (!(await isDirectory(distClientPath))) {
33
+ throw new Error(`No "dist/" folder found. Prepare your project for deployment with "npx expo export"`);
34
+ }
35
+ log_1.default.log('Detected "static" worker deployment');
36
+ }
37
+ else if (exp.web?.output === 'server') {
38
+ distClientPath = path.resolve(distPath, 'client');
39
+ distServerPath = path.resolve(distPath, 'server');
40
+ if (!(await isDirectory(distClientPath))) {
41
+ throw new Error(`No "dist/client/" folder found. Prepare your project for deployment with "npx expo export"`);
42
+ }
43
+ else if (!(await isDirectory(distServerPath))) {
44
+ throw new Error(`No "dist/server/" folder found. Prepare your project for deployment with "npx expo export"`);
45
+ }
46
+ log_1.default.log('Detected "server" worker deployment');
47
+ }
48
+ else {
49
+ throw new Error(`Single-page apps are not supported. Ensure that app.json key "expo.web.output" is set to "server" or "static".`);
50
+ }
51
+ async function* emitWorkerTarballAsync(assetMap) {
52
+ yield ['assets.json', JSON.stringify(assetMap)];
53
+ // TODO: Create manifest from user configuration
54
+ const manifest = { env: {} };
55
+ yield ['manifest.json', JSON.stringify(manifest)];
56
+ if (distServerPath) {
57
+ const workerFiles = WorkerAssets.listWorkerFilesAsync(distServerPath);
58
+ for await (const workerFile of workerFiles) {
59
+ yield [`server/${workerFile.normalizedPath}`, workerFile.data];
60
+ }
61
+ }
62
+ }
63
+ async function uploadTarballAsync(tarPath) {
64
+ const uploadUrl = await (0, deployment_1.getSignedDeploymentUrlAsync)(graphqlClient, exp, {
65
+ appId: projectId,
66
+ });
67
+ const { response } = await (0, upload_1.uploadAsync)({
68
+ url: uploadUrl,
69
+ filePath: tarPath,
70
+ compress: false,
71
+ headers: {
72
+ accept: 'application/json',
73
+ },
74
+ });
75
+ if (response.status === 413) {
76
+ throw new Error('Upload failed! (Payload too large)\n' +
77
+ `The files in "dist/server/" (at: ${distServerPath}) exceed the maximum file size (10MB gzip).`);
78
+ }
79
+ else if (!response.ok) {
80
+ throw new Error(`Upload failed! (${response.statusText})`);
81
+ }
82
+ else {
83
+ const json = await response.json();
84
+ if (!json.success || !json.result || typeof json.result !== 'object') {
85
+ throw new Error(json.message ? `Upload failed: ${json.message}` : 'Upload failed!');
86
+ }
87
+ return json.result;
88
+ }
89
+ }
90
+ async function uploadAssetsAsync(assetMap, uploads) {
91
+ if (typeof uploads !== 'object' || !uploads) {
92
+ return;
93
+ }
94
+ // TODO(@kitten): Batch and upload multiple files in parallel
95
+ const uploadParams = [];
96
+ for await (const asset of WorkerAssets.listAssetMapFilesAsync(distClientPath, assetMap)) {
97
+ const uploadURL = uploads[asset.normalizedPath];
98
+ if (uploadURL) {
99
+ uploadParams.push({ url: uploadURL, filePath: asset.path });
100
+ }
101
+ }
102
+ const progress = {
103
+ total: uploadParams.length,
104
+ pending: 0,
105
+ percent: 0,
106
+ transferred: 0,
107
+ };
108
+ const updateProgress = (0, progress_1.createProgressTracker)({
109
+ total: progress.total,
110
+ message(ratio) {
111
+ const percent = `${Math.floor(ratio * 100)}`;
112
+ const details = chalk_1.default.dim(`(${progress.pending} Pending, ${progress.transferred} Completed, ${progress.total} Total)`);
113
+ return `Uploading client assets: ${percent.padStart(3)}% ${details}`;
114
+ },
115
+ completedMessage: 'Uploaded assets for serverless deployment',
116
+ });
117
+ try {
118
+ for await (const signal of (0, upload_1.batchUploadAsync)(uploadParams)) {
119
+ if ('response' in signal) {
120
+ progress.pending--;
121
+ progress.percent = ++progress.transferred / progress.total;
122
+ }
123
+ else {
124
+ progress.pending++;
125
+ }
126
+ updateProgress({ progress });
127
+ }
128
+ }
129
+ catch (error) {
130
+ updateProgress({ isComplete: true, error });
131
+ throw error;
132
+ }
133
+ updateProgress({ isComplete: true });
134
+ }
135
+ let progress = (0, ora_1.ora)('Preparing worker upload');
136
+ let assetMap;
137
+ let tarPath;
138
+ try {
139
+ assetMap = await WorkerAssets.createAssetMapAsync(distClientPath);
140
+ tarPath = await WorkerAssets.packFilesIterableAsync(emitWorkerTarballAsync(assetMap));
141
+ }
142
+ catch (error) {
143
+ progress.fail('Failed to prepare worker upload');
144
+ throw error;
145
+ }
146
+ progress.succeed('Prepared worker upload');
147
+ progress = (0, ora_1.ora)('Creating worker deployment');
148
+ let deployResult;
149
+ try {
150
+ deployResult = await uploadTarballAsync(tarPath);
151
+ }
152
+ catch (error) {
153
+ progress.fail('Failed to create worker deployment');
154
+ throw error;
155
+ }
156
+ progress.succeed('Created worker deployment');
157
+ await uploadAssetsAsync(assetMap, deployResult.uploads);
158
+ const baseDomain = process.env.EXPO_STAGING ? 'staging.expo' : 'expo';
159
+ const deploymentURL = `https://${deployResult.fullName}.${baseDomain}.app`;
160
+ const deploymentsUrl = `https://${baseDomain}.dev/accounts/${exp.owner}/projects/${deployResult.name}/serverless/deployments`;
161
+ log_1.default.addNewLineIfNone();
162
+ log_1.default.log(`🎉 Your worker deployment is ready: ${deploymentURL}`);
163
+ log_1.default.addNewLineIfNone();
164
+ log_1.default.log(`🔗 Manage on EAS: ${deploymentsUrl}`);
165
+ }
166
+ }
167
+ _a = WorkerDeploy;
168
+ WorkerDeploy.description = 'deploy an Expo web build';
169
+ WorkerDeploy.aliases = ['deploy'];
170
+ // TODO(@kitten): Keep command hidden until worker deployments are live
171
+ WorkerDeploy.hidden = true;
172
+ WorkerDeploy.state = 'beta';
173
+ WorkerDeploy.flags = {
174
+ // TODO(@kitten): Allow deployment identifier to be specified
175
+ };
176
+ WorkerDeploy.contextDefinition = {
177
+ ..._a.ContextOptions.DynamicProjectConfig,
178
+ ..._a.ContextOptions.ProjectDir,
179
+ ..._a.ContextOptions.LoggedIn,
180
+ };
181
+ exports.default = WorkerDeploy;