@expo/build-tools 1.0.178 → 1.0.179

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.
@@ -27,6 +27,7 @@ const calculateEASUpdateRuntimeVersion_1 = require("./functions/calculateEASUpda
27
27
  const repack_1 = require("./functions/repack");
28
28
  const eagerBundle_1 = require("./functions/eagerBundle");
29
29
  const createSubmissionEntity_1 = require("./functions/createSubmissionEntity");
30
+ const downloadBuild_1 = require("./functions/downloadBuild");
30
31
  function getEasFunctions(ctx) {
31
32
  const functions = [
32
33
  (0, checkout_1.createCheckoutBuildFunction)(),
@@ -34,6 +35,7 @@ function getEasFunctions(ctx) {
34
35
  (0, useNpmToken_1.createSetUpNpmrcBuildFunction)(),
35
36
  (0, installNodeModules_1.createInstallNodeModulesBuildFunction)(),
36
37
  (0, prebuild_1.createPrebuildBuildFunction)(),
38
+ (0, downloadBuild_1.createDownloadBuildFunction)(),
37
39
  (0, configureEASUpdateIfInstalled_1.configureEASUpdateIfInstalledFunction)(),
38
40
  (0, injectAndroidCredentials_1.injectAndroidCredentialsFunction)(),
39
41
  (0, configureAndroidVersion_1.configureAndroidVersionFunction)(),
@@ -1 +1 @@
1
- {"version":3,"file":"easFunctions.js","sourceRoot":"","sources":["../../src/steps/easFunctions.ts"],"names":[],"mappings":";;;AAIA,+DAA+E;AAC/E,mDAAmE;AACnE,yDAAwE;AACxE,uEAAuF;AACvF,mDAAmE;AACnE,yFAAyG;AACzG,6FAAkG;AAClG,mFAAwF;AACxF,iFAAsF;AACtF,qDAA0D;AAC1D,qGAA0G;AAC1G,iFAAsF;AACtF,yEAA8E;AAC9E,yFAA8F;AAC9F,yDAA8D;AAC9D,2EAA2F;AAC3F,qEAAqF;AACrF,+DAA+E;AAC/E,uIAA0I;AAC1I,yDAAyE;AACzE,mEAA8E;AAC9E,uEAAuF;AACvF,mGAAwG;AACxG,+CAA+D;AAC/D,yDAAmE;AACnE,+EAAoF;AAEpF,SAAgB,eAAe,CAAC,GAAuB;IACrD,MAAM,SAAS,GAAG;QAChB,IAAA,sCAA2B,GAAE;QAC7B,IAAA,kDAAiC,EAAC,GAAG,CAAC;QACtC,IAAA,2CAA6B,GAAE;QAC/B,IAAA,0DAAqC,GAAE;QACvC,IAAA,sCAA2B,GAAE;QAE7B,IAAA,qEAAqC,GAAE;QACvC,IAAA,2DAAgC,GAAE;QAClC,IAAA,yDAA+B,GAAE;QACjC,IAAA,sCAAwB,GAAE;QAC1B,IAAA,6BAAiB,GAAE;QACnB,IAAA,6EAAyC,GAAE;QAC3C,IAAA,yDAA+B,GAAE;QACjC,IAAA,iDAA2B,GAAE;QAC7B,IAAA,iEAAmC,GAAE;QACrC,IAAA,iCAAmB,GAAE;QACrB,IAAA,8DAAuC,GAAE;QACzC,IAAA,wDAAoC,GAAE;QACtC,IAAA,kDAAiC,GAAE;QAEnC,IAAA,4CAA8B,GAAE;QAChC,IAAA,iDAA8B,GAAE;QAEhC,IAAA,2EAAwC,GAAE;QAE1C,IAAA,kCAAyB,GAAE;QAE3B,IAAA,uDAA8B,GAAE;KACjC,CAAC;IAEF,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QACtB,SAAS,CAAC,IAAI,CACZ,GAAG;YACD,IAAA,4EAA8C,EAAC,GAAG,CAAC;YACnD,IAAA,0DAAqC,EAAC,GAAG,CAAC;YAC1C,IAAA,6GAAwD,EAAC,GAAG,CAAC;SAC9D,CACF,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AA3CD,0CA2CC","sourcesContent":["import { BuildFunction } from '@expo/steps';\n\nimport { CustomBuildContext } from '../customBuildContext';\n\nimport { createUploadArtifactBuildFunction } from './functions/uploadArtifact';\nimport { createCheckoutBuildFunction } from './functions/checkout';\nimport { createSetUpNpmrcBuildFunction } from './functions/useNpmToken';\nimport { createInstallNodeModulesBuildFunction } from './functions/installNodeModules';\nimport { createPrebuildBuildFunction } from './functions/prebuild';\nimport { createFindAndUploadBuildArtifactsBuildFunction } from './functions/findAndUploadBuildArtifacts';\nimport { configureEASUpdateIfInstalledFunction } from './functions/configureEASUpdateIfInstalled';\nimport { injectAndroidCredentialsFunction } from './functions/injectAndroidCredentials';\nimport { configureAndroidVersionFunction } from './functions/configureAndroidVersion';\nimport { runGradleFunction } from './functions/runGradle';\nimport { resolveAppleTeamIdFromCredentialsFunction } from './functions/resolveAppleTeamIdFromCredentials';\nimport { configureIosCredentialsFunction } from './functions/configureIosCredentials';\nimport { configureIosVersionFunction } from './functions/configureIosVersion';\nimport { generateGymfileFromTemplateFunction } from './functions/generateGymfileFromTemplate';\nimport { runFastlaneFunction } from './functions/runFastlane';\nimport { createStartAndroidEmulatorBuildFunction } from './functions/startAndroidEmulator';\nimport { createStartIosSimulatorBuildFunction } from './functions/startIosSimulator';\nimport { createInstallMaestroBuildFunction } from './functions/installMaestro';\nimport { createGetCredentialsForBuildTriggeredByGithubIntegration } from './functions/getCredentialsForBuildTriggeredByGitHubIntegration';\nimport { createInstallPodsBuildFunction } from './functions/installPods';\nimport { createSendSlackMessageFunction } from './functions/sendSlackMessage';\nimport { createResolveBuildConfigBuildFunction } from './functions/resolveBuildConfig';\nimport { calculateEASUpdateRuntimeVersionFunction } from './functions/calculateEASUpdateRuntimeVersion';\nimport { createRepackBuildFunction } from './functions/repack';\nimport { eagerBundleBuildFunction } from './functions/eagerBundle';\nimport { createSubmissionEntityFunction } from './functions/createSubmissionEntity';\n\nexport function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {\n const functions = [\n createCheckoutBuildFunction(),\n createUploadArtifactBuildFunction(ctx),\n createSetUpNpmrcBuildFunction(),\n createInstallNodeModulesBuildFunction(),\n createPrebuildBuildFunction(),\n\n configureEASUpdateIfInstalledFunction(),\n injectAndroidCredentialsFunction(),\n configureAndroidVersionFunction(),\n eagerBundleBuildFunction(),\n runGradleFunction(),\n resolveAppleTeamIdFromCredentialsFunction(),\n configureIosCredentialsFunction(),\n configureIosVersionFunction(),\n generateGymfileFromTemplateFunction(),\n runFastlaneFunction(),\n createStartAndroidEmulatorBuildFunction(),\n createStartIosSimulatorBuildFunction(),\n createInstallMaestroBuildFunction(),\n\n createInstallPodsBuildFunction(),\n createSendSlackMessageFunction(),\n\n calculateEASUpdateRuntimeVersionFunction(),\n\n createRepackBuildFunction(),\n\n createSubmissionEntityFunction(),\n ];\n\n if (ctx.hasBuildJob()) {\n functions.push(\n ...[\n createFindAndUploadBuildArtifactsBuildFunction(ctx),\n createResolveBuildConfigBuildFunction(ctx),\n createGetCredentialsForBuildTriggeredByGithubIntegration(ctx),\n ]\n );\n }\n\n return functions;\n}\n"]}
1
+ {"version":3,"file":"easFunctions.js","sourceRoot":"","sources":["../../src/steps/easFunctions.ts"],"names":[],"mappings":";;;AAIA,+DAA+E;AAC/E,mDAAmE;AACnE,yDAAwE;AACxE,uEAAuF;AACvF,mDAAmE;AACnE,yFAAyG;AACzG,6FAAkG;AAClG,mFAAwF;AACxF,iFAAsF;AACtF,qDAA0D;AAC1D,qGAA0G;AAC1G,iFAAsF;AACtF,yEAA8E;AAC9E,yFAA8F;AAC9F,yDAA8D;AAC9D,2EAA2F;AAC3F,qEAAqF;AACrF,+DAA+E;AAC/E,uIAA0I;AAC1I,yDAAyE;AACzE,mEAA8E;AAC9E,uEAAuF;AACvF,mGAAwG;AACxG,+CAA+D;AAC/D,yDAAmE;AACnE,+EAAoF;AACpF,6DAAwE;AAExE,SAAgB,eAAe,CAAC,GAAuB;IACrD,MAAM,SAAS,GAAG;QAChB,IAAA,sCAA2B,GAAE;QAC7B,IAAA,kDAAiC,EAAC,GAAG,CAAC;QACtC,IAAA,2CAA6B,GAAE;QAC/B,IAAA,0DAAqC,GAAE;QACvC,IAAA,sCAA2B,GAAE;QAC7B,IAAA,2CAA2B,GAAE;QAE7B,IAAA,qEAAqC,GAAE;QACvC,IAAA,2DAAgC,GAAE;QAClC,IAAA,yDAA+B,GAAE;QACjC,IAAA,sCAAwB,GAAE;QAC1B,IAAA,6BAAiB,GAAE;QACnB,IAAA,6EAAyC,GAAE;QAC3C,IAAA,yDAA+B,GAAE;QACjC,IAAA,iDAA2B,GAAE;QAC7B,IAAA,iEAAmC,GAAE;QACrC,IAAA,iCAAmB,GAAE;QACrB,IAAA,8DAAuC,GAAE;QACzC,IAAA,wDAAoC,GAAE;QACtC,IAAA,kDAAiC,GAAE;QAEnC,IAAA,4CAA8B,GAAE;QAChC,IAAA,iDAA8B,GAAE;QAEhC,IAAA,2EAAwC,GAAE;QAE1C,IAAA,kCAAyB,GAAE;QAE3B,IAAA,uDAA8B,GAAE;KACjC,CAAC;IAEF,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QACtB,SAAS,CAAC,IAAI,CACZ,GAAG;YACD,IAAA,4EAA8C,EAAC,GAAG,CAAC;YACnD,IAAA,0DAAqC,EAAC,GAAG,CAAC;YAC1C,IAAA,6GAAwD,EAAC,GAAG,CAAC;SAC9D,CACF,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AA5CD,0CA4CC","sourcesContent":["import { BuildFunction } from '@expo/steps';\n\nimport { CustomBuildContext } from '../customBuildContext';\n\nimport { createUploadArtifactBuildFunction } from './functions/uploadArtifact';\nimport { createCheckoutBuildFunction } from './functions/checkout';\nimport { createSetUpNpmrcBuildFunction } from './functions/useNpmToken';\nimport { createInstallNodeModulesBuildFunction } from './functions/installNodeModules';\nimport { createPrebuildBuildFunction } from './functions/prebuild';\nimport { createFindAndUploadBuildArtifactsBuildFunction } from './functions/findAndUploadBuildArtifacts';\nimport { configureEASUpdateIfInstalledFunction } from './functions/configureEASUpdateIfInstalled';\nimport { injectAndroidCredentialsFunction } from './functions/injectAndroidCredentials';\nimport { configureAndroidVersionFunction } from './functions/configureAndroidVersion';\nimport { runGradleFunction } from './functions/runGradle';\nimport { resolveAppleTeamIdFromCredentialsFunction } from './functions/resolveAppleTeamIdFromCredentials';\nimport { configureIosCredentialsFunction } from './functions/configureIosCredentials';\nimport { configureIosVersionFunction } from './functions/configureIosVersion';\nimport { generateGymfileFromTemplateFunction } from './functions/generateGymfileFromTemplate';\nimport { runFastlaneFunction } from './functions/runFastlane';\nimport { createStartAndroidEmulatorBuildFunction } from './functions/startAndroidEmulator';\nimport { createStartIosSimulatorBuildFunction } from './functions/startIosSimulator';\nimport { createInstallMaestroBuildFunction } from './functions/installMaestro';\nimport { createGetCredentialsForBuildTriggeredByGithubIntegration } from './functions/getCredentialsForBuildTriggeredByGitHubIntegration';\nimport { createInstallPodsBuildFunction } from './functions/installPods';\nimport { createSendSlackMessageFunction } from './functions/sendSlackMessage';\nimport { createResolveBuildConfigBuildFunction } from './functions/resolveBuildConfig';\nimport { calculateEASUpdateRuntimeVersionFunction } from './functions/calculateEASUpdateRuntimeVersion';\nimport { createRepackBuildFunction } from './functions/repack';\nimport { eagerBundleBuildFunction } from './functions/eagerBundle';\nimport { createSubmissionEntityFunction } from './functions/createSubmissionEntity';\nimport { createDownloadBuildFunction } from './functions/downloadBuild';\n\nexport function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {\n const functions = [\n createCheckoutBuildFunction(),\n createUploadArtifactBuildFunction(ctx),\n createSetUpNpmrcBuildFunction(),\n createInstallNodeModulesBuildFunction(),\n createPrebuildBuildFunction(),\n createDownloadBuildFunction(),\n\n configureEASUpdateIfInstalledFunction(),\n injectAndroidCredentialsFunction(),\n configureAndroidVersionFunction(),\n eagerBundleBuildFunction(),\n runGradleFunction(),\n resolveAppleTeamIdFromCredentialsFunction(),\n configureIosCredentialsFunction(),\n configureIosVersionFunction(),\n generateGymfileFromTemplateFunction(),\n runFastlaneFunction(),\n createStartAndroidEmulatorBuildFunction(),\n createStartIosSimulatorBuildFunction(),\n createInstallMaestroBuildFunction(),\n\n createInstallPodsBuildFunction(),\n createSendSlackMessageFunction(),\n\n calculateEASUpdateRuntimeVersionFunction(),\n\n createRepackBuildFunction(),\n\n createSubmissionEntityFunction(),\n ];\n\n if (ctx.hasBuildJob()) {\n functions.push(\n ...[\n createFindAndUploadBuildArtifactsBuildFunction(ctx),\n createResolveBuildConfigBuildFunction(ctx),\n createGetCredentialsForBuildTriggeredByGithubIntegration(ctx),\n ]\n );\n }\n\n return functions;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ /// <reference types="bunyan" />
2
+ import { BuildFunction } from '@expo/steps';
3
+ import { bunyan } from '@expo/logger';
4
+ export declare function createDownloadBuildFunction(): BuildFunction;
5
+ export declare function downloadBuildAsync({ logger, buildId, expoApiServerURL, expoToken, extensions, }: {
6
+ logger: bunyan;
7
+ buildId: string;
8
+ expoApiServerURL: string;
9
+ expoToken: string | null;
10
+ extensions: string[];
11
+ }): Promise<{
12
+ artifactPath: string;
13
+ }>;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.downloadBuildAsync = exports.createDownloadBuildFunction = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_os_1 = __importDefault(require("node:os"));
10
+ const stream_1 = __importDefault(require("stream"));
11
+ const util_1 = require("util");
12
+ const steps_1 = require("@expo/steps");
13
+ const results_1 = require("@expo/results");
14
+ const node_fetch_1 = __importDefault(require("node-fetch"));
15
+ const fast_glob_1 = require("fast-glob");
16
+ const zod_1 = require("zod");
17
+ const errors_1 = require("@expo/eas-build-job/dist/errors");
18
+ const retryOnDNSFailure_1 = require("../../utils/retryOnDNSFailure");
19
+ const artifacts_1 = require("../../utils/artifacts");
20
+ const files_1 = require("../../utils/files");
21
+ const strings_1 = require("../../utils/strings");
22
+ const streamPipeline = (0, util_1.promisify)(stream_1.default.pipeline);
23
+ function createDownloadBuildFunction() {
24
+ return new steps_1.BuildFunction({
25
+ namespace: 'eas',
26
+ id: 'download_build',
27
+ name: 'Download build',
28
+ inputProviders: [
29
+ steps_1.BuildStepInput.createProvider({
30
+ id: 'build_id',
31
+ required: true,
32
+ allowedValueTypeName: steps_1.BuildStepInputValueTypeName.STRING,
33
+ }),
34
+ steps_1.BuildStepInput.createProvider({
35
+ id: 'extensions',
36
+ required: false,
37
+ allowedValueTypeName: steps_1.BuildStepInputValueTypeName.JSON,
38
+ defaultValue: ['apk', 'aab', 'ipa', 'app'],
39
+ }),
40
+ ],
41
+ outputProviders: [
42
+ steps_1.BuildStepOutput.createProvider({
43
+ id: 'artifact_path',
44
+ required: true,
45
+ }),
46
+ ],
47
+ fn: async (stepsCtx, { inputs, outputs, env }) => {
48
+ var _a;
49
+ const { logger } = stepsCtx;
50
+ const extensions = zod_1.z.array(zod_1.z.string()).parse(inputs.extensions.value);
51
+ logger.info(`Expected extensions: [${extensions.join(', ')}]`);
52
+ const buildId = zod_1.z.string().uuid().parse(inputs.build_id.value);
53
+ logger.info(`Downloading build ${buildId}...`);
54
+ const { artifactPath } = await downloadBuildAsync({
55
+ logger,
56
+ buildId,
57
+ expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,
58
+ expoToken: (_a = env.EXPO_TOKEN) !== null && _a !== void 0 ? _a : null,
59
+ extensions,
60
+ });
61
+ outputs.artifact_path.set(artifactPath);
62
+ },
63
+ });
64
+ }
65
+ exports.createDownloadBuildFunction = createDownloadBuildFunction;
66
+ async function downloadBuildAsync({ logger, buildId, expoApiServerURL, expoToken, extensions, }) {
67
+ const tempDirectory = await node_fs_1.default.promises.mkdtemp(node_os_1.default.tmpdir());
68
+ const response = await (0, retryOnDNSFailure_1.retryOnDNSFailure)(node_fetch_1.default)(new URL(`/v2/artifacts/eas/${buildId}`, expoApiServerURL), {
69
+ headers: expoToken ? { Authorization: `Bearer ${expoToken}` } : undefined,
70
+ });
71
+ if (!response.ok) {
72
+ const textResult = await (0, results_1.asyncResult)(response.text());
73
+ throw new Error(`Unexpected response from server (${response.status}): ${textResult.value}`);
74
+ }
75
+ // URL may contain percent-encoded characters, e.g. my%20file.apk
76
+ // this replaces all non-alphanumeric characters (excluding dot) with underscore
77
+ const archiveFilename = node_path_1.default
78
+ .basename(new URL(response.url).pathname)
79
+ .replace(/([^a-z0-9.-]+)/gi, '_');
80
+ const archivePath = node_path_1.default.join(tempDirectory, archiveFilename);
81
+ await streamPipeline(response.body, node_fs_1.default.createWriteStream(archivePath));
82
+ const { size } = await node_fs_1.default.promises.stat(archivePath);
83
+ logger.info(`Downloaded ${archivePath} (${(0, artifacts_1.formatBytes)(size)} bytes).`);
84
+ const isFileATarGzArchive = await (0, files_1.isFileTarGzAsync)(archivePath);
85
+ if (!isFileATarGzArchive) {
86
+ logger.info(`Artifact is not a .tar.gz archive, skipping decompression and validation.`);
87
+ return { artifactPath: archivePath };
88
+ }
89
+ const extractionDirectory = await node_fs_1.default.promises.mkdtemp(node_os_1.default.tmpdir());
90
+ await (0, files_1.decompressTarAsync)({
91
+ archivePath,
92
+ destinationDirectory: extractionDirectory,
93
+ });
94
+ const matchingFiles = await (0, fast_glob_1.glob)(`**/*.(${extensions.join('|')})`, {
95
+ absolute: true,
96
+ cwd: extractionDirectory,
97
+ onlyFiles: false,
98
+ onlyDirectories: false,
99
+ });
100
+ if (matchingFiles.length === 0) {
101
+ throw new errors_1.UserFacingError('EAS_DOWNLOAD_BUILD_NO_MATCHING_FILES', `No ${extensions.map((ext) => `.${ext}`).join(', ')} entries found in the archive.`);
102
+ }
103
+ logger.info(`Found ${matchingFiles.length} matching ${(0, strings_1.pluralize)(matchingFiles.length, 'entry')}:\n${matchingFiles.map((f) => `- ${node_path_1.default.relative(extractionDirectory, f)}`).join('\n')}`);
104
+ return { artifactPath: matchingFiles[0] };
105
+ }
106
+ exports.downloadBuildAsync = downloadBuildAsync;
107
+ //# sourceMappingURL=downloadBuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloadBuild.js","sourceRoot":"","sources":["../../../src/steps/functions/downloadBuild.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAC7B,sDAAyB;AACzB,sDAAyB;AACzB,oDAA4B;AAC5B,+BAAiC;AAEjC,uCAKqB;AACrB,2CAA4C;AAC5C,4DAA+B;AAC/B,yCAAiC;AACjC,6BAAwB;AAExB,4DAAkE;AAElE,qEAAkE;AAClE,qDAAoD;AACpD,6CAAyE;AACzE,iDAAgD;AAEhD,MAAM,cAAc,GAAG,IAAA,gBAAS,EAAC,gBAAM,CAAC,QAAQ,CAAC,CAAC;AAElD,SAAgB,2BAA2B;IACzC,OAAO,IAAI,qBAAa,CAAC;QACvB,SAAS,EAAE,KAAK;QAChB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,gBAAgB;QACtB,cAAc,EAAE;YACd,sBAAc,CAAC,cAAc,CAAC;gBAC5B,EAAE,EAAE,UAAU;gBACd,QAAQ,EAAE,IAAI;gBACd,oBAAoB,EAAE,mCAA2B,CAAC,MAAM;aACzD,CAAC;YACF,sBAAc,CAAC,cAAc,CAAC;gBAC5B,EAAE,EAAE,YAAY;gBAChB,QAAQ,EAAE,KAAK;gBACf,oBAAoB,EAAE,mCAA2B,CAAC,IAAI;gBACtD,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;aAC3C,CAAC;SACH;QACD,eAAe,EAAE;YACf,uBAAe,CAAC,cAAc,CAAC;gBAC7B,EAAE,EAAE,eAAe;gBACnB,QAAQ,EAAE,IAAI;aACf,CAAC;SACH;QACD,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;;YAC/C,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;YAE5B,MAAM,UAAU,GAAG,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,CAAC,IAAI,CAAC,yBAAyB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC/D,MAAM,CAAC,IAAI,CAAC,qBAAqB,OAAO,KAAK,CAAC,CAAC;YAE/C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,kBAAkB,CAAC;gBAChD,MAAM;gBACN,OAAO;gBACP,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB;gBAChE,SAAS,EAAE,MAAA,GAAG,CAAC,UAAU,mCAAI,IAAI;gBACjC,UAAU;aACX,CAAC,CAAC;YAEH,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AA3CD,kEA2CC;AAEM,KAAK,UAAU,kBAAkB,CAAC,EACvC,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,SAAS,EACT,UAAU,GAOX;IACC,MAAM,aAAa,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,MAAM,IAAA,qCAAiB,EAAC,oBAAK,CAAC,CAC7C,IAAI,GAAG,CAAC,qBAAqB,OAAO,EAAE,EAAE,gBAAgB,CAAC,EACzD;QACE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS;KAC1E,CACF,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,MAAM,IAAA,qBAAW,EAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,MAAM,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,iEAAiE;IACjE,gFAAgF;IAChF,MAAM,eAAe,GAAG,mBAAI;SACzB,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;SACxC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,mBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAE9D,MAAM,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,iBAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;IAEvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAErD,MAAM,CAAC,IAAI,CAAC,cAAc,WAAW,KAAK,IAAA,uBAAW,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEvE,MAAM,mBAAmB,GAAG,MAAM,IAAA,wBAAgB,EAAC,WAAW,CAAC,CAAC;IAEhE,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QACzF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;IACvC,CAAC;IAED,MAAM,mBAAmB,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACnE,MAAM,IAAA,0BAAkB,EAAC;QACvB,WAAW;QACX,oBAAoB,EAAE,mBAAmB;KAC1C,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,IAAA,gBAAI,EAAC,SAAS,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;QACjE,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,mBAAmB;QACxB,SAAS,EAAE,KAAK;QAChB,eAAe,EAAE,KAAK;KACvB,CAAC,CAAC;IAEH,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,wBAAe,CACvB,sCAAsC,EACtC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CACpF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,IAAI,CACT,SAAS,aAAa,CAAC,MAAM,aAAa,IAAA,mBAAS,EAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,mBAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5K,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC;AAxED,gDAwEC","sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport stream from 'stream';\nimport { promisify } from 'util';\n\nimport {\n BuildFunction,\n BuildStepInput,\n BuildStepInputValueTypeName,\n BuildStepOutput,\n} from '@expo/steps';\nimport { asyncResult } from '@expo/results';\nimport fetch from 'node-fetch';\nimport { glob } from 'fast-glob';\nimport { z } from 'zod';\nimport { bunyan } from '@expo/logger';\nimport { UserFacingError } from '@expo/eas-build-job/dist/errors';\n\nimport { retryOnDNSFailure } from '../../utils/retryOnDNSFailure';\nimport { formatBytes } from '../../utils/artifacts';\nimport { decompressTarAsync, isFileTarGzAsync } from '../../utils/files';\nimport { pluralize } from '../../utils/strings';\n\nconst streamPipeline = promisify(stream.pipeline);\n\nexport function createDownloadBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'download_build',\n name: 'Download build',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'build_id',\n required: true,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'extensions',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.JSON,\n defaultValue: ['apk', 'aab', 'ipa', 'app'],\n }),\n ],\n outputProviders: [\n BuildStepOutput.createProvider({\n id: 'artifact_path',\n required: true,\n }),\n ],\n fn: async (stepsCtx, { inputs, outputs, env }) => {\n const { logger } = stepsCtx;\n\n const extensions = z.array(z.string()).parse(inputs.extensions.value);\n logger.info(`Expected extensions: [${extensions.join(', ')}]`);\n const buildId = z.string().uuid().parse(inputs.build_id.value);\n logger.info(`Downloading build ${buildId}...`);\n\n const { artifactPath } = await downloadBuildAsync({\n logger,\n buildId,\n expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,\n expoToken: env.EXPO_TOKEN ?? null,\n extensions,\n });\n\n outputs.artifact_path.set(artifactPath);\n },\n });\n}\n\nexport async function downloadBuildAsync({\n logger,\n buildId,\n expoApiServerURL,\n expoToken,\n extensions,\n}: {\n logger: bunyan;\n buildId: string;\n expoApiServerURL: string;\n expoToken: string | null;\n extensions: string[];\n}): Promise<{ artifactPath: string }> {\n const tempDirectory = await fs.promises.mkdtemp(os.tmpdir());\n\n const response = await retryOnDNSFailure(fetch)(\n new URL(`/v2/artifacts/eas/${buildId}`, expoApiServerURL),\n {\n headers: expoToken ? { Authorization: `Bearer ${expoToken}` } : undefined,\n }\n );\n\n if (!response.ok) {\n const textResult = await asyncResult(response.text());\n throw new Error(`Unexpected response from server (${response.status}): ${textResult.value}`);\n }\n\n // URL may contain percent-encoded characters, e.g. my%20file.apk\n // this replaces all non-alphanumeric characters (excluding dot) with underscore\n const archiveFilename = path\n .basename(new URL(response.url).pathname)\n .replace(/([^a-z0-9.-]+)/gi, '_');\n const archivePath = path.join(tempDirectory, archiveFilename);\n\n await streamPipeline(response.body, fs.createWriteStream(archivePath));\n\n const { size } = await fs.promises.stat(archivePath);\n\n logger.info(`Downloaded ${archivePath} (${formatBytes(size)} bytes).`);\n\n const isFileATarGzArchive = await isFileTarGzAsync(archivePath);\n\n if (!isFileATarGzArchive) {\n logger.info(`Artifact is not a .tar.gz archive, skipping decompression and validation.`);\n return { artifactPath: archivePath };\n }\n\n const extractionDirectory = await fs.promises.mkdtemp(os.tmpdir());\n await decompressTarAsync({\n archivePath,\n destinationDirectory: extractionDirectory,\n });\n\n const matchingFiles = await glob(`**/*.(${extensions.join('|')})`, {\n absolute: true,\n cwd: extractionDirectory,\n onlyFiles: false,\n onlyDirectories: false,\n });\n\n if (matchingFiles.length === 0) {\n throw new UserFacingError(\n 'EAS_DOWNLOAD_BUILD_NO_MATCHING_FILES',\n `No ${extensions.map((ext) => `.${ext}`).join(', ')} entries found in the archive.`\n );\n }\n\n logger.info(\n `Found ${matchingFiles.length} matching ${pluralize(matchingFiles.length, 'entry')}:\\n${matchingFiles.map((f) => `- ${path.relative(extractionDirectory, f)}`).join('\\n')}`\n );\n\n return { artifactPath: matchingFiles[0] };\n}\n"]}
@@ -18,3 +18,4 @@ export declare function uploadApplicationArchive(ctx: BuildContext<Job>, { logge
18
18
  patternOrPath: string;
19
19
  rootDir: string;
20
20
  }): Promise<void>;
21
+ export declare function formatBytes(bytes: number): string;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.uploadApplicationArchive = exports.maybeFindAndUploadBuildArtifacts = exports.findArtifacts = exports.FindArtifactsError = void 0;
6
+ exports.formatBytes = exports.uploadApplicationArchive = exports.maybeFindAndUploadBuildArtifacts = exports.findArtifacts = exports.FindArtifactsError = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const fast_glob_1 = __importDefault(require("fast-glob"));
@@ -163,4 +163,5 @@ function formatBytes(bytes) {
163
163
  }
164
164
  return `${Math.floor(bytes / 1024)} GB`;
165
165
  }
166
+ exports.formatBytes = formatBytes;
166
167
  //# sourceMappingURL=artifacts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/utils/artifacts.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,wDAA0B;AAC1B,0DAA2B;AAE3B,uDAAyE;AACzE,kEAAyC;AAIzC,MAAa,kBAAmB,SAAQ,KAAK;CAAG;AAAhD,gDAAgD;AAEzC,KAAK,UAAU,aAAa,CAAC,EAClC,OAAO,EACP,aAAa,EACb,MAAM,GAMP;IACC,MAAM,KAAK,GAAG,cAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAC1C,CAAC,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;YACpC,CAAC,CAAC,CAAC,aAAa,CAAC;YACjB,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,MAAM,IAAA,mBAAE,EAAC,aAAa,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,mBAAE,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,kBAAkB,CAAC,wCAAwC,aAAa,GAAG,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,mBAAmB,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;YACD,MAAM,IAAI,kBAAkB,CAAC,6BAA6B,aAAa,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC5B,2DAA2D;QAC3D,mCAAmC;QACnC,IAAI,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,sDAAsD;QACtD,6CAA6C;QAC7C,OAAO,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AArCD,sCAqCC;AAED,KAAK,UAAU,mBAAmB,CAAC,YAAoB,EAAE,WAAmB;IAC1E,IAAI,WAAW,GAAG,YAAY,CAAC;IAC/B,OAAO,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC3C,WAAW,GAAG,cAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,WAAW,KAAK,cAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;QACpD,WAAW,CAAC,KAAK,CAAC,uCAAuC,YAAY,IAAI,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,WAAW,CAAC,KAAK,CACf,uCAAuC,YAAY,iBAAiB,WAAW,aAAa,CAC7F,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,KAAK,CACf,uCAAuC,YAAY,iBAAiB,WAAW,eAAe,UAAU,CAAC,IAAI,CAC3G,IAAI,CACL,IAAI,CACN,CAAC;IACJ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,gCAAgC,CACpD,GAA2B,EAC3B,EAAE,MAAM,EAAsB;IAE9B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3E,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,CACrB,MAAM,OAAO,CAAC,GAAG,CACf,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACtC,aAAa,CAAC;YACZ,OAAO,EAAE,GAAG,CAAC,8BAA8B,EAAE;YAC7C,aAAa,EAAE,IAAI;YACnB,MAAM;SACP,CAAC,CACH,CACF,CACF,CAAC,IAAI,EAAE,CAAC;QACT,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC/D,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChC,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;YAC1C,MAAM,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC5C,MAAM,GAAG,CAAC,cAAc,CAAC;YACvB,QAAQ,EAAE;gBACR,IAAI,EAAE,mCAAmB,CAAC,eAAe;gBACzC,KAAK,EAAE,cAAc;aACtB;YACD,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,kCAAkC,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AApCD,4EAoCC;AAEM,KAAK,UAAU,wBAAwB,CAC5C,GAAsB,EACtB,EACE,MAAM,EACN,aAAa,EACb,OAAO,GAKR;IAED,MAAM,mBAAmB,GAAG,MAAM,aAAa,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACpE,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACrC,KAAK,MAAM,YAAY,IAAI,mBAAmB,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAChD,MAAM,GAAG,CAAC,cAAc,CAAC;QACvB,QAAQ,EAAE;YACR,IAAI,EAAE,mCAAmB,CAAC,mBAAmB;YAC7C,KAAK,EAAE,mBAAmB;SAC3B;QACD,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AA3BD,4DA2BC;AAED,KAAK,UAAU,iBAAiB,CAAC,SAAmB;IAClD,MAAM,cAAc,GAAuC,EAAE,CAAC;IAC9D,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/B,cAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC,CAAC,CACH,CAAC;IACF,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,kBAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,MAAM,IAAA,mBAAE,EAAC,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEnE,IAAI,KAAK,CAAC,MAAM,GAAG,MAAO,EAAE,CAAC;gBAC3B,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,uBAAuB,GAAG,IAAA,uBAAY,EAAS,GAAG,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,uBAAuB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,kBAAE,CAAC,IAAI,CAAC,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CACrF,CACF,CAAC;YACF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,aAAa;AACb,4HAA4H;AAC5H,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,KAAK,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC;QAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IAClC,CAAC;IACD,UAAU,IAAI,IAAI,CAAC;IACnB,IAAI,KAAK,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACjD,CAAC;IACD,IAAI,KAAK,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC;QAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1C,CAAC;IACD,UAAU,IAAI,IAAI,CAAC;IACnB,IAAI,KAAK,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACjD,CAAC;IACD,IAAI,KAAK,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC;QAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;IAChD,CAAC;IACD,UAAU,IAAI,IAAI,CAAC;IACnB,IAAI,KAAK,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AAC1C,CAAC","sourcesContent":["import path from 'path';\n\nimport fs from 'fs-extra';\nimport fg from 'fast-glob';\nimport { bunyan } from '@expo/logger';\nimport { ManagedArtifactType, Job, BuildJob } from '@expo/eas-build-job';\nimport promiseLimit from 'promise-limit';\n\nimport { BuildContext } from '../context';\n\nexport class FindArtifactsError extends Error {}\n\nexport async function findArtifacts({\n rootDir,\n patternOrPath,\n logger,\n}: {\n rootDir: string;\n patternOrPath: string;\n /** If provided, will log error suggesting possible files to upload. */\n logger: bunyan | null;\n}): Promise<string[]> {\n const files = path.isAbsolute(patternOrPath)\n ? (await fs.pathExists(patternOrPath))\n ? [patternOrPath]\n : []\n : await fg(patternOrPath, { cwd: rootDir, onlyFiles: false });\n if (files.length === 0) {\n if (fg.isDynamicPattern(patternOrPath)) {\n throw new FindArtifactsError(`There are no files matching pattern \"${patternOrPath}\"`);\n } else {\n if (logger) {\n await logMissingFileError(path.join(rootDir, patternOrPath), logger);\n }\n throw new FindArtifactsError(`No such file or directory ${patternOrPath}`);\n }\n }\n\n return files.map((filePath) => {\n // User may provide an absolute path as input in which case\n // fg will return an absolute path.\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n\n // User may also provide a relative path in which case\n // fg will return a path relative to rootDir.\n return path.join(rootDir, filePath);\n });\n}\n\nasync function logMissingFileError(artifactPath: string, buildLogger: bunyan): Promise<void> {\n let currentPath = artifactPath;\n while (!(await fs.pathExists(currentPath))) {\n currentPath = path.resolve(currentPath, '..');\n }\n if (currentPath === path.resolve(currentPath, '..')) {\n buildLogger.error(`There is no such file or directory \"${artifactPath}\".`);\n return;\n }\n const dirContent = await fs.readdir(currentPath);\n if (dirContent.length === 0) {\n buildLogger.error(\n `There is no such file or directory \"${artifactPath}\". Directory \"${currentPath}\" is empty.`\n );\n } else {\n buildLogger.error(\n `There is no such file or directory \"${artifactPath}\". Directory \"${currentPath}\" contains [${dirContent.join(\n ', '\n )}].`\n );\n }\n}\n\nexport async function maybeFindAndUploadBuildArtifacts(\n ctx: BuildContext<BuildJob>,\n { logger }: { logger: bunyan }\n): Promise<void> {\n if (!ctx.job.buildArtifactPaths || ctx.job.buildArtifactPaths.length === 0) {\n return;\n }\n try {\n const buildArtifacts = (\n await Promise.all(\n ctx.job.buildArtifactPaths.map((path) =>\n findArtifacts({\n rootDir: ctx.getReactNativeProjectDirectory(),\n patternOrPath: path,\n logger,\n })\n )\n )\n ).flat();\n const artifactsSizes = await getArtifactsSizes(buildArtifacts);\n logger.info(`Build artifacts:`);\n for (const artifactPath of buildArtifacts) {\n const maybeSize = artifactsSizes[artifactPath];\n logger.info(` - ${artifactPath}${maybeSize ? ` (${formatBytes(maybeSize)})` : ''}`);\n }\n logger.info('Uploading build artifacts...');\n await ctx.uploadArtifact({\n artifact: {\n type: ManagedArtifactType.BUILD_ARTIFACTS,\n paths: buildArtifacts,\n },\n logger,\n });\n } catch (err: any) {\n logger.error({ err }, 'Failed to upload build artifacts');\n }\n}\n\nexport async function uploadApplicationArchive(\n ctx: BuildContext<Job>,\n {\n logger,\n patternOrPath,\n rootDir,\n }: {\n logger: bunyan;\n patternOrPath: string;\n rootDir: string;\n }\n): Promise<void> {\n const applicationArchives = await findArtifacts({ rootDir, patternOrPath, logger });\n const artifactsSizes = await getArtifactsSizes(applicationArchives);\n logger.info(`Application archives:`);\n for (const artifactPath of applicationArchives) {\n const maybeSize = artifactsSizes[artifactPath];\n logger.info(` - ${artifactPath}${maybeSize ? ` (${formatBytes(maybeSize)})` : ''}`);\n }\n logger.info('Uploading application archive...');\n await ctx.uploadArtifact({\n artifact: {\n type: ManagedArtifactType.APPLICATION_ARCHIVE,\n paths: applicationArchives,\n },\n logger,\n });\n}\n\nasync function getArtifactsSizes(artifacts: string[]): Promise<Record<string, number | undefined>> {\n const artifactsSizes: Record<string, number | undefined> = {};\n await Promise.all(\n artifacts.map(async (artifact) => {\n artifactsSizes[artifact] = await getArtifactSize(artifact);\n })\n );\n return artifactsSizes;\n}\n\nasync function getArtifactSize(artifact: string): Promise<number | undefined> {\n try {\n const stat = await fs.stat(artifact);\n if (!stat.isDirectory()) {\n return stat.size;\n } else {\n const files = await fg('**/*', { cwd: artifact, onlyFiles: true });\n\n if (files.length > 100_000) {\n return undefined;\n }\n\n const getFileSizePromiseLimit = promiseLimit<number>(100);\n const sizes = await Promise.all(\n files.map((file) =>\n getFileSizePromiseLimit(async () => (await fs.stat(path.join(artifact, file))).size)\n )\n );\n return sizes.reduce((acc, size) => acc + size, 0);\n }\n } catch {\n return undefined;\n }\n}\n\n// same as in\n// https://github.com/expo/eas-cli/blob/f0e3b648a1634266e7d723bd49a84866ab9b5801/packages/eas-cli/src/utils/files.ts#L33-L60\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return `0`;\n }\n let multiplier = 1;\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes)} B`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} KB`;\n }\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes / 1024)} KB`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} MB`;\n }\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes / multiplier)} MB`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} GB`;\n }\n return `${Math.floor(bytes / 1024)} GB`;\n}\n"]}
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/utils/artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport fs from 'fs-extra';\nimport fg from 'fast-glob';\nimport { bunyan } from '@expo/logger';\nimport { ManagedArtifactType, Job, BuildJob } from '@expo/eas-build-job';\nimport promiseLimit from 'promise-limit';\n\nimport { BuildContext } from '../context';\n\nexport class FindArtifactsError extends Error {}\n\nexport async function findArtifacts({\n rootDir,\n patternOrPath,\n logger,\n}: {\n rootDir: string;\n patternOrPath: string;\n /** If provided, will log error suggesting possible files to upload. */\n logger: bunyan | null;\n}): Promise<string[]> {\n const files = path.isAbsolute(patternOrPath)\n ? (await fs.pathExists(patternOrPath))\n ? [patternOrPath]\n : []\n : await fg(patternOrPath, { cwd: rootDir, onlyFiles: false });\n if (files.length === 0) {\n if (fg.isDynamicPattern(patternOrPath)) {\n throw new FindArtifactsError(`There are no files matching pattern \"${patternOrPath}\"`);\n } else {\n if (logger) {\n await logMissingFileError(path.join(rootDir, patternOrPath), logger);\n }\n throw new FindArtifactsError(`No such file or directory ${patternOrPath}`);\n }\n }\n\n return files.map((filePath) => {\n // User may provide an absolute path as input in which case\n // fg will return an absolute path.\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n\n // User may also provide a relative path in which case\n // fg will return a path relative to rootDir.\n return path.join(rootDir, filePath);\n });\n}\n\nasync function logMissingFileError(artifactPath: string, buildLogger: bunyan): Promise<void> {\n let currentPath = artifactPath;\n while (!(await fs.pathExists(currentPath))) {\n currentPath = path.resolve(currentPath, '..');\n }\n if (currentPath === path.resolve(currentPath, '..')) {\n buildLogger.error(`There is no such file or directory \"${artifactPath}\".`);\n return;\n }\n const dirContent = await fs.readdir(currentPath);\n if (dirContent.length === 0) {\n buildLogger.error(\n `There is no such file or directory \"${artifactPath}\". Directory \"${currentPath}\" is empty.`\n );\n } else {\n buildLogger.error(\n `There is no such file or directory \"${artifactPath}\". Directory \"${currentPath}\" contains [${dirContent.join(\n ', '\n )}].`\n );\n }\n}\n\nexport async function maybeFindAndUploadBuildArtifacts(\n ctx: BuildContext<BuildJob>,\n { logger }: { logger: bunyan }\n): Promise<void> {\n if (!ctx.job.buildArtifactPaths || ctx.job.buildArtifactPaths.length === 0) {\n return;\n }\n try {\n const buildArtifacts = (\n await Promise.all(\n ctx.job.buildArtifactPaths.map((path) =>\n findArtifacts({\n rootDir: ctx.getReactNativeProjectDirectory(),\n patternOrPath: path,\n logger,\n })\n )\n )\n ).flat();\n const artifactsSizes = await getArtifactsSizes(buildArtifacts);\n logger.info(`Build artifacts:`);\n for (const artifactPath of buildArtifacts) {\n const maybeSize = artifactsSizes[artifactPath];\n logger.info(` - ${artifactPath}${maybeSize ? ` (${formatBytes(maybeSize)})` : ''}`);\n }\n logger.info('Uploading build artifacts...');\n await ctx.uploadArtifact({\n artifact: {\n type: ManagedArtifactType.BUILD_ARTIFACTS,\n paths: buildArtifacts,\n },\n logger,\n });\n } catch (err: any) {\n logger.error({ err }, 'Failed to upload build artifacts');\n }\n}\n\nexport async function uploadApplicationArchive(\n ctx: BuildContext<Job>,\n {\n logger,\n patternOrPath,\n rootDir,\n }: {\n logger: bunyan;\n patternOrPath: string;\n rootDir: string;\n }\n): Promise<void> {\n const applicationArchives = await findArtifacts({ rootDir, patternOrPath, logger });\n const artifactsSizes = await getArtifactsSizes(applicationArchives);\n logger.info(`Application archives:`);\n for (const artifactPath of applicationArchives) {\n const maybeSize = artifactsSizes[artifactPath];\n logger.info(` - ${artifactPath}${maybeSize ? ` (${formatBytes(maybeSize)})` : ''}`);\n }\n logger.info('Uploading application archive...');\n await ctx.uploadArtifact({\n artifact: {\n type: ManagedArtifactType.APPLICATION_ARCHIVE,\n paths: applicationArchives,\n },\n logger,\n });\n}\n\nasync function getArtifactsSizes(artifacts: string[]): Promise<Record<string, number | undefined>> {\n const artifactsSizes: Record<string, number | undefined> = {};\n await Promise.all(\n artifacts.map(async (artifact) => {\n artifactsSizes[artifact] = await getArtifactSize(artifact);\n })\n );\n return artifactsSizes;\n}\n\nasync function getArtifactSize(artifact: string): Promise<number | undefined> {\n try {\n const stat = await fs.stat(artifact);\n if (!stat.isDirectory()) {\n return stat.size;\n } else {\n const files = await fg('**/*', { cwd: artifact, onlyFiles: true });\n\n if (files.length > 100_000) {\n return undefined;\n }\n\n const getFileSizePromiseLimit = promiseLimit<number>(100);\n const sizes = await Promise.all(\n files.map((file) =>\n getFileSizePromiseLimit(async () => (await fs.stat(path.join(artifact, file))).size)\n )\n );\n return sizes.reduce((acc, size) => acc + size, 0);\n }\n } catch {\n return undefined;\n }\n}\n\n// same as in\n// https://github.com/expo/eas-cli/blob/f0e3b648a1634266e7d723bd49a84866ab9b5801/packages/eas-cli/src/utils/files.ts#L33-L60\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) {\n return `0`;\n }\n let multiplier = 1;\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes)} B`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} KB`;\n }\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes / 1024)} KB`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} MB`;\n }\n if (bytes < 1024 * multiplier) {\n return `${Math.floor(bytes / multiplier)} MB`;\n }\n multiplier *= 1024;\n if (bytes < 102.4 * multiplier) {\n return `${(bytes / multiplier).toFixed(1)} GB`;\n }\n return `${Math.floor(bytes / 1024)} GB`;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare function decompressTarAsync({ archivePath, destinationDirectory, }: {
2
+ archivePath: string;
3
+ destinationDirectory: string;
4
+ }): Promise<void>;
5
+ export declare function isFileTarGzAsync(path: string): Promise<boolean>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.isFileTarGzAsync = exports.decompressTarAsync = void 0;
30
+ // import fs from 'node:fs';
31
+ const promises_1 = __importDefault(require("node:fs/promises"));
32
+ const node_stream_1 = __importDefault(require("node:stream"));
33
+ const node_util_1 = require("node:util");
34
+ const tar = __importStar(require("tar"));
35
+ const streamPipeline = (0, node_util_1.promisify)(node_stream_1.default.pipeline);
36
+ async function decompressTarAsync({ archivePath, destinationDirectory, }) {
37
+ const fileHandle = await promises_1.default.open(archivePath, 'r');
38
+ await streamPipeline(fileHandle.createReadStream(), tar.extract({ cwd: destinationDirectory }, []));
39
+ }
40
+ exports.decompressTarAsync = decompressTarAsync;
41
+ async function isFileTarGzAsync(path) {
42
+ if (path.endsWith('tar.gz') || path.endsWith('.tgz')) {
43
+ return true;
44
+ }
45
+ // read only first 3 bytes to check if it's gzip
46
+ const fd = await promises_1.default.open(path, 'r');
47
+ const { buffer } = await fd.read(Buffer.alloc(3), 0, 3, 0);
48
+ await fd.close();
49
+ if (buffer.length < 3) {
50
+ return false;
51
+ }
52
+ // Check whether provided `buffer` is a valid Gzip file header
53
+ // Gzip files always begin with 0x1F 0x8B 0x08 magic bytes
54
+ // Source: https://en.wikipedia.org/wiki/Gzip#File_format
55
+ return buffer[0] === 0x1f && buffer[1] === 0x8b && buffer[2] === 0x08;
56
+ }
57
+ exports.isFileTarGzAsync = isFileTarGzAsync;
58
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4BAA4B;AAC5B,gEAA0C;AAC1C,8DAAiC;AACjC,yCAAsC;AAEtC,yCAA2B;AAE3B,MAAM,cAAc,GAAG,IAAA,qBAAS,EAAC,qBAAM,CAAC,QAAQ,CAAC,CAAC;AAE3C,KAAK,UAAU,kBAAkB,CAAC,EACvC,WAAW,EACX,oBAAoB,GAIrB;IACC,MAAM,UAAU,GAAG,MAAM,kBAAU,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,cAAc,CAClB,UAAU,CAAC,gBAAgB,EAAE,EAC7B,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAC/C,CAAC;AACJ,CAAC;AAZD,gDAYC;AAEM,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gDAAgD;IAChD,MAAM,EAAE,GAAG,MAAM,kBAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IAEjB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,8DAA8D;IAC9D,0DAA0D;IAC1D,yDAAyD;IACzD,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AACxE,CAAC;AAlBD,4CAkBC","sourcesContent":["// import fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport stream from 'node:stream';\nimport { promisify } from 'node:util';\n\nimport * as tar from 'tar';\n\nconst streamPipeline = promisify(stream.pipeline);\n\nexport async function decompressTarAsync({\n archivePath,\n destinationDirectory,\n}: {\n archivePath: string;\n destinationDirectory: string;\n}): Promise<void> {\n const fileHandle = await fsPromises.open(archivePath, 'r');\n await streamPipeline(\n fileHandle.createReadStream(),\n tar.extract({ cwd: destinationDirectory }, [])\n );\n}\n\nexport async function isFileTarGzAsync(path: string): Promise<boolean> {\n if (path.endsWith('tar.gz') || path.endsWith('.tgz')) {\n return true;\n }\n\n // read only first 3 bytes to check if it's gzip\n const fd = await fsPromises.open(path, 'r');\n const { buffer } = await fd.read(Buffer.alloc(3), 0, 3, 0);\n await fd.close();\n\n if (buffer.length < 3) {\n return false;\n }\n\n // Check whether provided `buffer` is a valid Gzip file header\n // Gzip files always begin with 0x1F 0x8B 0x08 magic bytes\n // Source: https://en.wikipedia.org/wiki/Gzip#File_format\n return buffer[0] === 0x1f && buffer[1] === 0x8b && buffer[2] === 0x08;\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare const pluralize: (count: number, word: string) => string;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pluralize = void 0;
4
+ const PLURAL_WORDS = {
5
+ entry: 'entries',
6
+ };
7
+ const pluralize = (count, word) => {
8
+ var _a;
9
+ const shouldUsePluralWord = count > 1 || count === 0;
10
+ const pluralWord = (_a = PLURAL_WORDS[word]) !== null && _a !== void 0 ? _a : `${word}s`;
11
+ return shouldUsePluralWord ? pluralWord : word;
12
+ };
13
+ exports.pluralize = pluralize;
14
+ //# sourceMappingURL=strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.js","sourceRoot":"","sources":["../../src/utils/strings.ts"],"names":[],"mappings":";;;AAAA,MAAM,YAAY,GAA2B;IAC3C,KAAK,EAAE,SAAS;CACjB,CAAC;AAEK,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,IAAY,EAAU,EAAE;;IAC/D,MAAM,mBAAmB,GAAG,KAAK,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,MAAA,YAAY,CAAC,IAAI,CAAC,mCAAI,GAAG,IAAI,GAAG,CAAC;IAEpD,OAAO,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC,CAAC;AALW,QAAA,SAAS,aAKpB","sourcesContent":["const PLURAL_WORDS: Record<string, string> = {\n entry: 'entries',\n};\n\nexport const pluralize = (count: number, word: string): string => {\n const shouldUsePluralWord = count > 1 || count === 0;\n const pluralWord = PLURAL_WORDS[word] ?? `${word}s`;\n\n return shouldUsePluralWord ? pluralWord : word;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "1.0.178",
3
+ "version": "1.0.179",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -49,7 +49,8 @@
49
49
  "promise-retry": "^2.0.1",
50
50
  "resolve-from": "^5.0.0",
51
51
  "retry": "^0.13.1",
52
- "semver": "^7.6.2"
52
+ "semver": "^7.6.2",
53
+ "tar": "^7.4.3"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/fs-extra": "^11.0.4",
@@ -64,7 +65,7 @@
64
65
  "@types/semver": "^7.5.8",
65
66
  "@types/uuid": "^9.0.8",
66
67
  "jest": "^29.7.0",
67
- "memfs": "^4.6.0",
68
+ "memfs": "^4.17.1",
68
69
  "ts-jest": "^29.1.4",
69
70
  "ts-mockito": "^2.6.1",
70
71
  "tslib": "^2.6.3",
@@ -75,5 +76,5 @@
75
76
  "node": "20.14.0",
76
77
  "yarn": "1.22.21"
77
78
  },
78
- "gitHead": "4f6c5a1eaa3fd24586d304e33e8edf8731791659"
79
+ "gitHead": "21a7204b1a03c579492c9d039eba3f08004a6be6"
79
80
  }