eas-cli 2.6.0 → 2.7.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.
- package/README.md +6 -1133
- package/build/branch/queries.d.ts +8 -1
- package/build/branch/queries.js +50 -1
- package/build/build/android/build.js +1 -0
- package/build/build/ios/build.js +1 -0
- package/build/build/local.js +1 -1
- package/build/build/validate.d.ts +1 -0
- package/build/build/validate.js +121 -1
- package/build/channel/queries.d.ts +11 -0
- package/build/channel/queries.js +46 -1
- package/build/commandUtils/context/contextUtils/getProjectIdAsync.js +1 -1
- package/build/commands/branch/create.d.ts +0 -3
- package/build/commands/branch/create.js +2 -27
- package/build/commands/channel/create.d.ts +0 -7
- package/build/commands/channel/create.js +4 -31
- package/build/commands/update/configure.d.ts +1 -0
- package/build/commands/update/configure.js +10 -218
- package/build/commands/update/index.d.ts +3 -9
- package/build/commands/update/index.js +136 -143
- package/build/graphql/generated.d.ts +26 -17
- package/build/graphql/types/Build.js +1 -0
- package/build/log.d.ts +1 -0
- package/build/log.js +3 -0
- package/build/project/projectUtils.d.ts +3 -1
- package/build/project/projectUtils.js +10 -3
- package/build/project/publish.d.ts +13 -10
- package/build/project/publish.js +68 -38
- package/build/project/workflow.d.ts +1 -0
- package/build/project/workflow.js +9 -1
- package/build/submit/ArchiveSource.js +12 -16
- package/build/update/configure.d.ts +22 -0
- package/build/update/configure.js +200 -0
- package/build/utils/expoCli.d.ts +6 -0
- package/build/utils/expoCli.js +46 -1
- package/build/utils/expodash/memoize.d.ts +2 -0
- package/build/utils/expodash/memoize.js +17 -0
- package/build/utils/image.d.ts +6 -0
- package/build/utils/image.js +107 -0
- package/build/utils/statuspageService.js +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +7 -3
|
@@ -88,10 +88,17 @@ async function validateAppVersionRuntimePolicySupportAsync(projectDir, exp) {
|
|
|
88
88
|
log_1.default.warn(`You need to be on SDK 46 or higher, and use expo-updates >= 0.14.4 to use appVersion runtime policy.`);
|
|
89
89
|
}
|
|
90
90
|
exports.validateAppVersionRuntimePolicySupportAsync = validateAppVersionRuntimePolicySupportAsync;
|
|
91
|
-
async function installExpoUpdatesAsync(projectDir) {
|
|
91
|
+
async function installExpoUpdatesAsync(projectDir, options) {
|
|
92
92
|
log_1.default.log(chalk_1.default.gray `> npx expo install expo-updates`);
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
try {
|
|
94
|
+
await (0, expoCli_1.expoCommandAsync)(projectDir, ['install', 'expo-updates'], { silent: options === null || options === void 0 ? void 0 : options.silent });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (options === null || options === void 0 ? void 0 : options.silent) {
|
|
98
|
+
log_1.default.error('stdout' in error ? error.stdout : error.message);
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
95
102
|
}
|
|
96
103
|
exports.installExpoUpdatesAsync = installExpoUpdatesAsync;
|
|
97
104
|
async function getOwnerAccountForProjectIdAsync(graphqlClient, projectId) {
|
|
@@ -3,12 +3,12 @@ import { ExpoConfig, Platform } from '@expo/config';
|
|
|
3
3
|
import Joi from 'joi';
|
|
4
4
|
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
5
5
|
import { PartialManifestAsset } from '../graphql/generated';
|
|
6
|
-
export declare type
|
|
6
|
+
export declare type ExpoCLIExportPlatformFlag = Platform | 'all';
|
|
7
7
|
declare type Metadata = {
|
|
8
8
|
version: number;
|
|
9
9
|
bundler: 'metro';
|
|
10
10
|
fileMetadata: {
|
|
11
|
-
[key in
|
|
11
|
+
[key in Platform]: {
|
|
12
12
|
assets: {
|
|
13
13
|
path: string;
|
|
14
14
|
ext: string;
|
|
@@ -23,7 +23,7 @@ export declare type RawAsset = {
|
|
|
23
23
|
path: string;
|
|
24
24
|
};
|
|
25
25
|
declare type CollectedAssets = {
|
|
26
|
-
[platform in
|
|
26
|
+
[platform in Platform]?: {
|
|
27
27
|
launchAsset: RawAsset;
|
|
28
28
|
assets: RawAsset[];
|
|
29
29
|
};
|
|
@@ -40,7 +40,7 @@ declare type ManifestFragment = {
|
|
|
40
40
|
extra?: ManifestExtra;
|
|
41
41
|
};
|
|
42
42
|
declare type UpdateInfoGroup = {
|
|
43
|
-
[key in
|
|
43
|
+
[key in Platform]: ManifestFragment;
|
|
44
44
|
};
|
|
45
45
|
export declare const MetadataJoi: Joi.ObjectSchema<any>;
|
|
46
46
|
export declare function guessContentTypeFromExtension(ext?: string): string;
|
|
@@ -58,16 +58,19 @@ export declare function convertAssetToUpdateInfoGroupFormatAsync(asset: RawAsset
|
|
|
58
58
|
* This will be sorted later based on the platform's runtime versions.
|
|
59
59
|
*/
|
|
60
60
|
export declare function buildUnsortedUpdateInfoGroupAsync(assets: CollectedAssets, exp: ExpoConfig): Promise<UpdateInfoGroup>;
|
|
61
|
-
export declare function buildBundlesAsync({ projectDir, inputDir, }: {
|
|
61
|
+
export declare function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }: {
|
|
62
62
|
projectDir: string;
|
|
63
63
|
inputDir: string;
|
|
64
|
+
exp: Pick<ExpoConfig, 'sdkVersion'>;
|
|
65
|
+
platformFlag: ExpoCLIExportPlatformFlag;
|
|
64
66
|
}): Promise<void>;
|
|
65
|
-
export declare function resolveInputDirectoryAsync(
|
|
67
|
+
export declare function resolveInputDirectoryAsync(inputDir: string, { skipBundler }: {
|
|
68
|
+
skipBundler?: boolean;
|
|
69
|
+
}): Promise<string>;
|
|
66
70
|
export declare function loadMetadata(distRoot: string): Metadata;
|
|
67
|
-
export declare function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}): Promise<CollectedAssets>;
|
|
71
|
+
export declare function filterExportedPlatformsByFlag<T extends Partial<Record<Platform, any>>>(record: T, platformFlag: ExpoCLIExportPlatformFlag): T;
|
|
72
|
+
/** Given a directory, load the metadata.json and collect the assets for each platform. */
|
|
73
|
+
export declare function collectAssetsAsync(dir: string): Promise<CollectedAssets>;
|
|
71
74
|
export declare function filterOutAssetsThatAlreadyExistAsync(graphqlClient: ExpoGraphqlClient, uniqueAssetsWithStorageKey: (RawAsset & {
|
|
72
75
|
storageKey: string;
|
|
73
76
|
})[]): Promise<(RawAsset & {
|
package/build/project/publish.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
|
|
3
|
+
exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.filterExportedPlatformsByFlag = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const json_file_1 = tslib_1.__importDefault(require("@expo/json-file"));
|
|
6
6
|
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
@@ -12,6 +12,7 @@ const promise_limit_1 = tslib_1.__importDefault(require("promise-limit"));
|
|
|
12
12
|
const generated_1 = require("../graphql/generated");
|
|
13
13
|
const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
|
|
14
14
|
const PublishQuery_1 = require("../graphql/queries/PublishQuery");
|
|
15
|
+
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
15
16
|
const uploads_1 = require("../uploads");
|
|
16
17
|
const expoCli_1 = require("../utils/expoCli");
|
|
17
18
|
const chunk_1 = tslib_1.__importDefault(require("../utils/expodash/chunk"));
|
|
@@ -21,13 +22,14 @@ const fileMetadataJoi = joi_1.default.object({
|
|
|
21
22
|
.required()
|
|
22
23
|
.items(joi_1.default.object({ path: joi_1.default.string().required(), ext: joi_1.default.string().required() })),
|
|
23
24
|
bundle: joi_1.default.string().required(),
|
|
24
|
-
}).
|
|
25
|
+
}).optional();
|
|
25
26
|
exports.MetadataJoi = joi_1.default.object({
|
|
26
27
|
version: joi_1.default.number().required(),
|
|
27
28
|
bundler: joi_1.default.string().required(),
|
|
28
29
|
fileMetadata: joi_1.default.object({
|
|
29
30
|
android: fileMetadataJoi,
|
|
30
31
|
ios: fileMetadataJoi,
|
|
32
|
+
web: fileMetadataJoi,
|
|
31
33
|
}).required(),
|
|
32
34
|
}).required();
|
|
33
35
|
function guessContentTypeFromExtension(ext) {
|
|
@@ -102,29 +104,44 @@ async function buildUnsortedUpdateInfoGroupAsync(assets, exp) {
|
|
|
102
104
|
return updateInfoGroup;
|
|
103
105
|
}
|
|
104
106
|
exports.buildUnsortedUpdateInfoGroupAsync = buildUnsortedUpdateInfoGroupAsync;
|
|
105
|
-
async function buildBundlesAsync({ projectDir, inputDir, }) {
|
|
107
|
+
async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }) {
|
|
106
108
|
const packageJSON = json_file_1.default.read(path_1.default.resolve(projectDir, 'package.json'));
|
|
107
109
|
if (!packageJSON) {
|
|
108
110
|
throw new Error('Could not locate package.json');
|
|
109
111
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
if ((0, expoCli_1.shouldUseVersionedExpoCLI)(projectDir, exp)) {
|
|
113
|
+
await (0, expoCli_1.expoCommandAsync)(projectDir, [
|
|
114
|
+
'export',
|
|
115
|
+
'--output-dir',
|
|
116
|
+
inputDir,
|
|
117
|
+
'--dump-sourcemap',
|
|
118
|
+
'--platform',
|
|
119
|
+
platformFlag,
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Legacy global Expo CLI
|
|
124
|
+
await (0, expoCli_1.expoCommandAsync)(projectDir, [
|
|
125
|
+
'export',
|
|
126
|
+
'--output-dir',
|
|
127
|
+
inputDir,
|
|
128
|
+
'--experimental-bundle',
|
|
129
|
+
'--non-interactive',
|
|
130
|
+
'--dump-sourcemap',
|
|
131
|
+
'--platform',
|
|
132
|
+
platformFlag,
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
118
135
|
}
|
|
119
136
|
exports.buildBundlesAsync = buildBundlesAsync;
|
|
120
|
-
async function resolveInputDirectoryAsync(
|
|
121
|
-
const distRoot = path_1.default.resolve(
|
|
137
|
+
async function resolveInputDirectoryAsync(inputDir, { skipBundler }) {
|
|
138
|
+
const distRoot = path_1.default.resolve(inputDir);
|
|
122
139
|
if (!(await fs_extra_1.default.pathExists(distRoot))) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
let error = `--input-dir="${inputDir}" not found.`;
|
|
141
|
+
if (skipBundler) {
|
|
142
|
+
error += ` --skip-bundler requires the project to be exported manually before uploading. Ex: npx expo export && eas update --skip-bundler`;
|
|
143
|
+
}
|
|
144
|
+
throw new Error(error);
|
|
128
145
|
}
|
|
129
146
|
return distRoot;
|
|
130
147
|
}
|
|
@@ -143,37 +160,50 @@ function loadMetadata(distRoot) {
|
|
|
143
160
|
if (metadata.bundler !== 'metro') {
|
|
144
161
|
throw new Error('Only bundles created with Metro are currently supported');
|
|
145
162
|
}
|
|
163
|
+
const platforms = Object.keys(metadata.fileMetadata);
|
|
164
|
+
if (platforms.length === 0) {
|
|
165
|
+
log_1.default.warn('No updates were exported for any platform');
|
|
166
|
+
}
|
|
167
|
+
log_1.default.debug(`Loaded ${platforms.length} platform(s): ${platforms.join(', ')}`);
|
|
146
168
|
return metadata;
|
|
147
169
|
}
|
|
148
170
|
exports.loadMetadata = loadMetadata;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
function filterExportedPlatformsByFlag(record, platformFlag) {
|
|
172
|
+
if (platformFlag === 'all') {
|
|
173
|
+
return record;
|
|
174
|
+
}
|
|
175
|
+
const platform = platformFlag;
|
|
176
|
+
if (!record[platform]) {
|
|
177
|
+
throw new Error(`--platform="${platform}" not found in metadata.json. Available platform(s): ${Object.keys(record).join(', ')}`);
|
|
178
|
+
}
|
|
179
|
+
return { [platform]: record[platform] };
|
|
180
|
+
}
|
|
181
|
+
exports.filterExportedPlatformsByFlag = filterExportedPlatformsByFlag;
|
|
182
|
+
/** Given a directory, load the metadata.json and collect the assets for each platform. */
|
|
183
|
+
async function collectAssetsAsync(dir) {
|
|
184
|
+
const metadata = loadMetadata(dir);
|
|
185
|
+
const collectedAssets = {};
|
|
186
|
+
for (const platform of Object.keys(metadata.fileMetadata)) {
|
|
187
|
+
collectedAssets[platform] = {
|
|
155
188
|
launchAsset: {
|
|
156
189
|
fileExtension: '.bundle',
|
|
157
190
|
contentType: 'application/javascript',
|
|
158
|
-
path: path_1.default.resolve(
|
|
191
|
+
path: path_1.default.resolve(dir, metadata.fileMetadata[platform].bundle),
|
|
159
192
|
},
|
|
160
|
-
assets: metadata.fileMetadata[platform].assets.map(asset => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
return {
|
|
167
|
-
fileExtension,
|
|
168
|
-
contentType: guessContentTypeFromExtension(asset.ext),
|
|
169
|
-
path: path_1.default.join(distRoot, asset.path),
|
|
170
|
-
};
|
|
171
|
-
}),
|
|
193
|
+
assets: metadata.fileMetadata[platform].assets.map(asset => ({
|
|
194
|
+
fileExtension: asset.ext ? ensureLeadingPeriod(asset.ext) : undefined,
|
|
195
|
+
contentType: guessContentTypeFromExtension(asset.ext),
|
|
196
|
+
path: path_1.default.join(dir, asset.path),
|
|
197
|
+
})),
|
|
172
198
|
};
|
|
173
199
|
}
|
|
174
|
-
return
|
|
200
|
+
return collectedAssets;
|
|
175
201
|
}
|
|
176
202
|
exports.collectAssetsAsync = collectAssetsAsync;
|
|
203
|
+
// ensure the file extension has a '.' prefix
|
|
204
|
+
function ensureLeadingPeriod(extension) {
|
|
205
|
+
return extension.startsWith('.') ? extension : `.${extension}`;
|
|
206
|
+
}
|
|
177
207
|
async function filterOutAssetsThatAlreadyExistAsync(graphqlClient, uniqueAssetsWithStorageKey) {
|
|
178
208
|
const assetMetadata = await PublishQuery_1.PublishQuery.getAssetMetadataAsync(graphqlClient, uniqueAssetsWithStorageKey.map(asset => asset.storageKey));
|
|
179
209
|
const missingAssetKeys = assetMetadata
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
|
2
2
|
export declare function resolveWorkflowAsync(projectDir: string, platform: Platform): Promise<Workflow>;
|
|
3
|
+
export declare function resolveWorkflowPerPlatformAsync(projectDir: string): Promise<Record<Platform, Workflow>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveWorkflowAsync = void 0;
|
|
3
|
+
exports.resolveWorkflowPerPlatformAsync = exports.resolveWorkflowAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
6
6
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
@@ -32,3 +32,11 @@ async function resolveWorkflowAsync(projectDir, platform) {
|
|
|
32
32
|
return eas_build_job_1.Workflow.MANAGED;
|
|
33
33
|
}
|
|
34
34
|
exports.resolveWorkflowAsync = resolveWorkflowAsync;
|
|
35
|
+
async function resolveWorkflowPerPlatformAsync(projectDir) {
|
|
36
|
+
const [android, ios] = await Promise.all([
|
|
37
|
+
resolveWorkflowAsync(projectDir, eas_build_job_1.Platform.ANDROID),
|
|
38
|
+
resolveWorkflowAsync(projectDir, eas_build_job_1.Platform.IOS),
|
|
39
|
+
]);
|
|
40
|
+
return { android, ios };
|
|
41
|
+
}
|
|
42
|
+
exports.resolveWorkflowPerPlatformAsync = resolveWorkflowPerPlatformAsync;
|
|
@@ -6,12 +6,12 @@ const eas_build_job_1 = require("@expo/eas-build-job");
|
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const url_1 = require("url");
|
|
8
8
|
const uuid = tslib_1.__importStar(require("uuid"));
|
|
9
|
-
const generated_1 = require("../graphql/generated");
|
|
10
9
|
const BuildQuery_1 = require("../graphql/queries/BuildQuery");
|
|
11
10
|
const AppPlatform_1 = require("../graphql/types/AppPlatform");
|
|
12
11
|
const log_1 = tslib_1.__importStar(require("../log"));
|
|
13
12
|
const platform_1 = require("../platform");
|
|
14
13
|
const prompts_1 = require("../prompts");
|
|
14
|
+
const date_1 = require("../utils/date");
|
|
15
15
|
const builds_1 = require("./utils/builds");
|
|
16
16
|
const files_1 = require("./utils/files");
|
|
17
17
|
exports.BUILD_LIST_ITEM_COUNT = 4;
|
|
@@ -187,26 +187,22 @@ async function handleBuildListSourceAsync(graphqlClient, source) {
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
function formatBuildChoice(build, expiryDate) {
|
|
190
|
-
const { id,
|
|
190
|
+
const { id, updatedAt, runtimeVersion, buildProfile, gitCommitHash, gitCommitMessage, channel } = build;
|
|
191
191
|
const formatValue = (field) => field ? chalk_1.default.bold(field) : chalk_1.default.dim('Unknown');
|
|
192
192
|
const buildDate = new Date(updatedAt);
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const title =
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
]
|
|
203
|
-
.filter(it => it != null)
|
|
204
|
-
.join(', '),
|
|
205
|
-
`\tProfile: ${formatValue(buildProfile)}, Release channel: ${formatValue(releaseChannel)}`,
|
|
206
|
-
`\tAuthored by: ${formatValue(initiatingActor === null || initiatingActor === void 0 ? void 0 : initiatingActor.displayName)}`,
|
|
193
|
+
const formattedCommitData = gitCommitHash && gitCommitMessage
|
|
194
|
+
? `${chalk_1.default.dim(gitCommitHash.slice(0, 7))} "${chalk_1.default.bold(gitCommitMessage)}"`
|
|
195
|
+
: 'Unknown';
|
|
196
|
+
const title = `ID: ${chalk_1.default.dim(id)} (${chalk_1.default.dim(`${(0, date_1.fromNow)(buildDate)} ago`)})`;
|
|
197
|
+
const description = [
|
|
198
|
+
`\tProfile: ${formatValue(buildProfile)}`,
|
|
199
|
+
`\tChannel: ${formatValue(channel)}`,
|
|
200
|
+
`\tRuntime version: ${formatValue(runtimeVersion)}`,
|
|
201
|
+
`\tCommit: ${formattedCommitData}`,
|
|
207
202
|
].join('\n');
|
|
208
203
|
return {
|
|
209
204
|
title,
|
|
205
|
+
description,
|
|
210
206
|
value: build,
|
|
211
207
|
disabled: buildDate < expiryDate,
|
|
212
208
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
3
|
+
import { RequestedPlatform } from '../platform';
|
|
4
|
+
export declare const DEFAULT_MANAGED_RUNTIME_VERSION: {
|
|
5
|
+
readonly policy: "sdkVersion";
|
|
6
|
+
};
|
|
7
|
+
export declare const DEFAULT_BARE_RUNTIME_VERSION: "1.0.0";
|
|
8
|
+
/**
|
|
9
|
+
* Make sure EAS Update is fully configured in the current project.
|
|
10
|
+
* This goes over a checklist and performs the following checks or changes:
|
|
11
|
+
* - Enure the `expo-updates` package is currently installed.
|
|
12
|
+
* - Ensure `app.json` is configured for EAS Updates
|
|
13
|
+
* - Sets `runtimeVersion` if not set
|
|
14
|
+
* - Sets `updates.url` if not set
|
|
15
|
+
* - Ensure latest changes are reflected in the native config, if any
|
|
16
|
+
*/
|
|
17
|
+
export declare function ensureEASUpdatesIsConfiguredAsync(graphqlClient: ExpoGraphqlClient, { exp: expWithoutUpdates, projectId, projectDir, platform, }: {
|
|
18
|
+
exp: ExpoConfig;
|
|
19
|
+
projectId: string;
|
|
20
|
+
projectDir: string;
|
|
21
|
+
platform: RequestedPlatform | null;
|
|
22
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureEASUpdatesIsConfiguredAsync = exports.DEFAULT_BARE_RUNTIME_VERSION = exports.DEFAULT_MANAGED_RUNTIME_VERSION = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_1 = require("@expo/config");
|
|
6
|
+
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const api_1 = require("../api");
|
|
9
|
+
const generated_1 = require("../graphql/generated");
|
|
10
|
+
const log_1 = tslib_1.__importStar(require("../log"));
|
|
11
|
+
const platform_1 = require("../platform");
|
|
12
|
+
const projectUtils_1 = require("../project/projectUtils");
|
|
13
|
+
const workflow_1 = require("../project/workflow");
|
|
14
|
+
const UpdatesModule_1 = require("./android/UpdatesModule");
|
|
15
|
+
const UpdatesModule_2 = require("./ios/UpdatesModule");
|
|
16
|
+
exports.DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'sdkVersion' };
|
|
17
|
+
exports.DEFAULT_BARE_RUNTIME_VERSION = '1.0.0';
|
|
18
|
+
function getDefaultRuntimeVersion(workflow) {
|
|
19
|
+
return workflow === eas_build_job_1.Workflow.GENERIC
|
|
20
|
+
? exports.DEFAULT_BARE_RUNTIME_VERSION
|
|
21
|
+
: exports.DEFAULT_MANAGED_RUNTIME_VERSION;
|
|
22
|
+
}
|
|
23
|
+
function isRuntimeEqual(runtimeVersionA, runtimeVersionB) {
|
|
24
|
+
if (typeof runtimeVersionA === 'string' && typeof runtimeVersionB === 'string') {
|
|
25
|
+
return runtimeVersionA === runtimeVersionB;
|
|
26
|
+
}
|
|
27
|
+
else if (typeof runtimeVersionA === 'object' && typeof runtimeVersionB === 'object') {
|
|
28
|
+
return runtimeVersionA.policy === runtimeVersionB.policy;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function replaceUndefinedObjectValues(value, replacement) {
|
|
35
|
+
for (const key in value) {
|
|
36
|
+
if (value[key] === undefined) {
|
|
37
|
+
value[key] = replacement;
|
|
38
|
+
}
|
|
39
|
+
else if (typeof value[key] === 'object') {
|
|
40
|
+
value[key] = replaceUndefinedObjectValues(value[key], replacement);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Partially merge the EAS Update config with the existing Expo config.
|
|
47
|
+
* This preserves and merges the nested update-related properties.
|
|
48
|
+
*/
|
|
49
|
+
function mergeExpoConfig(exp, modifyExp) {
|
|
50
|
+
var _a;
|
|
51
|
+
return {
|
|
52
|
+
runtimeVersion: (_a = modifyExp.runtimeVersion) !== null && _a !== void 0 ? _a : exp.runtimeVersion,
|
|
53
|
+
updates: { ...exp.updates, ...modifyExp.updates },
|
|
54
|
+
android: {
|
|
55
|
+
...exp.android,
|
|
56
|
+
...modifyExp.android,
|
|
57
|
+
},
|
|
58
|
+
ios: {
|
|
59
|
+
...exp.ios,
|
|
60
|
+
...modifyExp.ios,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Make sure the `app.json` is configured to use EAS Updates.
|
|
66
|
+
* This does a couple of things:
|
|
67
|
+
* - Ensure update URL is set to the project EAS endpoint
|
|
68
|
+
* - Ensure runtimeVersion is defined for both or individual platforms
|
|
69
|
+
* - Output the changes made, or the changes required to make manually
|
|
70
|
+
*/
|
|
71
|
+
async function ensureEASUpdatesIsConfiguredInExpoConfigAsync({ exp, projectId, projectDir, platform, workflows, }) {
|
|
72
|
+
var _a, _b, _c, _d, _e, _f;
|
|
73
|
+
const modifyConfig = {};
|
|
74
|
+
if (((_a = exp.updates) === null || _a === void 0 ? void 0 : _a.url) !== (0, api_1.getEASUpdateURL)(projectId)) {
|
|
75
|
+
modifyConfig.updates = { url: (0, api_1.getEASUpdateURL)(projectId) };
|
|
76
|
+
}
|
|
77
|
+
let androidRuntimeVersion = (_c = (_b = exp.android) === null || _b === void 0 ? void 0 : _b.runtimeVersion) !== null && _c !== void 0 ? _c : exp.runtimeVersion;
|
|
78
|
+
let iosRuntimeVersion = (_e = (_d = exp.ios) === null || _d === void 0 ? void 0 : _d.runtimeVersion) !== null && _e !== void 0 ? _e : exp.runtimeVersion;
|
|
79
|
+
if ((['all', 'android'].includes(platform) && !androidRuntimeVersion) ||
|
|
80
|
+
(['all', 'ios'].includes(platform) && !iosRuntimeVersion)) {
|
|
81
|
+
androidRuntimeVersion = androidRuntimeVersion !== null && androidRuntimeVersion !== void 0 ? androidRuntimeVersion : getDefaultRuntimeVersion(workflows.android);
|
|
82
|
+
iosRuntimeVersion = iosRuntimeVersion !== null && iosRuntimeVersion !== void 0 ? iosRuntimeVersion : getDefaultRuntimeVersion(workflows.ios);
|
|
83
|
+
if (platform === 'all' && isRuntimeEqual(androidRuntimeVersion, iosRuntimeVersion)) {
|
|
84
|
+
modifyConfig.runtimeVersion = androidRuntimeVersion;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
if (['all', 'android'].includes(platform)) {
|
|
88
|
+
modifyConfig.runtimeVersion = undefined;
|
|
89
|
+
modifyConfig.android = { runtimeVersion: androidRuntimeVersion };
|
|
90
|
+
}
|
|
91
|
+
if (['all', 'ios'].includes(platform)) {
|
|
92
|
+
modifyConfig.runtimeVersion = undefined;
|
|
93
|
+
modifyConfig.ios = { runtimeVersion: iosRuntimeVersion };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (Object.keys(modifyConfig).length === 0) {
|
|
98
|
+
return { exp, projectChanged: false };
|
|
99
|
+
}
|
|
100
|
+
const mergedExp = mergeExpoConfig(exp, modifyConfig);
|
|
101
|
+
const result = await (0, config_1.modifyConfigAsync)(projectDir, mergedExp);
|
|
102
|
+
switch (result.type) {
|
|
103
|
+
case 'success':
|
|
104
|
+
logEasUpdatesAutoConfig({ exp, modifyConfig });
|
|
105
|
+
return {
|
|
106
|
+
projectChanged: true,
|
|
107
|
+
// TODO(cedric): fix return type of `modifyConfigAsync` to avoid `null` for type === success repsonses
|
|
108
|
+
exp: (_f = result.config) === null || _f === void 0 ? void 0 : _f.expo,
|
|
109
|
+
};
|
|
110
|
+
case 'warn':
|
|
111
|
+
warnEASUpdatesManualConfig({ modifyConfig, workflows });
|
|
112
|
+
throw new Error(result.message);
|
|
113
|
+
case 'fail':
|
|
114
|
+
throw new Error(result.message);
|
|
115
|
+
default:
|
|
116
|
+
throw new Error(`Unexpected result type "${result.type}" received when modifying the project config.`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function logEasUpdatesAutoConfig({ modifyConfig, exp, }) {
|
|
120
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
121
|
+
if ((_a = modifyConfig.updates) === null || _a === void 0 ? void 0 : _a.url) {
|
|
122
|
+
log_1.default.withTick(((_b = exp.updates) === null || _b === void 0 ? void 0 : _b.url)
|
|
123
|
+
? `Overwrote updates.url "${exp.updates.url}" with "${modifyConfig.updates.url}"`
|
|
124
|
+
: `Configured updates.url to "${modifyConfig.updates.url}"`);
|
|
125
|
+
}
|
|
126
|
+
if ((_d = (_c = modifyConfig.android) === null || _c === void 0 ? void 0 : _c.runtimeVersion) !== null && _d !== void 0 ? _d : modifyConfig.runtimeVersion) {
|
|
127
|
+
log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Android]} with "${JSON.stringify((_f = (_e = modifyConfig.android) === null || _e === void 0 ? void 0 : _e.runtimeVersion) !== null && _f !== void 0 ? _f : modifyConfig.runtimeVersion)}"`);
|
|
128
|
+
}
|
|
129
|
+
if ((_h = (_g = modifyConfig.ios) === null || _g === void 0 ? void 0 : _g.runtimeVersion) !== null && _h !== void 0 ? _h : modifyConfig.runtimeVersion) {
|
|
130
|
+
log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Ios]} with "${JSON.stringify((_k = (_j = modifyConfig.ios) === null || _j === void 0 ? void 0 : _j.runtimeVersion) !== null && _k !== void 0 ? _k : modifyConfig.runtimeVersion)}"`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function warnEASUpdatesManualConfig({ modifyConfig, workflows, }) {
|
|
134
|
+
log_1.default.addNewLineIfNone();
|
|
135
|
+
log_1.default.warn(`It looks like you are using a dynamic configuration! ${(0, log_1.learnMore)('https://docs.expo.dev/workflow/configuration/#dynamic-configuration-with-appconfigjs)')}`);
|
|
136
|
+
log_1.default.warn(`Finish configuring EAS Update by adding the following to the project app.config.js:\n${(0, log_1.learnMore)('https://expo.fyi/eas-update-config')}\n`);
|
|
137
|
+
log_1.default.log(chalk_1.default.bold(JSON.stringify(replaceUndefinedObjectValues(modifyConfig, '<remove this key>'), null, 2)));
|
|
138
|
+
log_1.default.addNewLineIfNone();
|
|
139
|
+
if (workflows.android === eas_build_job_1.Workflow.GENERIC || workflows.ios === eas_build_job_1.Workflow.GENERIC) {
|
|
140
|
+
log_1.default.warn((0, chalk_1.default) `The native config files {bold Expo.plist & AndroidManifest.xml} must be updated to support EAS Update. ${(0, log_1.learnMore)('https://expo.fyi/eas-update-config.md#native-configuration')}`);
|
|
141
|
+
}
|
|
142
|
+
log_1.default.addNewLineIfNone();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Make sure that the current `app.json` configuration for EAS Updates is set natively.
|
|
146
|
+
*/
|
|
147
|
+
async function ensureEASUpdatesIsConfiguredNativelyAsync(graphqlClient, { exp, projectId, projectDir, platform, workflows, }) {
|
|
148
|
+
if (['all', 'android'].includes(platform) && workflows.android === eas_build_job_1.Workflow.GENERIC) {
|
|
149
|
+
await (0, UpdatesModule_1.syncUpdatesConfigurationAsync)(graphqlClient, projectDir, exp, projectId);
|
|
150
|
+
log_1.default.withTick(`Configured ${chalk_1.default.bold('AndroidManifest.xml')} for EAS Update`);
|
|
151
|
+
}
|
|
152
|
+
if (['all', 'ios'].includes(platform) && workflows.ios === eas_build_job_1.Workflow.GENERIC) {
|
|
153
|
+
await (0, UpdatesModule_2.syncUpdatesConfigurationAsync)(graphqlClient, projectDir, exp, projectId);
|
|
154
|
+
log_1.default.withTick(`Configured ${chalk_1.default.bold('Expo.plist')} for EAS Update`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Make sure EAS Update is fully configured in the current project.
|
|
159
|
+
* This goes over a checklist and performs the following checks or changes:
|
|
160
|
+
* - Enure the `expo-updates` package is currently installed.
|
|
161
|
+
* - Ensure `app.json` is configured for EAS Updates
|
|
162
|
+
* - Sets `runtimeVersion` if not set
|
|
163
|
+
* - Sets `updates.url` if not set
|
|
164
|
+
* - Ensure latest changes are reflected in the native config, if any
|
|
165
|
+
*/
|
|
166
|
+
async function ensureEASUpdatesIsConfiguredAsync(graphqlClient, { exp: expWithoutUpdates, projectId, projectDir, platform, }) {
|
|
167
|
+
const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, expWithoutUpdates.sdkVersion);
|
|
168
|
+
if (!hasExpoUpdates) {
|
|
169
|
+
await (0, projectUtils_1.installExpoUpdatesAsync)(projectDir, { silent: !log_1.default.isDebug });
|
|
170
|
+
log_1.default.withTick('Installed expo updates');
|
|
171
|
+
}
|
|
172
|
+
// Bail out if using a platform that doesn't require runtime versions
|
|
173
|
+
// or native setup, i.e. web.
|
|
174
|
+
if (!platform) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir);
|
|
178
|
+
const { projectChanged, exp: expWithUpdates } = await ensureEASUpdatesIsConfiguredInExpoConfigAsync({
|
|
179
|
+
exp: expWithoutUpdates,
|
|
180
|
+
projectDir,
|
|
181
|
+
projectId,
|
|
182
|
+
platform,
|
|
183
|
+
workflows,
|
|
184
|
+
});
|
|
185
|
+
if (projectChanged || !hasExpoUpdates) {
|
|
186
|
+
await ensureEASUpdatesIsConfiguredNativelyAsync(graphqlClient, {
|
|
187
|
+
exp: expWithUpdates,
|
|
188
|
+
projectDir,
|
|
189
|
+
projectId,
|
|
190
|
+
platform,
|
|
191
|
+
workflows,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
if (projectChanged) {
|
|
195
|
+
log_1.default.addNewLineIfNone();
|
|
196
|
+
log_1.default.warn(`All builds of your app going forward will be eligible to receive updates published with EAS Update.`);
|
|
197
|
+
log_1.default.newLine();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.ensureEASUpdatesIsConfiguredAsync = ensureEASUpdatesIsConfiguredAsync;
|
package/build/utils/expoCli.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
/**
|
|
3
|
+
* @returns `true` if the project is SDK +46, has `@expo/cli`, and `EXPO_USE_LOCAL_CLI` is not set to a _false_ value.
|
|
4
|
+
*/
|
|
5
|
+
export declare function shouldUseVersionedExpoCLIExpensive(projectDir: string, exp: Pick<ExpoConfig, 'sdkVersion'>): boolean;
|
|
6
|
+
export declare const shouldUseVersionedExpoCLI: typeof shouldUseVersionedExpoCLIExpensive;
|
|
1
7
|
export declare function expoCommandAsync(projectDir: string, args: string[], { silent }?: {
|
|
2
8
|
silent?: boolean;
|
|
3
9
|
}): Promise<void>;
|
package/build/utils/expoCli.js
CHANGED
|
@@ -1,11 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.expoCommandAsync = void 0;
|
|
3
|
+
exports.expoCommandAsync = exports.shouldUseVersionedExpoCLI = exports.shouldUseVersionedExpoCLIExpensive = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const getenv_1 = require("getenv");
|
|
7
8
|
const resolve_from_1 = tslib_1.__importDefault(require("resolve-from"));
|
|
9
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
8
10
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
11
|
+
const memoize_1 = require("./expodash/memoize");
|
|
12
|
+
// Aggressively returns `true` (UNVERSIONED, invalid SDK version format) to push users towards the versioned CLI.
|
|
13
|
+
function gteSdkVersion(fromSdkVersion, sdkVersion) {
|
|
14
|
+
if (fromSdkVersion === 'UNVERSIONED') {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
return semver_1.default.gte(fromSdkVersion, sdkVersion);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @returns `true` if the project is SDK +46, has `@expo/cli`, and `EXPO_USE_LOCAL_CLI` is not set to a _false_ value.
|
|
26
|
+
*/
|
|
27
|
+
function shouldUseVersionedExpoCLIExpensive(projectDir, exp) {
|
|
28
|
+
// Users can disable local CLI settings EXPO_USE_LOCAL_CLI=false
|
|
29
|
+
// https://github.com/expo/expo/blob/69eddda7bb1dbfab44258f468cf7f22984c1e44e/packages/expo/bin/cli.js#L10
|
|
30
|
+
// Run the environment variable check first as it's the cheapest.
|
|
31
|
+
const userDefinedVersionedCliEnabled = (0, getenv_1.boolish)('EXPO_USE_LOCAL_CLI', true);
|
|
32
|
+
if (!userDefinedVersionedCliEnabled) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
// NOTE(EvanBacon): The CLI package could be available through a monorepo
|
|
37
|
+
// we need to ensure the project is specifically using a known supported Expo SDK version.
|
|
38
|
+
if (
|
|
39
|
+
// If the version isn't defined then skip the check.
|
|
40
|
+
// Users running in a non-standard way should use the latest supported behavior (local CLI).
|
|
41
|
+
exp.sdkVersion &&
|
|
42
|
+
!gteSdkVersion(exp.sdkVersion, '46.0.0')) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
log_1.default.debug('Error detecting Expo SDK version for enabling versioned Expo CLI:', error);
|
|
48
|
+
}
|
|
49
|
+
// Finally ensure the CLI is available for sanity.
|
|
50
|
+
return !!resolve_from_1.default.silent(projectDir, '@expo/cli');
|
|
51
|
+
}
|
|
52
|
+
exports.shouldUseVersionedExpoCLIExpensive = shouldUseVersionedExpoCLIExpensive;
|
|
53
|
+
exports.shouldUseVersionedExpoCLI = (0, memoize_1.memoize)(shouldUseVersionedExpoCLIExpensive);
|
|
9
54
|
async function expoCommandAsync(projectDir, args, { silent = false } = {}) {
|
|
10
55
|
const expoCliPath = (0, resolve_from_1.default)(projectDir, 'expo/bin/cli.js');
|
|
11
56
|
const spawnPromise = (0, spawn_async_1.default)(expoCliPath, args, {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memoize = void 0;
|
|
4
|
+
/** `lodash.memoize` */
|
|
5
|
+
function memoize(fn) {
|
|
6
|
+
const cache = {};
|
|
7
|
+
return ((...args) => {
|
|
8
|
+
const key = JSON.stringify(args);
|
|
9
|
+
if (cache[key]) {
|
|
10
|
+
return cache[key];
|
|
11
|
+
}
|
|
12
|
+
const result = fn(...args);
|
|
13
|
+
cache[key] = result;
|
|
14
|
+
return result;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
exports.memoize = memoize;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare class ImageNonPngError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export declare class ImageTransparencyError extends Error {
|
|
4
|
+
}
|
|
5
|
+
export declare function ensurePNGIsNotTransparentAsync(imagePathOrURL: string): Promise<void>;
|
|
6
|
+
export declare function isPNGAsync(imagePathOrURL: string): Promise<boolean>;
|