@expo/build-tools 1.0.48 → 1.0.49

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.
@@ -16,7 +16,7 @@ async function installDependenciesAsync(ctx, { logger, workingDir }) {
16
16
  else if (ctx.packageManager === packageManager_1.PackageManager.YARN) {
17
17
  const isYarn2 = await (0, project_1.isUsingYarn2)(ctx.getReactNativeProjectDirectory());
18
18
  if (isYarn2) {
19
- args = ['install', '--no-immutable'];
19
+ args = ['install', '--no-immutable', '--inline-builds'];
20
20
  }
21
21
  }
22
22
  logger.info(`Running "${ctx.packageManager} ${args.join(' ')}" in ${workingDir} directory`);
@@ -1 +1 @@
1
- {"version":3,"file":"installDependencies.js","sourceRoot":"","sources":["../../src/common/installDependencies.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAIxB,sEAAuC;AAGvC,4DAA8E;AAC9E,8CAAgD;AAEzC,KAAK,UAAU,wBAAwB,CAC5C,GAAuB,EACvB,EAAE,MAAM,EAAE,UAAU,EAA0C;IAE9D,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QAC9C,IAAI,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;KAC5C;SAAM,IAAI,GAAG,CAAC,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QACrD,MAAM,OAAO,GAAG,MAAM,IAAA,sBAAY,EAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC;QACzE,IAAI,OAAO,EAAE;YACX,IAAI,GAAG,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;SACtC;KACF;IACD,MAAM,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,UAAU,YAAY,CAAC,CAAC;IAC5F,MAAM,IAAA,sBAAK,EAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE;QACpC,GAAG,EAAE,UAAU;QACf,MAAM;QACN,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAAC;AACL,CAAC;AAnBD,4DAmBC;AAED,SAAgB,kBAAkB,CAAC,GAAsB;IACvD,MAAM,cAAc,GAAG,IAAA,oCAAmB,EAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC;IACjF,IAAI,cAAc,KAAK,GAAG,CAAC,8BAA8B,EAAE,EAAE;QAC3D,MAAM,mCAAmC,GAAG,cAAI,CAAC,QAAQ,CACvD,GAAG,CAAC,cAAc,EAClB,GAAG,CAAC,8BAA8B,EAAE,CACrC,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,qBAAqB,mCAAmC,UAAU,GAAG,CAAC,cAAc,YAAY,CACjG,CAAC;KACH;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAZD,gDAYC","sourcesContent":["import path from 'path';\n\nimport { Job } from '@expo/eas-build-job';\nimport { bunyan } from '@expo/logger';\nimport spawn from '@expo/turtle-spawn';\n\nimport { BuildContext } from '../context';\nimport { PackageManager, findPackagerRootDir } from '../utils/packageManager';\nimport { isUsingYarn2 } from '../utils/project';\n\nexport async function installDependenciesAsync<TJob extends Job>(\n ctx: BuildContext<TJob>,\n { logger, workingDir }: { logger: bunyan; workingDir: string }\n): Promise<void> {\n let args = ['install'];\n if (ctx.packageManager === PackageManager.PNPM) {\n args = ['install', '--no-frozen-lockfile'];\n } else if (ctx.packageManager === PackageManager.YARN) {\n const isYarn2 = await isUsingYarn2(ctx.getReactNativeProjectDirectory());\n if (isYarn2) {\n args = ['install', '--no-immutable'];\n }\n }\n logger.info(`Running \"${ctx.packageManager} ${args.join(' ')}\" in ${workingDir} directory`);\n await spawn(ctx.packageManager, args, {\n cwd: workingDir,\n logger,\n env: ctx.env,\n });\n}\n\nexport function resolvePackagerDir(ctx: BuildContext<Job>): string {\n const packagerRunDir = findPackagerRootDir(ctx.getReactNativeProjectDirectory());\n if (packagerRunDir !== ctx.getReactNativeProjectDirectory()) {\n const relativeReactNativeProjectDirectory = path.relative(\n ctx.buildDirectory,\n ctx.getReactNativeProjectDirectory()\n );\n ctx.logger.info(\n `We detected that '${relativeReactNativeProjectDirectory}' is a ${ctx.packageManager} workspace`\n );\n }\n return packagerRunDir;\n}\n"]}
1
+ {"version":3,"file":"installDependencies.js","sourceRoot":"","sources":["../../src/common/installDependencies.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAIxB,sEAAuC;AAGvC,4DAA8E;AAC9E,8CAAgD;AAEzC,KAAK,UAAU,wBAAwB,CAC5C,GAAuB,EACvB,EAAE,MAAM,EAAE,UAAU,EAA0C;IAE9D,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QAC9C,IAAI,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;KAC5C;SAAM,IAAI,GAAG,CAAC,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QACrD,MAAM,OAAO,GAAG,MAAM,IAAA,sBAAY,EAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC;QACzE,IAAI,OAAO,EAAE;YACX,IAAI,GAAG,CAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;SACzD;KACF;IACD,MAAM,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,UAAU,YAAY,CAAC,CAAC;IAC5F,MAAM,IAAA,sBAAK,EAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE;QACpC,GAAG,EAAE,UAAU;QACf,MAAM;QACN,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAAC;AACL,CAAC;AAnBD,4DAmBC;AAED,SAAgB,kBAAkB,CAAC,GAAsB;IACvD,MAAM,cAAc,GAAG,IAAA,oCAAmB,EAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC;IACjF,IAAI,cAAc,KAAK,GAAG,CAAC,8BAA8B,EAAE,EAAE;QAC3D,MAAM,mCAAmC,GAAG,cAAI,CAAC,QAAQ,CACvD,GAAG,CAAC,cAAc,EAClB,GAAG,CAAC,8BAA8B,EAAE,CACrC,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,qBAAqB,mCAAmC,UAAU,GAAG,CAAC,cAAc,YAAY,CACjG,CAAC;KACH;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAZD,gDAYC","sourcesContent":["import path from 'path';\n\nimport { Job } from '@expo/eas-build-job';\nimport { bunyan } from '@expo/logger';\nimport spawn from '@expo/turtle-spawn';\n\nimport { BuildContext } from '../context';\nimport { PackageManager, findPackagerRootDir } from '../utils/packageManager';\nimport { isUsingYarn2 } from '../utils/project';\n\nexport async function installDependenciesAsync<TJob extends Job>(\n ctx: BuildContext<TJob>,\n { logger, workingDir }: { logger: bunyan; workingDir: string }\n): Promise<void> {\n let args = ['install'];\n if (ctx.packageManager === PackageManager.PNPM) {\n args = ['install', '--no-frozen-lockfile'];\n } else if (ctx.packageManager === PackageManager.YARN) {\n const isYarn2 = await isUsingYarn2(ctx.getReactNativeProjectDirectory());\n if (isYarn2) {\n args = ['install', '--no-immutable', '--inline-builds'];\n }\n }\n logger.info(`Running \"${ctx.packageManager} ${args.join(' ')}\" in ${workingDir} directory`);\n await spawn(ctx.packageManager, args, {\n cwd: workingDir,\n logger,\n env: ctx.env,\n });\n}\n\nexport function resolvePackagerDir(ctx: BuildContext<Job>): string {\n const packagerRunDir = findPackagerRootDir(ctx.getReactNativeProjectDirectory());\n if (packagerRunDir !== ctx.getReactNativeProjectDirectory()) {\n const relativeReactNativeProjectDirectory = path.relative(\n ctx.buildDirectory,\n ctx.getReactNativeProjectDirectory()\n );\n ctx.logger.info(\n `We detected that '${relativeReactNativeProjectDirectory}' is a ${ctx.packageManager} workspace`\n );\n }\n return packagerRunDir;\n}\n"]}
@@ -102,7 +102,7 @@ class IosCredentialsManager {
102
102
  this.ctx.logger.info('Initializing provisioning profile');
103
103
  const provisioningProfile = new provisioningProfile_1.default(this.ctx, Buffer.from(targetCredentials.provisioningProfileBase64, 'base64'), this.keychain.data.path, target, certificateCommonName);
104
104
  await provisioningProfile.init();
105
- this.ctx.logger.info('Validating whether distribution certificate has been imported successfully');
105
+ this.ctx.logger.info('Validating whether the distribution certificate has been imported successfully');
106
106
  await this.keychain.ensureCertificateImported(provisioningProfile.data.teamId, certificateFingerprint);
107
107
  this.ctx.logger.info('Verifying whether the distribution certificate and provisioning profile match');
108
108
  provisioningProfile.verifyCertificate(certificateFingerprint);
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/ios/credentials/manager.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport os from 'os';\nimport path from 'path';\n\nimport { Ios } from '@expo/eas-build-job';\nimport fs from 'fs-extra';\nimport { orderBy } from 'lodash';\nimport nullthrows from 'nullthrows';\nimport { v4 as uuid } from 'uuid';\n\nimport { BuildContext } from '../../context';\n\nimport * as distributionCertificateUtils from './distributionCertificate';\nimport Keychain from './keychain';\nimport ProvisioningProfile, {\n DistributionType,\n ProvisioningProfileData,\n} from './provisioningProfile';\n\nexport interface Credentials {\n applicationTargetProvisioningProfile: ProvisioningProfile<Ios.Job>;\n keychainPath: string;\n targetProvisioningProfiles: TargetProvisioningProfiles;\n distributionType: DistributionType;\n teamId: string;\n}\n\nexport type TargetProvisioningProfiles = Record<string, ProvisioningProfileData>;\n\nexport default class IosCredentialsManager<TJob extends Ios.Job> {\n private keychain?: Keychain<TJob>;\n private readonly provisioningProfiles: ProvisioningProfile<TJob>[] = [];\n private cleanedUp = false;\n\n constructor(private readonly ctx: BuildContext<TJob>) {}\n\n public async prepare(): Promise<Credentials | null> {\n if (this.ctx.job.simulator) {\n return null;\n }\n\n const { buildCredentials } = nullthrows(\n this.ctx.job.secrets,\n 'Secrets must be defined for non-custom builds'\n );\n if (!buildCredentials) {\n throw new Error('credentials are required for an iOS build');\n }\n\n this.ctx.logger.info('Preparing credentials');\n\n this.ctx.logger.info('Creating keychain');\n this.keychain = new Keychain(this.ctx);\n await this.keychain.create();\n\n const targets = Object.keys(buildCredentials);\n const targetProvisioningProfiles: TargetProvisioningProfiles = {};\n for (const target of targets) {\n const provisioningProfile = await this.prepareTargetCredentials(\n target,\n buildCredentials[target]\n );\n this.provisioningProfiles.push(provisioningProfile);\n targetProvisioningProfiles[target] = provisioningProfile.data;\n }\n\n const applicationTargetProvisioningProfile = this.getApplicationTargetProvisioningProfile();\n\n // TODO: ensure that all dist types and team ids in the array are the same\n const { distributionType, teamId } = applicationTargetProvisioningProfile.data;\n\n return {\n applicationTargetProvisioningProfile,\n keychainPath: this.keychain.data.path,\n targetProvisioningProfiles,\n distributionType,\n teamId,\n };\n }\n\n public async cleanUp(): Promise<void> {\n if (this.cleanedUp || (!this.keychain && this.provisioningProfiles.length === 0)) {\n return;\n }\n\n if (this.keychain) {\n await this.keychain.destroy();\n }\n if (this.provisioningProfiles) {\n for (const provisioningProfile of this.provisioningProfiles) {\n await provisioningProfile.destroy();\n }\n }\n this.cleanedUp = true;\n }\n\n private async prepareTargetCredentials(\n target: string,\n targetCredentials: Ios.TargetCredentials\n ): Promise<ProvisioningProfile<TJob>> {\n try {\n assert(this.keychain, 'Keychain should be initialized');\n\n this.ctx.logger.info(`Preparing credentials for target '${target}'`);\n const distCertPath = path.join(os.tmpdir(), `${uuid()}.p12`);\n\n this.ctx.logger.info('Getting distribution certificate fingerprint and common name');\n const certificateFingerprint = distributionCertificateUtils.getFingerprint(\n targetCredentials.distributionCertificate\n );\n const certificateCommonName = distributionCertificateUtils.getCommonName(\n targetCredentials.distributionCertificate\n );\n this.ctx.logger.info(\n `Fingerprint = \"${certificateFingerprint}\", common name = ${certificateCommonName}`\n );\n\n this.ctx.logger.info(`Writing distribution certificate to ${distCertPath}`);\n await fs.writeFile(\n distCertPath,\n Buffer.from(targetCredentials.distributionCertificate.dataBase64, 'base64')\n );\n\n this.ctx.logger.info('Importing distribution certificate into the keychain');\n await this.keychain.importCertificate(\n distCertPath,\n targetCredentials.distributionCertificate.password\n );\n\n this.ctx.logger.info('Initializing provisioning profile');\n const provisioningProfile = new ProvisioningProfile(\n this.ctx,\n Buffer.from(targetCredentials.provisioningProfileBase64, 'base64'),\n this.keychain.data.path,\n target,\n certificateCommonName\n );\n await provisioningProfile.init();\n\n this.ctx.logger.info(\n 'Validating whether distribution certificate has been imported successfully'\n );\n await this.keychain.ensureCertificateImported(\n provisioningProfile.data.teamId,\n certificateFingerprint\n );\n\n this.ctx.logger.info(\n 'Verifying whether the distribution certificate and provisioning profile match'\n );\n provisioningProfile.verifyCertificate(certificateFingerprint);\n\n return provisioningProfile;\n } catch (err) {\n await this.cleanUp();\n throw err;\n }\n }\n\n private getApplicationTargetProvisioningProfile(): ProvisioningProfile<TJob> {\n // sorting works because bundle ids share common prefix\n const sorted = orderBy(this.provisioningProfiles, 'data.bundleIdentifier', 'asc');\n return sorted[0];\n }\n}\n"]}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/ios/credentials/manager.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport os from 'os';\nimport path from 'path';\n\nimport { Ios } from '@expo/eas-build-job';\nimport fs from 'fs-extra';\nimport { orderBy } from 'lodash';\nimport nullthrows from 'nullthrows';\nimport { v4 as uuid } from 'uuid';\n\nimport { BuildContext } from '../../context';\n\nimport * as distributionCertificateUtils from './distributionCertificate';\nimport Keychain from './keychain';\nimport ProvisioningProfile, {\n DistributionType,\n ProvisioningProfileData,\n} from './provisioningProfile';\n\nexport interface Credentials {\n applicationTargetProvisioningProfile: ProvisioningProfile<Ios.Job>;\n keychainPath: string;\n targetProvisioningProfiles: TargetProvisioningProfiles;\n distributionType: DistributionType;\n teamId: string;\n}\n\nexport type TargetProvisioningProfiles = Record<string, ProvisioningProfileData>;\n\nexport default class IosCredentialsManager<TJob extends Ios.Job> {\n private keychain?: Keychain<TJob>;\n private readonly provisioningProfiles: ProvisioningProfile<TJob>[] = [];\n private cleanedUp = false;\n\n constructor(private readonly ctx: BuildContext<TJob>) {}\n\n public async prepare(): Promise<Credentials | null> {\n if (this.ctx.job.simulator) {\n return null;\n }\n\n const { buildCredentials } = nullthrows(\n this.ctx.job.secrets,\n 'Secrets must be defined for non-custom builds'\n );\n if (!buildCredentials) {\n throw new Error('credentials are required for an iOS build');\n }\n\n this.ctx.logger.info('Preparing credentials');\n\n this.ctx.logger.info('Creating keychain');\n this.keychain = new Keychain(this.ctx);\n await this.keychain.create();\n\n const targets = Object.keys(buildCredentials);\n const targetProvisioningProfiles: TargetProvisioningProfiles = {};\n for (const target of targets) {\n const provisioningProfile = await this.prepareTargetCredentials(\n target,\n buildCredentials[target]\n );\n this.provisioningProfiles.push(provisioningProfile);\n targetProvisioningProfiles[target] = provisioningProfile.data;\n }\n\n const applicationTargetProvisioningProfile = this.getApplicationTargetProvisioningProfile();\n\n // TODO: ensure that all dist types and team ids in the array are the same\n const { distributionType, teamId } = applicationTargetProvisioningProfile.data;\n\n return {\n applicationTargetProvisioningProfile,\n keychainPath: this.keychain.data.path,\n targetProvisioningProfiles,\n distributionType,\n teamId,\n };\n }\n\n public async cleanUp(): Promise<void> {\n if (this.cleanedUp || (!this.keychain && this.provisioningProfiles.length === 0)) {\n return;\n }\n\n if (this.keychain) {\n await this.keychain.destroy();\n }\n if (this.provisioningProfiles) {\n for (const provisioningProfile of this.provisioningProfiles) {\n await provisioningProfile.destroy();\n }\n }\n this.cleanedUp = true;\n }\n\n private async prepareTargetCredentials(\n target: string,\n targetCredentials: Ios.TargetCredentials\n ): Promise<ProvisioningProfile<TJob>> {\n try {\n assert(this.keychain, 'Keychain should be initialized');\n\n this.ctx.logger.info(`Preparing credentials for target '${target}'`);\n const distCertPath = path.join(os.tmpdir(), `${uuid()}.p12`);\n\n this.ctx.logger.info('Getting distribution certificate fingerprint and common name');\n const certificateFingerprint = distributionCertificateUtils.getFingerprint(\n targetCredentials.distributionCertificate\n );\n const certificateCommonName = distributionCertificateUtils.getCommonName(\n targetCredentials.distributionCertificate\n );\n this.ctx.logger.info(\n `Fingerprint = \"${certificateFingerprint}\", common name = ${certificateCommonName}`\n );\n\n this.ctx.logger.info(`Writing distribution certificate to ${distCertPath}`);\n await fs.writeFile(\n distCertPath,\n Buffer.from(targetCredentials.distributionCertificate.dataBase64, 'base64')\n );\n\n this.ctx.logger.info('Importing distribution certificate into the keychain');\n await this.keychain.importCertificate(\n distCertPath,\n targetCredentials.distributionCertificate.password\n );\n\n this.ctx.logger.info('Initializing provisioning profile');\n const provisioningProfile = new ProvisioningProfile(\n this.ctx,\n Buffer.from(targetCredentials.provisioningProfileBase64, 'base64'),\n this.keychain.data.path,\n target,\n certificateCommonName\n );\n await provisioningProfile.init();\n\n this.ctx.logger.info(\n 'Validating whether the distribution certificate has been imported successfully'\n );\n await this.keychain.ensureCertificateImported(\n provisioningProfile.data.teamId,\n certificateFingerprint\n );\n\n this.ctx.logger.info(\n 'Verifying whether the distribution certificate and provisioning profile match'\n );\n provisioningProfile.verifyCertificate(certificateFingerprint);\n\n return provisioningProfile;\n } catch (err) {\n await this.cleanUp();\n throw err;\n }\n }\n\n private getApplicationTargetProvisioningProfile(): ProvisioningProfile<TJob> {\n // sorting works because bundle ids share common prefix\n const sorted = orderBy(this.provisioningProfiles, 'data.bundleIdentifier', 'asc');\n return sorted[0];\n }\n}\n"]}
@@ -30,7 +30,7 @@ async function installNodeModules(stepCtx, env) {
30
30
  else if (packageManager === packageManager_1.PackageManager.YARN) {
31
31
  const isYarn2 = await (0, project_1.isUsingYarn2)(stepCtx.workingDirectory);
32
32
  if (isYarn2) {
33
- args = ['install', '--no-immutable'];
33
+ args = ['install', '--no-immutable', '--inline-builds'];
34
34
  }
35
35
  }
36
36
  logger.info(`Running "${packageManager} ${args.join(' ')}" in ${packagerRunDir} directory`);
@@ -1 +1 @@
1
- {"version":3,"file":"installNodeModules.js","sourceRoot":"","sources":["../../../src/steps/functions/installNodeModules.ts"],"names":[],"mappings":";;;;;;AAAA,uCAA0D;AAE1D,sEAAuC;AAEvC,+DAIoC;AACpC,iDAAmD;AAEnD,SAAgB,qCAAqC;IACnD,OAAO,IAAI,qBAAa,CAAC;QACvB,SAAS,EAAE,KAAK;QAChB,EAAE,EAAE,sBAAsB;QAC1B,IAAI,EAAE,sBAAsB;QAC5B,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YAC7B,MAAM,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AATD,sFASC;AAEM,KAAK,UAAU,kBAAkB,CACtC,OAAyB,EACzB,GAAiB;IAEjB,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,cAAc,GAAG,IAAA,sCAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,IAAA,oCAAmB,EAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrE,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,IAAI,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QAC1C,IAAI,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;KAC5C;SAAM,IAAI,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QACjD,MAAM,OAAO,GAAG,MAAM,IAAA,sBAAY,EAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE;YACX,IAAI,GAAG,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;SACtC;KACF;IACD,MAAM,CAAC,IAAI,CAAC,YAAY,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,cAAc,YAAY,CAAC,CAAC;IAC5F,MAAM,IAAA,sBAAK,EAAC,cAAc,EAAE,IAAI,EAAE;QAChC,GAAG,EAAE,cAAc;QACnB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,GAAG;KACJ,CAAC,CAAC;AACL,CAAC;AAtBD,gDAsBC","sourcesContent":["import { BuildFunction, BuildStepEnv } from '@expo/steps';\nimport { BuildStepContext } from '@expo/steps/dist_esm/BuildStepContext';\nimport spawn from '@expo/turtle-spawn';\n\nimport {\n findPackagerRootDir,\n PackageManager,\n resolvePackageManager,\n} from '../../utils/packageManager';\nimport { isUsingYarn2 } from '../../utils/project';\n\nexport function createInstallNodeModulesBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'install_node_modules',\n name: 'Install node modules',\n fn: async (stepCtx, { env }) => {\n await installNodeModules(stepCtx, env);\n },\n });\n}\n\nexport async function installNodeModules(\n stepCtx: BuildStepContext,\n env: BuildStepEnv\n): Promise<void> {\n const { logger } = stepCtx;\n const packageManager = resolvePackageManager(stepCtx.global.projectTargetDirectory);\n const packagerRunDir = findPackagerRootDir(stepCtx.workingDirectory);\n let args = ['install'];\n if (packageManager === PackageManager.PNPM) {\n args = ['install', '--no-frozen-lockfile'];\n } else if (packageManager === PackageManager.YARN) {\n const isYarn2 = await isUsingYarn2(stepCtx.workingDirectory);\n if (isYarn2) {\n args = ['install', '--no-immutable'];\n }\n }\n logger.info(`Running \"${packageManager} ${args.join(' ')}\" in ${packagerRunDir} directory`);\n await spawn(packageManager, args, {\n cwd: packagerRunDir,\n logger: stepCtx.logger,\n env,\n });\n}\n"]}
1
+ {"version":3,"file":"installNodeModules.js","sourceRoot":"","sources":["../../../src/steps/functions/installNodeModules.ts"],"names":[],"mappings":";;;;;;AAAA,uCAA0D;AAE1D,sEAAuC;AAEvC,+DAIoC;AACpC,iDAAmD;AAEnD,SAAgB,qCAAqC;IACnD,OAAO,IAAI,qBAAa,CAAC;QACvB,SAAS,EAAE,KAAK;QAChB,EAAE,EAAE,sBAAsB;QAC1B,IAAI,EAAE,sBAAsB;QAC5B,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YAC7B,MAAM,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AATD,sFASC;AAEM,KAAK,UAAU,kBAAkB,CACtC,OAAyB,EACzB,GAAiB;IAEjB,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,cAAc,GAAG,IAAA,sCAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,IAAA,oCAAmB,EAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrE,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,IAAI,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QAC1C,IAAI,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;KAC5C;SAAM,IAAI,cAAc,KAAK,+BAAc,CAAC,IAAI,EAAE;QACjD,MAAM,OAAO,GAAG,MAAM,IAAA,sBAAY,EAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE;YACX,IAAI,GAAG,CAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;SACzD;KACF;IACD,MAAM,CAAC,IAAI,CAAC,YAAY,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,cAAc,YAAY,CAAC,CAAC;IAC5F,MAAM,IAAA,sBAAK,EAAC,cAAc,EAAE,IAAI,EAAE;QAChC,GAAG,EAAE,cAAc;QACnB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,GAAG;KACJ,CAAC,CAAC;AACL,CAAC;AAtBD,gDAsBC","sourcesContent":["import { BuildFunction, BuildStepEnv } from '@expo/steps';\nimport { BuildStepContext } from '@expo/steps/dist_esm/BuildStepContext';\nimport spawn from '@expo/turtle-spawn';\n\nimport {\n findPackagerRootDir,\n PackageManager,\n resolvePackageManager,\n} from '../../utils/packageManager';\nimport { isUsingYarn2 } from '../../utils/project';\n\nexport function createInstallNodeModulesBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'install_node_modules',\n name: 'Install node modules',\n fn: async (stepCtx, { env }) => {\n await installNodeModules(stepCtx, env);\n },\n });\n}\n\nexport async function installNodeModules(\n stepCtx: BuildStepContext,\n env: BuildStepEnv\n): Promise<void> {\n const { logger } = stepCtx;\n const packageManager = resolvePackageManager(stepCtx.global.projectTargetDirectory);\n const packagerRunDir = findPackagerRootDir(stepCtx.workingDirectory);\n let args = ['install'];\n if (packageManager === PackageManager.PNPM) {\n args = ['install', '--no-frozen-lockfile'];\n } else if (packageManager === PackageManager.YARN) {\n const isYarn2 = await isUsingYarn2(stepCtx.workingDirectory);\n if (isYarn2) {\n args = ['install', '--no-immutable', '--inline-builds'];\n }\n }\n logger.info(`Running \"${packageManager} ${args.join(' ')}\" in ${packagerRunDir} directory`);\n await spawn(packageManager, args, {\n cwd: packagerRunDir,\n logger: stepCtx.logger,\n env,\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "1.0.48",
3
+ "version": "1.0.49",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -26,7 +26,7 @@
26
26
  "@expo/downloader": "1.0.37",
27
27
  "@expo/eas-build-job": "1.0.48",
28
28
  "@expo/logger": "1.0.37",
29
- "@expo/package-manager": "1.1.1",
29
+ "@expo/package-manager": "1.1.2",
30
30
  "@expo/plist": "^0.0.20",
31
31
  "@expo/steps": "1.0.37",
32
32
  "@expo/template-file": "1.0.37",
@@ -65,5 +65,5 @@
65
65
  "node": "18.13.0",
66
66
  "yarn": "1.22.19"
67
67
  },
68
- "gitHead": "e5078b0b17758dafb6e51fcd7a0ce3d21982af97"
68
+ "gitHead": "1e6eaee0547f5b143881a3c4138987ff9b3d641b"
69
69
  }