eas-cli 12.0.0 → 12.1.1
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 +60 -60
- package/build/build/build.js +8 -45
- package/build/build/evaluateConfigWithEnvVarsAsync.d.ts +2 -1
- package/build/build/evaluateConfigWithEnvVarsAsync.js +31 -9
- package/build/build/graphql.d.ts +2 -1
- package/build/build/graphql.js +13 -2
- package/build/build/runBuildAndSubmit.js +1 -1
- package/build/commands/build/resign.js +1 -0
- package/build/commands/build/version/get.js +1 -0
- package/build/commands/build/version/set.js +1 -0
- package/build/commands/build/version/sync.js +1 -0
- package/build/commands/config.js +1 -0
- package/build/commands/update/index.js +22 -5
- package/build/commands/update/roll-back-to-embedded.js +6 -6
- package/build/commands/worker/deploy.d.ts +15 -0
- package/build/commands/worker/deploy.js +181 -0
- package/build/graphql/generated.d.ts +301 -53
- package/build/graphql/generated.js +72 -12
- package/build/project/ios/target.js +1 -1
- package/build/project/maybeUploadFingerprintAsync.d.ts +15 -0
- package/build/project/maybeUploadFingerprintAsync.js +57 -0
- package/build/project/publish.d.ts +16 -11
- package/build/project/publish.js +33 -30
- package/build/project/resolveRuntimeVersionAsync.d.ts +13 -0
- package/build/project/resolveRuntimeVersionAsync.js +21 -17
- package/build/worker/assets.d.ts +25 -0
- package/build/worker/assets.js +110 -0
- package/build/worker/deployment.d.ts +6 -0
- package/build/worker/deployment.js +57 -0
- package/build/worker/mutations.d.ts +11 -0
- package/build/worker/mutations.js +45 -0
- package/build/worker/upload.d.ts +20 -0
- package/build/worker/upload.js +141 -0
- package/oclif.manifest.json +22 -1
- package/package.json +5 -2
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSignedDeploymentUrlAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const mutations_1 = require("./mutations");
|
|
6
|
+
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
7
|
+
const prompts_1 = require("../prompts");
|
|
8
|
+
async function getSignedDeploymentUrlAsync(graphqlClient, exp, deploymentVariables) {
|
|
9
|
+
try {
|
|
10
|
+
return await mutations_1.DeploymentsMutation.createSignedDeploymentUrlAsync(graphqlClient, deploymentVariables);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
const isMissingDevDomain = error?.graphQLErrors?.some(e => ['APP_NO_DEV_DOMAIN_NAME'].includes(e?.extensions?.errorCode));
|
|
14
|
+
if (!isMissingDevDomain) {
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
await chooseDevDomainNameAsync({
|
|
18
|
+
graphqlClient,
|
|
19
|
+
appId: deploymentVariables.appId,
|
|
20
|
+
slug: exp.slug,
|
|
21
|
+
});
|
|
22
|
+
return await mutations_1.DeploymentsMutation.createSignedDeploymentUrlAsync(graphqlClient, deploymentVariables);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.getSignedDeploymentUrlAsync = getSignedDeploymentUrlAsync;
|
|
26
|
+
async function chooseDevDomainNameAsync({ graphqlClient, appId, slug, }) {
|
|
27
|
+
const validationMessage = 'The project does not have a dev domain name.';
|
|
28
|
+
const { name } = await (0, prompts_1.promptAsync)({
|
|
29
|
+
type: 'text',
|
|
30
|
+
name: 'name',
|
|
31
|
+
message: 'Choose a dev domain name for your project:',
|
|
32
|
+
validate: value => (value && value.length > 3 ? true : validationMessage),
|
|
33
|
+
initial: slug,
|
|
34
|
+
});
|
|
35
|
+
if (!name) {
|
|
36
|
+
throw new Error('Prompt failed');
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const success = await mutations_1.DeploymentsMutation.assignDevDomainNameAsync(graphqlClient, {
|
|
40
|
+
appId,
|
|
41
|
+
name,
|
|
42
|
+
});
|
|
43
|
+
if (!success) {
|
|
44
|
+
throw new Error('Failed to assign dev domain name');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const isChosenNameTaken = error?.graphQLErrors?.some(e => ['DEV_DOMAIN_NAME_TAKEN'].includes(e?.extensions?.errorCode));
|
|
49
|
+
if (isChosenNameTaken) {
|
|
50
|
+
log_1.default.error(`The entered dev domain name "${name}" is taken. Choose a different name.`);
|
|
51
|
+
await chooseDevDomainNameAsync({ graphqlClient, appId, slug });
|
|
52
|
+
}
|
|
53
|
+
if (!isChosenNameTaken) {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
|
+
export declare const DeploymentsMutation: {
|
|
3
|
+
createSignedDeploymentUrlAsync(graphqlClient: ExpoGraphqlClient, deploymentVariables: {
|
|
4
|
+
appId: string;
|
|
5
|
+
deploymentIdentifier?: string | null;
|
|
6
|
+
}): Promise<string>;
|
|
7
|
+
assignDevDomainNameAsync(graphqlClient: ExpoGraphqlClient, devDomainNameVariables: {
|
|
8
|
+
appId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}): Promise<boolean>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeploymentsMutation = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
|
+
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
|
7
|
+
const client_1 = require("../graphql/client");
|
|
8
|
+
exports.DeploymentsMutation = {
|
|
9
|
+
async createSignedDeploymentUrlAsync(graphqlClient, deploymentVariables) {
|
|
10
|
+
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
11
|
+
.mutation((0, graphql_tag_1.default) `
|
|
12
|
+
mutation createDeploymentUrlMutation($appId: ID!, $deploymentIdentifier: ID) {
|
|
13
|
+
deployments {
|
|
14
|
+
createSignedDeploymentUrl(
|
|
15
|
+
appId: $appId
|
|
16
|
+
deploymentIdentifier: $deploymentIdentifier
|
|
17
|
+
) {
|
|
18
|
+
pendingWorkerDeploymentId
|
|
19
|
+
deploymentIdentifier
|
|
20
|
+
url
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
`, deploymentVariables)
|
|
25
|
+
.toPromise());
|
|
26
|
+
const url = data.deployments?.createSignedDeploymentUrl.url;
|
|
27
|
+
(0, assert_1.default)(url, 'Deployment URL must be defined');
|
|
28
|
+
return url;
|
|
29
|
+
},
|
|
30
|
+
async assignDevDomainNameAsync(graphqlClient, devDomainNameVariables) {
|
|
31
|
+
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
32
|
+
.mutation((0, graphql_tag_1.default) `
|
|
33
|
+
mutation AssignDevDomainName($appId: ID!, $name: DevDomainName!) {
|
|
34
|
+
devDomainName {
|
|
35
|
+
assignDevDomainName(appId: $appId, name: $name) {
|
|
36
|
+
id
|
|
37
|
+
name
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`, devDomainNameVariables)
|
|
42
|
+
.toPromise());
|
|
43
|
+
return data.devDomainName.assignDevDomainName.name === devDomainNameVariables.name;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HeadersInit, RequestInit, Response } from 'node-fetch';
|
|
2
|
+
export interface UploadParams extends Omit<RequestInit, 'signal' | 'body'> {
|
|
3
|
+
filePath: string;
|
|
4
|
+
compress?: boolean;
|
|
5
|
+
url: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
headers?: HeadersInit;
|
|
8
|
+
body?: undefined;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export interface UploadResult {
|
|
12
|
+
params: UploadParams;
|
|
13
|
+
response: Response;
|
|
14
|
+
}
|
|
15
|
+
export declare function uploadAsync(params: UploadParams): Promise<UploadResult>;
|
|
16
|
+
export interface UploadPending {
|
|
17
|
+
params: UploadParams;
|
|
18
|
+
}
|
|
19
|
+
export type BatchUploadSignal = UploadResult | UploadPending;
|
|
20
|
+
export declare function batchUploadAsync(uploads: readonly UploadParams[]): AsyncGenerator<BatchUploadSignal>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.batchUploadAsync = exports.uploadAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const https = tslib_1.__importStar(require("https"));
|
|
6
|
+
const https_proxy_agent_1 = tslib_1.__importDefault(require("https-proxy-agent"));
|
|
7
|
+
const mime_1 = tslib_1.__importDefault(require("mime"));
|
|
8
|
+
const minizlib_1 = require("minizlib");
|
|
9
|
+
const node_fetch_1 = tslib_1.__importStar(require("node-fetch"));
|
|
10
|
+
const node_fs_1 = tslib_1.__importStar(require("node:fs"));
|
|
11
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
12
|
+
const promise_retry_1 = tslib_1.__importDefault(require("promise-retry"));
|
|
13
|
+
const MAX_RETRIES = 4;
|
|
14
|
+
const MAX_CONCURRENCY = 10;
|
|
15
|
+
const MIN_RETRY_TIMEOUT = 100;
|
|
16
|
+
const MAX_UPLOAD_SIZE = 5e8; // 5MB
|
|
17
|
+
const MIN_COMPRESSION_SIZE = 5e4; // 50kB
|
|
18
|
+
const isCompressible = (contentType, size) => {
|
|
19
|
+
if (size < MIN_COMPRESSION_SIZE) {
|
|
20
|
+
// Don't compress small files
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
else if (contentType && /^(?:audio|video|image)\//i.test(contentType)) {
|
|
24
|
+
// Never compress images, audio, or videos as they're presumably precompressed
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
else if (contentType && /^application\//i.test(contentType)) {
|
|
28
|
+
// Only compress `application/` files if they're marked as XML/JSON/JS
|
|
29
|
+
return /(?:xml|json5?|javascript)$/i.test(contentType);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
let sharedAgent;
|
|
36
|
+
const getAgent = () => {
|
|
37
|
+
if (sharedAgent) {
|
|
38
|
+
return sharedAgent;
|
|
39
|
+
}
|
|
40
|
+
else if (process.env.https_proxy) {
|
|
41
|
+
return (sharedAgent = (0, https_proxy_agent_1.default)(process.env.https_proxy));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return (sharedAgent = new https.Agent({
|
|
45
|
+
keepAlive: true,
|
|
46
|
+
maxSockets: MAX_CONCURRENCY,
|
|
47
|
+
maxTotalSockets: MAX_CONCURRENCY,
|
|
48
|
+
scheduling: 'lifo',
|
|
49
|
+
timeout: 4000,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
async function uploadAsync(params) {
|
|
54
|
+
const { filePath, signal, compress, method = 'POST', url, headers: headersInit, ...requestInit } = params;
|
|
55
|
+
const stat = await node_fs_1.default.promises.stat(params.filePath);
|
|
56
|
+
if (stat.size > MAX_UPLOAD_SIZE) {
|
|
57
|
+
throw new Error(`Upload of "${params.filePath}" aborted: File size is greater than the upload limit (>500MB)`);
|
|
58
|
+
}
|
|
59
|
+
const contentType = mime_1.default.getType(node_path_1.default.basename(params.filePath));
|
|
60
|
+
return await (0, promise_retry_1.default)(async (retry) => {
|
|
61
|
+
const headers = new node_fetch_1.Headers(headersInit);
|
|
62
|
+
if (contentType) {
|
|
63
|
+
headers.set('content-type', contentType);
|
|
64
|
+
}
|
|
65
|
+
let bodyStream = (0, node_fs_1.createReadStream)(filePath);
|
|
66
|
+
if (compress && isCompressible(contentType, stat.size)) {
|
|
67
|
+
const gzip = new minizlib_1.Gzip({ portable: true });
|
|
68
|
+
bodyStream.on('error', error => gzip.emit('error', error));
|
|
69
|
+
// @ts-expect-error: Gzip implements a Readable-like interface
|
|
70
|
+
bodyStream = bodyStream.pipe(gzip);
|
|
71
|
+
headers.set('content-encoding', 'gzip');
|
|
72
|
+
}
|
|
73
|
+
let response;
|
|
74
|
+
try {
|
|
75
|
+
response = await (0, node_fetch_1.default)(params.url, {
|
|
76
|
+
...requestInit,
|
|
77
|
+
method,
|
|
78
|
+
body: bodyStream,
|
|
79
|
+
headers,
|
|
80
|
+
agent: getAgent(),
|
|
81
|
+
// @ts-expect-error: Internal types don't match
|
|
82
|
+
signal,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return retry(error);
|
|
87
|
+
}
|
|
88
|
+
if (response.status === 408 ||
|
|
89
|
+
response.status === 409 ||
|
|
90
|
+
response.status === 429 ||
|
|
91
|
+
(response.status >= 500 && response.status <= 599)) {
|
|
92
|
+
const message = `Upload of "${filePath}" failed: ${response.statusText}`;
|
|
93
|
+
const text = await response.text().catch(() => null);
|
|
94
|
+
return retry(new Error(text ? `${message}\n${text}` : message));
|
|
95
|
+
}
|
|
96
|
+
else if (response.status === 413) {
|
|
97
|
+
const message = `Upload of "${filePath}" failed: File size exceeded the upload limit`;
|
|
98
|
+
throw new Error(message);
|
|
99
|
+
}
|
|
100
|
+
else if (!response.ok) {
|
|
101
|
+
throw new Error(`Upload of "${filePath}" failed: ${response.statusText}`);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
params,
|
|
105
|
+
response,
|
|
106
|
+
};
|
|
107
|
+
}, {
|
|
108
|
+
retries: MAX_RETRIES,
|
|
109
|
+
minTimeout: MIN_RETRY_TIMEOUT,
|
|
110
|
+
randomize: true,
|
|
111
|
+
factor: 2,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
exports.uploadAsync = uploadAsync;
|
|
115
|
+
async function* batchUploadAsync(uploads) {
|
|
116
|
+
const controller = new AbortController();
|
|
117
|
+
const queue = new Set();
|
|
118
|
+
try {
|
|
119
|
+
let index = 0;
|
|
120
|
+
while (index < uploads.length || queue.size > 0) {
|
|
121
|
+
while (queue.size < MAX_CONCURRENCY && index < uploads.length) {
|
|
122
|
+
const uploadParams = uploads[index++];
|
|
123
|
+
let uploadPromise;
|
|
124
|
+
queue.add((uploadPromise = uploadAsync({ ...uploadParams, signal: controller.signal }).finally(() => queue.delete(uploadPromise))));
|
|
125
|
+
yield { params: uploadParams };
|
|
126
|
+
}
|
|
127
|
+
yield await Promise.race(queue);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (typeof error !== 'object' || error.name !== 'AbortError') {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
if (queue.size > 0) {
|
|
137
|
+
controller.abort();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.batchUploadAsync = batchUploadAsync;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "12.
|
|
2
|
+
"version": "12.1.1",
|
|
3
3
|
"commands": {
|
|
4
4
|
"analytics": {
|
|
5
5
|
"id": "analytics",
|
|
@@ -3378,6 +3378,27 @@
|
|
|
3378
3378
|
"loggedIn": {}
|
|
3379
3379
|
}
|
|
3380
3380
|
},
|
|
3381
|
+
"worker:deploy": {
|
|
3382
|
+
"id": "worker:deploy",
|
|
3383
|
+
"description": "deploy an Expo web build",
|
|
3384
|
+
"strict": true,
|
|
3385
|
+
"pluginName": "eas-cli",
|
|
3386
|
+
"pluginAlias": "eas-cli",
|
|
3387
|
+
"pluginType": "core",
|
|
3388
|
+
"hidden": true,
|
|
3389
|
+
"state": "beta",
|
|
3390
|
+
"aliases": [
|
|
3391
|
+
"deploy"
|
|
3392
|
+
],
|
|
3393
|
+
"flags": {},
|
|
3394
|
+
"args": {},
|
|
3395
|
+
"contextDefinition": {
|
|
3396
|
+
"getDynamicPublicProjectConfigAsync": {},
|
|
3397
|
+
"getDynamicPrivateProjectConfigAsync": {},
|
|
3398
|
+
"projectDir": {},
|
|
3399
|
+
"loggedIn": {}
|
|
3400
|
+
}
|
|
3401
|
+
},
|
|
3381
3402
|
"build:version:get": {
|
|
3382
3403
|
"id": "build:version:get",
|
|
3383
3404
|
"description": "get the latest version from EAS servers",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eas-cli",
|
|
3
3
|
"description": "EAS command line tool",
|
|
4
|
-
"version": "12.
|
|
4
|
+
"version": "12.1.1",
|
|
5
5
|
"author": "Expo <support@expo.dev>",
|
|
6
6
|
"bin": {
|
|
7
7
|
"eas": "./bin/run"
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"log-symbols": "4.1.0",
|
|
64
64
|
"mime": "3.0.0",
|
|
65
65
|
"minimatch": "5.1.2",
|
|
66
|
+
"minizlib": "3.0.1",
|
|
66
67
|
"nanoid": "3.3.4",
|
|
67
68
|
"node-fetch": "2.6.7",
|
|
68
69
|
"node-forge": "1.3.1",
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
"semver": "7.5.4",
|
|
79
80
|
"slash": "3.0.0",
|
|
80
81
|
"tar": "6.2.1",
|
|
82
|
+
"tar-stream": "3.1.7",
|
|
81
83
|
"terminal-link": "2.1.1",
|
|
82
84
|
"tslib": "2.6.2",
|
|
83
85
|
"turndown": "7.1.2",
|
|
@@ -105,6 +107,7 @@
|
|
|
105
107
|
"@types/prompts": "2.4.2",
|
|
106
108
|
"@types/semver": "7.5.6",
|
|
107
109
|
"@types/tar": "6.1.10",
|
|
110
|
+
"@types/tar-stream": "3.1.3",
|
|
108
111
|
"@types/tough-cookie": "4.0.2",
|
|
109
112
|
"@types/uuid": "9.0.7",
|
|
110
113
|
"@types/wrap-ansi": "3.0.0",
|
|
@@ -223,5 +226,5 @@
|
|
|
223
226
|
"node": "20.11.0",
|
|
224
227
|
"yarn": "1.22.21"
|
|
225
228
|
},
|
|
226
|
-
"gitHead": "
|
|
229
|
+
"gitHead": "d63fc1f01ed170f17091ee391d0d9bc388a5fda9"
|
|
227
230
|
}
|