Skip to content

Commit

Permalink
[expo-constants] Source env when creating app config (expo#29099)
Browse files Browse the repository at this point in the history
# Why

Let's say you have a **.env** with the following config:

```
HELLO_WORLD=123
```

Then you add that to your `extra` in **app.config.js**

```js
{
  ...
  "extra": {
    "helloWorld": process.env.HELLO_WORLD ?? 'ENV VAR NOT DEFINED'
  }
}
```

Then in your app you read the value:

```js
export default function App() {
  return (
    <View style={styles.container}>
      <Text>process.env.HELLO_WORLD: {Constants.expoConfig.extra.helloWorld}</Text>
    </View>
  );
}
```

Then you run a build in Expo Go, you will see the value 123. Similarly,
if you load it in a dev build, it show the same result. But if you run
`npx expo run:android --variant release`, then you will see "ENV VAR NOT
DEFINED". Similarly, if you committed that **.env** file to your app (or
loaded it in a pre-install hook) on EAS Build, then you will see "ENV
VAR NOT DEFINED".

This happens because we do not load `@expo/env` in our
**getAppConfig.js** script in `expo-constants`.

# How

Load the env before calling `getConfig(..)` from **getAppConfig.js**.

# Test Plan

- Applied patch with patch-package
- Ran `npx expo run:ios --configuration Release`, `npx expo run:android
--variant release`, `eas build -p all --profile preview` - verified in
each case that the env is loaded as expected.
  • Loading branch information
brentvatne authored May 29, 2024
1 parent 0cb8c0a commit f0075a4
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ packages/*/build/** -diff linguist-generated
packages/*/plugin/build/** -diff linguist-generated
packages/*/cli/build/** -diff linguist-generated
packages/*/utils/build/** -diff linguist-generated
packages/*/scripts/build/** -diff linguist-generated
packages/@*/*/build/** -diff linguist-generated

ios/vendored/** linguist-vendored
Expand Down
2 changes: 2 additions & 0 deletions packages/expo-constants/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### 🐛 Bug fixes

- Source env when creating app config. ([#29099](https://github.com/expo/expo/pull/29099) by [@brentvatne](https://github.com/brentvatne))

### 💡 Others

## 16.0.1 — 2024-04-23
Expand Down
3 changes: 2 additions & 1 deletion packages/expo-constants/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"preset": "expo-module-scripts"
},
"dependencies": {
"@expo/config": "~9.0.0"
"@expo/config": "~9.0.0",
"@expo/env": "~0.3.0"
},
"devDependencies": {
"expo-module-scripts": "^3.0.0"
Expand Down
51 changes: 51 additions & 0 deletions packages/expo-constants/scripts/__tests__/getAppConfig-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const { getConfig } = require('@expo/config');
const fs = require('fs');
const path = require('path');
const { load } = require('@expo/env');

jest.mock('fs');
jest.mock('path');
jest.mock('@expo/config');
jest.mock('@expo/env', () => ({
load: jest.fn(),
}));

const possibleProjectRoot = '/path/to/project';
const destinationDir = '/path/to/destination';
const mockExpConfig = { some: 'config' };

describe('getAppConfig', () => {
beforeAll(() => {
jest.resetAllMocks();
// Mock the arguments
process.argv[2] = possibleProjectRoot;
process.argv[3] = destinationDir;

fs.existsSync.mockImplementation((filePath) => {
if (filePath === path.join(possibleProjectRoot, 'package.json')) {
return true;
}
return false;
});

path.join.mockImplementation((...args) => args.join('/'));
path.resolve.mockImplementation((...args) => args.join('/'));
jest.spyOn(process, 'chdir').mockImplementation(() => {});
getConfig.mockReturnValue({ exp: mockExpConfig });

// Import the script (this runs the script)
require('../build/getAppConfig');
});

it('should call writeFileSync with the correct parameters', () => {
// Verify writeFileSync was called with the expected arguments
expect(fs.writeFileSync).toHaveBeenCalledWith(
path.join(destinationDir, 'app.config'),
JSON.stringify(mockExpConfig)
);
});

it('should load from @expo/env', () => {
expect(load).toHaveBeenCalledWith(possibleProjectRoot);
})
});
1 change: 1 addition & 0 deletions packages/expo-constants/scripts/build/getAppConfig.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions packages/expo-constants/scripts/build/getAppConfig.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 1 addition & 22 deletions packages/expo-constants/scripts/getAppConfig.js
Original file line number Diff line number Diff line change
@@ -1,22 +1 @@
const { getConfig } = require('@expo/config');
const fs = require('fs');
const path = require('path');

const possibleProjectRoot = process.argv[2];
const destinationDir = process.argv[3];

// Remove projectRoot validation when we no longer support React Native <= 62
let projectRoot;
if (fs.existsSync(path.join(possibleProjectRoot, 'package.json'))) {
projectRoot = possibleProjectRoot;
} else if (fs.existsSync(path.join(possibleProjectRoot, '..', 'package.json'))) {
projectRoot = path.resolve(possibleProjectRoot, '..');
}

process.chdir(projectRoot);

const { exp } = getConfig(projectRoot, {
isPublicConfig: true,
skipSDKVersionRequirement: true,
});
fs.writeFileSync(path.join(destinationDir, 'app.config'), JSON.stringify(exp));
require('./build/getAppConfig');
1 change: 1 addition & 0 deletions packages/expo-constants/scripts/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('expo-module-scripts/jest-preset-scripts');
28 changes: 28 additions & 0 deletions packages/expo-constants/scripts/src/getAppConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getConfig } from '@expo/config';
import fs from 'fs';
import path from 'path';

const possibleProjectRoot = process.argv[2];
const destinationDir = process.argv[3];

// TODO: Verify we can remove projectRoot validation, now that we no longer
// support React Native <= 62
let projectRoot;
if (fs.existsSync(path.join(possibleProjectRoot, 'package.json'))) {
projectRoot = possibleProjectRoot;
} else if (fs.existsSync(path.join(possibleProjectRoot, '..', 'package.json'))) {
projectRoot = path.resolve(possibleProjectRoot, '..');
} else {
throw new Error(
`Unable to locate project (no package.json found) at path: ${possibleProjectRoot}`
);
}

require('@expo/env').load(projectRoot);
process.chdir(projectRoot);

const { exp } = getConfig(projectRoot, {
isPublicConfig: true,
skipSDKVersionRequirement: true,
});
fs.writeFileSync(path.join(destinationDir, 'app.config'), JSON.stringify(exp));
9 changes: 9 additions & 0 deletions packages/expo-constants/scripts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "expo-module-scripts/tsconfig.plugin",
"compilerOptions": {
"outDir": "build",
"rootDir": "src"
},
"include": ["./src"],
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
}
2 changes: 2 additions & 0 deletions packages/expo-module-scripts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Add support for building scripts directory (similar to cli, utils, and plugins). ([#29099](https://github.com/expo/expo/pull/29099) by [@brentvatne](https://github.com/brentvatne))

### 🐛 Bug fixes

### 💡 Others
Expand Down
1 change: 1 addition & 0 deletions packages/expo-module-scripts/babel.config.scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./babel.config.cli');
20 changes: 13 additions & 7 deletions packages/expo-module-scripts/bin/expo-module-build
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ args=("$@")

# If the command is used like `yarn build plugin`, set the --build option to point to
# plugin/tsconfig.json
extra_module_build_types=("plugin" "cli" "utils")
extra_module_build_types=("plugin" "cli" "utils" "scripts")
for i in "${extra_module_build_types[@]}"
do
if [ "$1" == "$i" ]; then
# `--build` must be the first argument, so reset the array
args=()
args+=("--build")
args+=("$(pwd)/$i")
# Push the rest of the arguments minus the `plugin` arg
args+=("${@:2}")
# Check if tsconfig.json exists in the directory
if [ -f "$(pwd)/$i/tsconfig.json" ]; then
# `--build` must be the first argument, so reset the array
args=()
args+=("--build")
args+=("$(pwd)/$i")
# Push the rest of the arguments minus the `plugin` arg
args+=("${@:2}")
else
echo "tsconfig.json not found in $@, skipping build for $@/"
exit
fi
fi
done

Expand Down
2 changes: 1 addition & 1 deletion packages/expo-module-scripts/bin/expo-module-lint
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ script_dir="$(dirname "$0")"
args=()

# If the command is used like `yarn lint plugin` then set the target to `plugin/src`
extra_module_build_types=("plugin" "cli" "utils")
extra_module_build_types=("plugin" "cli" "utils" "scripts")
found_target=""
for i in "${extra_module_build_types[@]}"
do
Expand Down
2 changes: 1 addition & 1 deletion packages/expo-module-scripts/bin/expo-module-prepare
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ echo "Configuring module"
"$script_dir/expo-module-configure"
"$script_dir/expo-module-build"

extra_module_build_types=("plugin" "cli" "utils")
extra_module_build_types=("plugin" "cli" "utils" "scripts")
for i in "${extra_module_build_types[@]}"
do
if [[ -d "$i" ]]; then
Expand Down
2 changes: 1 addition & 1 deletion packages/expo-module-scripts/bin/expo-module-test
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ script_dir="$(dirname "$0")"
args=("$@")

# If the command is used like `yarn test plugin`, set the --rootDir option to the `plugin` directory
extra_module_build_types=("plugin" "cli" "utils")
extra_module_build_types=("plugin" "cli" "utils" "scripts")
for i in "${extra_module_build_types[@]}"
do
if [ "$1" == "$i" ]; then
Expand Down
2 changes: 2 additions & 0 deletions packages/expo-module-scripts/jest-preset-scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** @type {import('jest').Config} */
module.exports = require('./jest-preset-cli');

0 comments on commit f0075a4

Please sign in to comment.