Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Drop nodeModulesPath support #3141

Merged
merged 11 commits into from
Feb 1, 2021
Merged
1 change: 1 addition & 0 deletions packages/config-plugins/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@expo/plist": "0.0.11",
"find-up": "~5.0.0",
"fs-extra": "9.0.0",
"resolve-from": "^5.0.0",
"getenv": "0.7.0",
"glob": "7.1.6",
"slash": "^3.0.0",
Expand Down
28 changes: 8 additions & 20 deletions packages/config-plugins/src/android/Updates.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ExpoConfig } from '@expo/config-types';
import path from 'path';
import resolveFrom from 'resolve-from';

import { ConfigPlugin } from '../Plugin.types';
import { withAndroidManifest } from '../plugins/android-plugins';
import { projectHasModule } from '../utils/modules';
import {
addMetaDataItemToMainApplication,
AndroidManifest,
Expand All @@ -16,7 +16,7 @@ const CREATE_MANIFEST_ANDROID_PATH = 'expo-updates/scripts/create-manifest-andro

type ExpoConfigUpdates = Pick<
ExpoConfig,
'sdkVersion' | 'owner' | 'runtimeVersion' | 'nodeModulesPath' | 'updates' | 'slug'
'sdkVersion' | 'owner' | 'runtimeVersion' | 'updates' | 'slug'
>;

export enum Config {
Expand Down Expand Up @@ -134,10 +134,9 @@ export function setVersionsConfig(
}
export function ensureBuildGradleContainsConfigurationScript(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>,
buildGradleContents: string
): string {
if (!isBuildGradleConfigured(projectRoot, config, buildGradleContents)) {
if (!isBuildGradleConfigured(projectRoot, buildGradleContents)) {
let cleanedUpBuildGradleContents;

const isBuildGradleMisconfigured = buildGradleContents
Expand All @@ -152,22 +151,15 @@ export function ensureBuildGradleContainsConfigurationScript(
cleanedUpBuildGradleContents = buildGradleContents;
}

const gradleScriptApply = formatApplyLineForBuildGradle(projectRoot, config);
const gradleScriptApply = formatApplyLineForBuildGradle(projectRoot);
return `${cleanedUpBuildGradleContents}\n// Integration with Expo updates\n${gradleScriptApply}\n`;
} else {
return buildGradleContents;
}
}

export function formatApplyLineForBuildGradle(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>
): string {
const updatesGradleScriptPath = projectHasModule(
CREATE_MANIFEST_ANDROID_PATH,
projectRoot,
config
);
export function formatApplyLineForBuildGradle(projectRoot: string): string {
const updatesGradleScriptPath = resolveFrom.silent(projectRoot, CREATE_MANIFEST_ANDROID_PATH);

if (!updatesGradleScriptPath) {
throw new Error(
Expand All @@ -180,12 +172,8 @@ export function formatApplyLineForBuildGradle(
)}`;
}

export function isBuildGradleConfigured(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>,
buildGradleContents: string
): boolean {
const androidBuildScript = formatApplyLineForBuildGradle(projectRoot, config);
export function isBuildGradleConfigured(projectRoot: string, buildGradleContents: string): boolean {
const androidBuildScript = formatApplyLineForBuildGradle(projectRoot);

return (
buildGradleContents
Expand Down
20 changes: 14 additions & 6 deletions packages/config-plugins/src/android/__tests__/Updates-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ const fixturesPath = path.resolve(__dirname, 'fixtures');
const sampleManifestPath = path.resolve(fixturesPath, 'react-native-AndroidManifest.xml');

jest.mock('fs');
jest.mock('resolve-from');

const { silent } = require('resolve-from');

const fsReal = jest.requireActual('fs') as typeof fs;

describe('Android Updates config', () => {
beforeEach(() => {
const resolveFrom = require('resolve-from');
resolveFrom.silent = silent;
vol.reset();
});

Expand Down Expand Up @@ -109,15 +115,18 @@ describe('Android Updates config', () => {
);

const contents = await fsExtra.readFile('/app/android/app/build.gradle', 'utf-8');
const newContents = Updates.ensureBuildGradleContainsConfigurationScript(
'/app',
{},
contents
);
const newContents = Updates.ensureBuildGradleContainsConfigurationScript('/app', contents);
expect(newContents).toMatchSnapshot();
});

it('fixes the path to create-manifest-android.gradle in case of a monorepo', async () => {
// Pseudo node module resolution since actually mocking it could prove challenging.
// In a yarn workspace, resolve-from would be able to locate a module in any node_module folder if properly linked.
const resolveFrom = require('resolve-from');
resolveFrom.silent = (p, a) => {
return silent(path.join(p, '..'), a);
};

vol.fromJSON(
{
'workspace/android/app/build.gradle': fsReal.readFileSync(
Expand All @@ -135,7 +144,6 @@ describe('Android Updates config', () => {
const contents = await fsExtra.readFile('/app/workspace/android/app/build.gradle', 'utf-8');
const newContents = Updates.ensureBuildGradleContainsConfigurationScript(
'/app/workspace',
{ nodeModulesPath: '/app' },
contents
);
expect(newContents).toMatchSnapshot();
Expand Down
19 changes: 7 additions & 12 deletions packages/config-plugins/src/ios/Updates.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { ExpoConfig } from '@expo/config-types';
import * as path from 'path';
import resolveFrom from 'resolve-from';
import xcode from 'xcode';

import { ConfigPlugin } from '../Plugin.types';
import { withExpoPlist } from '../plugins/ios-plugins';
import { projectHasModule } from '../utils/modules';
import { ExpoPlist } from './IosConfig.types';

const CREATE_MANIFEST_IOS_PATH = 'expo-updates/scripts/create-manifest-ios.sh';

type ExpoConfigUpdates = Pick<
ExpoConfig,
'sdkVersion' | 'owner' | 'runtimeVersion' | 'nodeModulesPath' | 'updates' | 'slug'
'sdkVersion' | 'owner' | 'runtimeVersion' | 'updates' | 'slug'
>;

export enum Config {
Expand Down Expand Up @@ -114,11 +114,8 @@ export function setVersionsConfig(config: ExpoConfigUpdates, expoPlist: ExpoPlis
return newExpoPlist;
}

function formatConfigurationScriptPath(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>
): string {
const buildScriptPath = projectHasModule(CREATE_MANIFEST_IOS_PATH, projectRoot, config);
function formatConfigurationScriptPath(projectRoot: string): string {
const buildScriptPath = resolveFrom.silent(projectRoot, CREATE_MANIFEST_IOS_PATH);

if (!buildScriptPath) {
throw new Error(
Expand Down Expand Up @@ -154,13 +151,12 @@ export function getBundleReactNativePhase(project: xcode.XcodeProject): ShellScr

export function ensureBundleReactNativePhaseContainsConfigurationScript(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>,
project: xcode.XcodeProject
): xcode.XcodeProject {
const bundleReactNative = getBundleReactNativePhase(project);
const buildPhaseShellScriptPath = formatConfigurationScriptPath(projectRoot, config);
const buildPhaseShellScriptPath = formatConfigurationScriptPath(projectRoot);

if (!isShellScriptBuildPhaseConfigured(projectRoot, config, project)) {
if (!isShellScriptBuildPhaseConfigured(projectRoot, project)) {
// check if there's already another path to create-manifest-ios.sh
// this might be the case for monorepos
if (bundleReactNative.shellScript.includes(CREATE_MANIFEST_IOS_PATH)) {
Expand All @@ -179,11 +175,10 @@ export function ensureBundleReactNativePhaseContainsConfigurationScript(

export function isShellScriptBuildPhaseConfigured(
projectRoot: string,
config: Pick<ExpoConfigUpdates, 'nodeModulesPath'>,
project: xcode.XcodeProject
): boolean {
const bundleReactNative = getBundleReactNativePhase(project);
const buildPhaseShellScriptPath = formatConfigurationScriptPath(projectRoot, config);
const buildPhaseShellScriptPath = formatConfigurationScriptPath(projectRoot);
return bundleReactNative.shellScript.includes(buildPhaseShellScriptPath);
}

Expand Down
16 changes: 13 additions & 3 deletions packages/config-plugins/src/ios/__tests__/Updates-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import * as Updates from '../Updates';
import { getPbxproj } from '../utils/Xcodeproj';

const fsReal = jest.requireActual('fs') as typeof fs;

jest.mock('fs');
jest.mock('resolve-from');

const { silent } = require('resolve-from');

describe('iOS Updates config', () => {
it(`returns correct default values from all getters if no value provided`, () => {
Expand Down Expand Up @@ -62,6 +64,8 @@ describe('iOS Updates config', () => {
describe(Updates.ensureBundleReactNativePhaseContainsConfigurationScript, () => {
beforeEach(() => {
vol.reset();
const resolveFrom = require('resolve-from');
resolveFrom.silent = silent;
});

it("adds create-manifest-ios.sh line to the 'Bundle React Native code and images' build phase ", () => {
Expand All @@ -77,12 +81,19 @@ describe('iOS Updates config', () => {
);

const xcodeProject = getPbxproj('/app');
Updates.ensureBundleReactNativePhaseContainsConfigurationScript('/app', {}, xcodeProject);
Updates.ensureBundleReactNativePhaseContainsConfigurationScript('/app', xcodeProject);
const bundleReactNative = Updates.getBundleReactNativePhase(xcodeProject);
expect(bundleReactNative.shellScript).toMatchSnapshot();
});

it('fixes the path to create-manifest-ios.sh in case of a monorepo', () => {
// Pseudo node module resolution since actually mocking it could prove challenging.
// In a yarn workspace, resolve-from would be able to locate a module in any node_module folder if properly linked.
const resolveFrom = require('resolve-from');
resolveFrom.silent = (p, a) => {
return silent(path.join(p, '..'), a);
};

vol.fromJSON(
{
'workspace/ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync(
Expand All @@ -99,7 +110,6 @@ describe('iOS Updates config', () => {
const xcodeProject = getPbxproj('/app/workspace');
Updates.ensureBundleReactNativePhaseContainsConfigurationScript(
'/app/workspace',
{ nodeModulesPath: '/app' },
xcodeProject
);
const bundleReactNative = Updates.getBundleReactNativePhase(xcodeProject);
Expand Down
11 changes: 0 additions & 11 deletions packages/config-plugins/src/utils/modules.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
import { ExpoConfig } from '@expo/config-types';
import { stat, Stats, statSync } from 'fs-extra';
import resolveFrom from 'resolve-from';

export function projectHasModule(
modulePath: string,
projectRoot: string,
exp: Pick<ExpoConfig, 'nodeModulesPath'>
): string | undefined {
const fromDir = exp.nodeModulesPath ? exp.nodeModulesPath : projectRoot;
return resolveFrom.silent(fromDir, modulePath);
}

/**
* A non-failing version of async FS stat.
Expand Down
8 changes: 3 additions & 5 deletions packages/config-types/src/ExpoConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@ export interface ExpoConfig {
packagerOpts?: {
[k: string]: any;
};
ignoreNodeModulesValidation?: boolean;
nodeModulesPath?: string;
/**
* Configuration for how and when the app should request OTA JavaScript updates
*/
Expand Down Expand Up @@ -355,7 +353,7 @@ export interface IOS {
*/
googleMobileAdsAppId?: string;
/**
* A boolean indicating whether to initialize Google App Measurement and begin sending user-level event data to Google immediately when the app starts. The default in Expo (Client and in standalone apps) is `false`. [Sets the opposite of the given value to the following key in `Info.plist`.](https://developers.google.com/admob/ios/eu-consent#delay_app_measurement_optional)
* A boolean indicating whether to initialize Google App Measurement and begin sending user-level event data to Google immediately when the app starts. The default in Expo (Go and in standalone apps) is `false`. [Sets the opposite of the given value to the following key in `Info.plist`.](https://developers.google.com/admob/ios/eu-consent#delay_app_measurement_optional)
*/
googleMobileAdsAutoInit?: boolean;
/**
Expand Down Expand Up @@ -409,7 +407,7 @@ export interface IOS {
[k: string]: any;
};
/**
* An array that contains Associated Domains for the standalone app. See [Apple's docs for config](https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/enabling_universal_links).
* An array that contains Associated Domains for the standalone app. See [Apple's docs for config](https://developer.apple.com/documentation/safariservices/supporting_associated_domains).
*/
associatedDomains?: string[];
/**
Expand All @@ -429,7 +427,7 @@ export interface IOS {
*/
splash?: {
/**
* Local path to a XIB file as the loading screen. It overrides other loading screen options. Note: This will only be used in the standalone app (i.e., after you build the app). It will not be used in Expo Go.
* Local path to a XIB file as the loading screen. It overrides other loading screen options. Note: This will only be used in the standalone app (i.e., after you build the app). It will not be used in the Expo Go.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved
*/
xib?: string;
/**
Expand Down
Loading