eas-build-cache-provider 0.0.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 +3 -0
- package/build/helpers.d.ts +9 -0
- package/build/helpers.js +30 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +98 -0
- package/build/log.d.ts +40 -0
- package/build/log.js +100 -0
- package/build/types.d.ts +0 -0
- package/build/types.js +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SpawnResult } from '@expo/spawn-async';
|
|
2
|
+
type RunOptions = any;
|
|
3
|
+
export declare function isSpawnResultError(obj: any): obj is Error & SpawnResult;
|
|
4
|
+
export declare function isDevClientBuild({ runOptions, projectRoot, }: {
|
|
5
|
+
runOptions: RunOptions;
|
|
6
|
+
projectRoot: string;
|
|
7
|
+
}): boolean;
|
|
8
|
+
export declare function hasDirectDevClientDependency(projectRoot: string): boolean;
|
|
9
|
+
export {};
|
package/build/helpers.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasDirectDevClientDependency = exports.isDevClientBuild = exports.isSpawnResultError = void 0;
|
|
4
|
+
const config_1 = require("@expo/config");
|
|
5
|
+
function isSpawnResultError(obj) {
|
|
6
|
+
return (obj &&
|
|
7
|
+
'message' in obj &&
|
|
8
|
+
obj.status !== undefined &&
|
|
9
|
+
obj.stdout !== undefined &&
|
|
10
|
+
obj.stderr !== undefined);
|
|
11
|
+
}
|
|
12
|
+
exports.isSpawnResultError = isSpawnResultError;
|
|
13
|
+
function isDevClientBuild({ runOptions, projectRoot, }) {
|
|
14
|
+
if (!hasDirectDevClientDependency(projectRoot)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if ('variant' in runOptions && runOptions.variant !== undefined) {
|
|
18
|
+
return runOptions.variant === 'debug';
|
|
19
|
+
}
|
|
20
|
+
if ('configuration' in runOptions && runOptions.configuration !== undefined) {
|
|
21
|
+
return runOptions.configuration === 'Debug';
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
exports.isDevClientBuild = isDevClientBuild;
|
|
26
|
+
function hasDirectDevClientDependency(projectRoot) {
|
|
27
|
+
const { dependencies = {}, devDependencies = {} } = (0, config_1.getPackageJson)(projectRoot);
|
|
28
|
+
return !!dependencies['expo-dev-client'] || !!devDependencies['expo-dev-client'];
|
|
29
|
+
}
|
|
30
|
+
exports.hasDirectDevClientDependency = hasDirectDevClientDependency;
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
7
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
+
const helpers_1 = require("./helpers");
|
|
9
|
+
const log_1 = tslib_1.__importDefault(require("./log"));
|
|
10
|
+
async function resolveRemoteBuildCacheAsync({ projectRoot, platform, fingerprintHash, runOptions, }) {
|
|
11
|
+
const easJsonPath = path_1.default.join(projectRoot, 'eas.json');
|
|
12
|
+
if (!(await fs_extra_1.default.exists(easJsonPath))) {
|
|
13
|
+
log_1.default.debug('eas.json not found, skip checking for remote builds');
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
log_1.default.log((0, chalk_1.default) `{whiteBright \u203A} {bold Searching builds with matching fingerprint on EAS servers}`);
|
|
17
|
+
try {
|
|
18
|
+
const results = await (0, spawn_async_1.default)('npx', [
|
|
19
|
+
'eas-cli',
|
|
20
|
+
'build:download',
|
|
21
|
+
`--platform=${platform}`,
|
|
22
|
+
`--fingerprint=${fingerprintHash}`,
|
|
23
|
+
'--non-interactive',
|
|
24
|
+
(0, helpers_1.isDevClientBuild)({ runOptions, projectRoot }) ? '--dev-client' : '--no-dev-client',
|
|
25
|
+
'--json',
|
|
26
|
+
], {
|
|
27
|
+
cwd: projectRoot,
|
|
28
|
+
});
|
|
29
|
+
log_1.default.log((0, chalk_1.default) `{whiteBright \u203A} {bold Successfully downloaded cached build}`);
|
|
30
|
+
// {
|
|
31
|
+
// "path": "/var/folders/03/lppcpcnn61q3mz5ckzmzd8w80000gn/T/eas-cli-nodejs/eas-build-run-cache/c0f9ba9c-0cf1-4c5c-8566-b28b7971050f_22f1bbfa-1c09-4b67-9e4a-721906546b58.app"
|
|
32
|
+
// }
|
|
33
|
+
const json = JSON.parse(results.stdout.trim());
|
|
34
|
+
return json?.path;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
log_1.default.debug('eas-cli error:', error);
|
|
38
|
+
// @TODO(2025-04-11): remove this in a future release
|
|
39
|
+
if ((0, helpers_1.isSpawnResultError)(error) && error.stderr.includes('command build:download not found')) {
|
|
40
|
+
log_1.default.warn(`To take advantage of remote build cache, upgrade your eas-cli installation to latest.`);
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function uploadEASRemoteBuildCacheAsync({ projectRoot, platform, fingerprintHash, buildPath, }) {
|
|
46
|
+
const easJsonPath = path_1.default.join(projectRoot, 'eas.json');
|
|
47
|
+
if (!(await fs_extra_1.default.exists(easJsonPath))) {
|
|
48
|
+
log_1.default.debug('eas.json not found, skip uploading builds');
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
log_1.default.log((0, chalk_1.default) `{whiteBright \u203A} {bold Uploading build to remote cache}`);
|
|
53
|
+
const results = await (0, spawn_async_1.default)('npx', [
|
|
54
|
+
'eas-cli',
|
|
55
|
+
'upload',
|
|
56
|
+
`--platform=${platform}`,
|
|
57
|
+
`--fingerprint=${fingerprintHash}`,
|
|
58
|
+
buildPath ? `--build-path=${buildPath}` : '',
|
|
59
|
+
'--non-interactive',
|
|
60
|
+
'--json',
|
|
61
|
+
], {
|
|
62
|
+
cwd: projectRoot,
|
|
63
|
+
});
|
|
64
|
+
// {
|
|
65
|
+
// "url": "/var/folders/03/lppcpcnn61q3mz5ckzmzd8w80000gn/T/eas-cli-nodejs/eas-build-run-cache/c0f9ba9c-0cf1-4c5c-8566-b28b7971050f_22f1bbfa-1c09-4b67-9e4a-721906546b58.app"
|
|
66
|
+
// }
|
|
67
|
+
const json = JSON.parse(results.stdout.trim());
|
|
68
|
+
log_1.default.log((0, chalk_1.default) `{whiteBright \u203A} {bold Build successfully uploaded: ${json?.url}}`);
|
|
69
|
+
return json?.url;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
log_1.default.debug('eas-cli error:', error);
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
async function calculateEASFingerprintHashAsync({ projectRoot, platform, }) {
|
|
77
|
+
// prefer using `eas fingerprint:generate` because it automatically upload sources
|
|
78
|
+
try {
|
|
79
|
+
const results = await (0, spawn_async_1.default)('npx', ['eas-cli', 'fingerprint:generate', `--platform=${platform}`, '--json', '--non-interactive'], {
|
|
80
|
+
cwd: projectRoot,
|
|
81
|
+
});
|
|
82
|
+
// {
|
|
83
|
+
// "hash": "203f960b965e154b77dc31c6c42e5582e8d77196"
|
|
84
|
+
// }
|
|
85
|
+
const json = JSON.parse(results.stdout.trim());
|
|
86
|
+
return json?.hash;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
log_1.default.debug('eas-cli error:', error);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const EASRemoteBuildCacheProvider = {
|
|
94
|
+
resolveRemoteBuildCache: resolveRemoteBuildCacheAsync,
|
|
95
|
+
uploadRemoteBuildCache: uploadEASRemoteBuildCacheAsync,
|
|
96
|
+
calculateFingerprintHash: calculateEASFingerprintHashAsync,
|
|
97
|
+
};
|
|
98
|
+
exports.default = EASRemoteBuildCacheProvider;
|
package/build/log.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export default class Log {
|
|
2
|
+
static readonly isDebug: boolean;
|
|
3
|
+
static log(...args: any[]): void;
|
|
4
|
+
static newLine(): void;
|
|
5
|
+
static addNewLineIfNone(): void;
|
|
6
|
+
static error(...args: any[]): void;
|
|
7
|
+
static warn(...args: any[]): void;
|
|
8
|
+
static debug(...args: any[]): void;
|
|
9
|
+
static gray(...args: any[]): void;
|
|
10
|
+
static warnDeprecatedFlag(flag: string, message: string): void;
|
|
11
|
+
static fail(message: string): void;
|
|
12
|
+
static succeed(message: string): void;
|
|
13
|
+
static withTick(...args: any[]): void;
|
|
14
|
+
static withInfo(...args: any[]): void;
|
|
15
|
+
private static consoleLog;
|
|
16
|
+
private static withTextColor;
|
|
17
|
+
private static isLastLineNewLine;
|
|
18
|
+
private static updateIsLastLineNewLine;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Prints a link for given URL, using text if provided, otherwise text is just the URL.
|
|
22
|
+
* Format links as dim (unless disabled) and with an underline.
|
|
23
|
+
*
|
|
24
|
+
* @example https://expo.dev
|
|
25
|
+
*/
|
|
26
|
+
export declare function link(url: string, { text, fallback, dim }?: {
|
|
27
|
+
text?: string;
|
|
28
|
+
dim?: boolean;
|
|
29
|
+
fallback?: string;
|
|
30
|
+
}): string;
|
|
31
|
+
/**
|
|
32
|
+
* Provide a consistent "Learn more" link experience.
|
|
33
|
+
* Format links as dim (unless disabled) with an underline.
|
|
34
|
+
*
|
|
35
|
+
* @example Learn more: https://expo.dev
|
|
36
|
+
*/
|
|
37
|
+
export declare function learnMore(url: string, { learnMoreMessage: maybeLearnMoreMessage, dim, }?: {
|
|
38
|
+
learnMoreMessage?: string;
|
|
39
|
+
dim?: boolean;
|
|
40
|
+
}): string;
|
package/build/log.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.learnMore = exports.link = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const figures_1 = tslib_1.__importDefault(require("figures"));
|
|
7
|
+
const getenv_1 = require("getenv");
|
|
8
|
+
const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
|
|
9
|
+
const terminal_link_1 = tslib_1.__importDefault(require("terminal-link"));
|
|
10
|
+
class Log {
|
|
11
|
+
static isDebug = (0, getenv_1.boolish)('EXPO_DEBUG', false);
|
|
12
|
+
static log(...args) {
|
|
13
|
+
Log.consoleLog(...args);
|
|
14
|
+
}
|
|
15
|
+
static newLine() {
|
|
16
|
+
Log.consoleLog();
|
|
17
|
+
}
|
|
18
|
+
static addNewLineIfNone() {
|
|
19
|
+
if (!Log.isLastLineNewLine) {
|
|
20
|
+
Log.newLine();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
static error(...args) {
|
|
24
|
+
Log.consoleLog(...Log.withTextColor(args, chalk_1.default.red));
|
|
25
|
+
}
|
|
26
|
+
static warn(...args) {
|
|
27
|
+
Log.consoleLog(...Log.withTextColor(args, chalk_1.default.yellow));
|
|
28
|
+
}
|
|
29
|
+
static debug(...args) {
|
|
30
|
+
if (Log.isDebug) {
|
|
31
|
+
Log.consoleLog(...args);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
static gray(...args) {
|
|
35
|
+
Log.consoleLog(...Log.withTextColor(args, chalk_1.default.gray));
|
|
36
|
+
}
|
|
37
|
+
static warnDeprecatedFlag(flag, message) {
|
|
38
|
+
Log.warn(`› ${chalk_1.default.bold('--' + flag)} flag is deprecated. ${message}`);
|
|
39
|
+
}
|
|
40
|
+
static fail(message) {
|
|
41
|
+
Log.log(`${chalk_1.default.red(log_symbols_1.default.error)} ${message}`);
|
|
42
|
+
}
|
|
43
|
+
static succeed(message) {
|
|
44
|
+
Log.log(`${chalk_1.default.green(log_symbols_1.default.success)} ${message}`);
|
|
45
|
+
}
|
|
46
|
+
static withTick(...args) {
|
|
47
|
+
Log.consoleLog(chalk_1.default.green(figures_1.default.tick), ...args);
|
|
48
|
+
}
|
|
49
|
+
static withInfo(...args) {
|
|
50
|
+
Log.consoleLog(chalk_1.default.green(figures_1.default.info), ...args);
|
|
51
|
+
}
|
|
52
|
+
static consoleLog(...args) {
|
|
53
|
+
Log.updateIsLastLineNewLine(args);
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.log(...args);
|
|
56
|
+
}
|
|
57
|
+
static withTextColor(args, chalkColor) {
|
|
58
|
+
return args.map(arg => chalkColor(arg));
|
|
59
|
+
}
|
|
60
|
+
static isLastLineNewLine = false;
|
|
61
|
+
static updateIsLastLineNewLine(args) {
|
|
62
|
+
if (args.length === 0) {
|
|
63
|
+
Log.isLastLineNewLine = true;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const lastArg = args[args.length - 1];
|
|
67
|
+
if (typeof lastArg === 'string' && (lastArg === '' || lastArg.match(/[\r\n]$/))) {
|
|
68
|
+
Log.isLastLineNewLine = true;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
Log.isLastLineNewLine = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.default = Log;
|
|
77
|
+
/**
|
|
78
|
+
* Prints a link for given URL, using text if provided, otherwise text is just the URL.
|
|
79
|
+
* Format links as dim (unless disabled) and with an underline.
|
|
80
|
+
*
|
|
81
|
+
* @example https://expo.dev
|
|
82
|
+
*/
|
|
83
|
+
function link(url, { text = url, fallback, dim = true } = {}) {
|
|
84
|
+
// Links can be disabled via env variables https://github.com/jamestalmage/supports-hyperlinks/blob/master/index.js
|
|
85
|
+
const output = (0, terminal_link_1.default)(text, url, {
|
|
86
|
+
fallback: () => fallback ?? (text === url ? chalk_1.default.underline(url) : `${text}: ${chalk_1.default.underline(url)}`),
|
|
87
|
+
});
|
|
88
|
+
return dim ? chalk_1.default.dim(output) : output;
|
|
89
|
+
}
|
|
90
|
+
exports.link = link;
|
|
91
|
+
/**
|
|
92
|
+
* Provide a consistent "Learn more" link experience.
|
|
93
|
+
* Format links as dim (unless disabled) with an underline.
|
|
94
|
+
*
|
|
95
|
+
* @example Learn more: https://expo.dev
|
|
96
|
+
*/
|
|
97
|
+
function learnMore(url, { learnMoreMessage: maybeLearnMoreMessage, dim = true, } = {}) {
|
|
98
|
+
return link(url, { text: maybeLearnMoreMessage ?? 'Learn more', dim });
|
|
99
|
+
}
|
|
100
|
+
exports.learnMore = learnMore;
|
package/build/types.d.ts
ADDED
|
File without changes
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eas-build-cache-provider",
|
|
3
|
+
"description": "A build cache provider plugin for the Expo CLI",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"author": "Expo <support@expo.dev>",
|
|
6
|
+
"bugs": "https://github.com/expo/eas-cli/issues",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@babel/code-frame": "7.23.5",
|
|
9
|
+
"@expo/config-plugins": "9.0.12",
|
|
10
|
+
"@expo/spawn-async": "^1.7.2",
|
|
11
|
+
"chalk": "4.1.2",
|
|
12
|
+
"fs-extra": "11.2.0",
|
|
13
|
+
"log-symbols": "4.1.0",
|
|
14
|
+
"semver": "7.5.2",
|
|
15
|
+
"terminal-link": "2.1.1",
|
|
16
|
+
"tslib": "2.4.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@tsconfig/node18": "18.2.4",
|
|
20
|
+
"@types/babel__code-frame": "7.0.3",
|
|
21
|
+
"@types/fs-extra": "11.0.4",
|
|
22
|
+
"memfs": "3.4.13",
|
|
23
|
+
"rimraf": "3.0.2",
|
|
24
|
+
"typescript": "5.3.3"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/expo/eas-cli",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"main": "build/index.js",
|
|
32
|
+
"types": "build/index.d.ts",
|
|
33
|
+
"repository": "expo/eas-cli",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc --project tsconfig.build.json",
|
|
36
|
+
"build-allow-unused": "tsc --project tsconfig.allowUnused.json",
|
|
37
|
+
"watch": "yarn build --watch --preserveWatchOutput",
|
|
38
|
+
"watch-allow-unused": "yarn build-allow-unused --watch --preserveWatchOutput",
|
|
39
|
+
"typecheck": "tsc",
|
|
40
|
+
"prepack": "yarn rebuild",
|
|
41
|
+
"rebuild": "rimraf build && yarn build",
|
|
42
|
+
"test": "jest",
|
|
43
|
+
"clean": "rimraf build node_modules yarn-error.log"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"/build"
|
|
47
|
+
],
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"volta": {
|
|
52
|
+
"node": "20.11.0",
|
|
53
|
+
"yarn": "1.22.21"
|
|
54
|
+
}
|
|
55
|
+
}
|