expo-module-scripts 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## Unpublished
4
+
5
+ ### 🛠 Breaking changes
6
+
7
+ ### 🎉 New features
8
+
9
+ ### 🐛 Bug fixes
10
+
11
+ ### 💡 Others
12
+
13
+ ## 2.1.0 — 2022-08-04
14
+
15
+ ### 🎉 New features
16
+
17
+ - Add `templates/scripts/source-login-scripts.sh` vendoring tool for node binary resolution in Xcode build phases scripts. ([#15336](https://github.com/expo/expo/pull/15336) by [@kudo](https://github.com/kudo))
18
+
19
+ ### 🐛 Bug fixes
20
+
21
+ - Fixed `source-login-scripts.sh` error when `extendedglob` is enabled in zsh config. ([#17024](https://github.com/expo/expo/pull/17024) by [@kudo](https://github.com/kudo))
22
+ - Fixed `expo-module prepare` error if target packages contain temporary kotlin build files. ([#17023](https://github.com/expo/expo/pull/17023) by [@kudo](https://github.com/kudo))
23
+ - Improved support of nvm sourcing in iOS shell scripts. ([#17109](https://github.com/expo/expo/pull/17109) by [@liamronancb](https://github.com/liamronancb))
24
+ - Fixed `source-login-scripts.sh` ~/zlogin typo. ([#17622](https://github.com/expo/expo/pull/17622) by [@vrgimael](https://github.com/vrgimael))
25
+ - Deprecated the unreliable `source-login-scripts.sh` and sourcing the Node.js binary path from `.xcode.env` and `.xcode.env.local`. ([#18330](https://github.com/expo/expo/pull/18330) by [@kudo](https://github.com/kudo))
26
+
27
+ ### 💡 Others
28
+
29
+ - Updated `@testing-library/react-hooks` to version `7.0.1`. ([#14552](https://github.com/expo/expo/pull/14552)) by [@Simek](https://github.com/Simek))
package/README.md CHANGED
@@ -6,11 +6,12 @@ This package contains a collection of common scripts for all Expo modules and th
6
6
 
7
7
  - [Getting Started](#getting-started)
8
8
  - [Setup](#setup)
9
+ - [🔌 Config Plugin](#-config-plugin)
9
10
  - [🤡 Jest](#-jest)
10
11
  - [📝 LICENSE](#-license)
11
12
  - [Side Effects](#side-effects)
12
13
  - [Entry Point and Types](#entry-point-and-types)
13
- - [🔗 NPM Linking](#-npm-linking)
14
+ - [🔗 npm Linking](#-npm-linking)
14
15
  - [⌘ Commands](#-commands)
15
16
  - [configure](#configure)
16
17
  - [typecheck](#typecheck)
@@ -21,7 +22,8 @@ This package contains a collection of common scripts for all Expo modules and th
21
22
  - [Lifecycle Commands](#lifecycle-commands)
22
23
  - [prepare (npm lifecycle)](#prepare--npm-lifecycle-)
23
24
  - [prepublishOnly (npm lifecycle)](#prepublishonly--npm-lifecycle-)
24
- - [Unified dependencies](#unified-dependencies)
25
+ - [Excluding Files from npm](#excluding-files-from-npm)
26
+ - [Unified Dependencies](#unified-dependencies)
25
27
 
26
28
  ## Getting Started
27
29
 
@@ -37,22 +39,23 @@ npm install --save-dev expo-module-scripts
37
39
 
38
40
  Add the following scripts to your `package.json` and run `yarn`
39
41
 
40
- ```json5
41
- {
42
+ ```json
43
+ {
42
44
  "scripts": {
43
- "build": "expo-module build",
44
- "clean": "expo-module clean",
45
- "test": "expo-module test",
46
- "prepare": "expo-module prepare",
47
- "prepublishOnly": "expo-module prepublishOnly",
48
- "expo-module": "expo-module"
49
- },
45
+ "build": "expo-module build",
46
+ "clean": "expo-module clean",
47
+ "test": "expo-module test",
48
+ "prepare": "expo-module prepare",
49
+ "prepublishOnly": "expo-module prepublishOnly",
50
+ "expo-module": "expo-module"
51
+ }
50
52
  }
51
53
  ```
52
54
 
53
55
  Running `yarn` will now run the `prepare` script, which generates any missing files:
54
- - [`.eslintrc.js`](./templates/.eslintrc.js) ([docs](https://eslint.org/docs/user-guide/configuring)) this extends [`eslint-config-universe`](https://github.com/expo/expo/tree/master/packages/eslint-config-universe).
55
- - Optionally you can customize Prettier too: [.prettierrc guide](https://github.com/expo/expo/tree/master/packages/eslint-config-universe#customizing-prettier).
56
+
57
+ - [`.eslintrc.js`](./templates/.eslintrc.js) ([docs](https://eslint.org/docs/user-guide/configuring)) this extends [`eslint-config-universe`](https://github.com/expo/expo/tree/main/packages/eslint-config-universe).
58
+ - Optionally you can customize Prettier too: [.prettierrc guide](https://github.com/expo/expo/tree/main/packages/eslint-config-universe#customizing-prettier).
56
59
  - [`.npmignore`](./templates/.npmignore) ([docs](https://docs.npmjs.com/misc/developers)) currently only ignores the `babel.config.js` in your module. You might also want to also add tests and docs.
57
60
  - Expo modules use `.npmignore` **instead of** the `files` field in the `package.json`.
58
61
  - (Pro Tip) Test which files get packaged by running `npm pack`. If you see files that aren't crucial to running the module, you should add them to `.npmignore`.
@@ -62,29 +65,104 @@ Running `yarn` will now run the `prepare` script, which generates any missing fi
62
65
  - Try and incorporate a table of contents (TOC).
63
66
  - [`tsconfig.json`](./templates/tsconfig.json) ([docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)) extends [`tsconfig.base.json`](./tsconfig.base.json) this is important for ensuring all Unimodules use the same version of TypeScript.
64
67
 
65
- You should also add the following fields to your `package.json`:
68
+ Besides, running `yarn prepare` script will also synchronize optional files from `expo-module-scripts` when the file is present and contains the `@generated` pattern:
69
+
70
+ - [`with-node.sh`](./templates/scripts/with-node.sh): An Xcode build phase script helper for Node.js binary resolution. It sources the project's **.xcode.env** and **.xcode.env.local** files, which may define an environment variable named `NODE_BINARY` to specify the file path of the Node.js binary to run.
71
+
72
+ ### 🔌 Config Plugin
73
+
74
+ To create a [config plugin](https://github.com/expo/expo-cli/blob/main/packages/config-plugins/README.md) that automatically configures your native code, you have two options:
75
+
76
+ 1. Create a `plugin` folder and write your plugin in TypeScript (recommended).
77
+ 2. Create an `app.plugin.js` file in the project root and write the plugin in pure Node.js-compliant JavaScript.
78
+
79
+ Config plugins must be transpiled for compatibility with Node.js (LTS). The features supported in Node.js are slightly different from those in Expo or React Native modules, which support ES6 import/export keywords and JSX, for example. This means we'll need two different `tsconfig.json` files and two different `src` (and `build`) folders — one for the code that will execute in an Expo or React Native app and the other for the plugin that executes in Node.js.
80
+
81
+ This can quickly become complex, so we've created a system for easily targeting the plugin folder.
82
+
83
+ #### Plugin setup
84
+
85
+ The following files are required for a TypeScript plugin:
86
+
87
+ ```
88
+ ╭── app.plugin.js ➡️ Entry file
89
+ ╰── plugin/ ➡️ All code related to the plugin
90
+ ├── __tests__/ ➡️ Optional: Folder for tests related to the plugin
91
+ ├── tsconfig.json ➡️ The TypeScript config for transpiling the plugin to JavaScript
92
+ ├── jest.config.js ➡️ Optional: The Jest preset
93
+ ╰── src/index.ts ➡️ The TypeScript entry point for your plugin
94
+ ```
95
+
96
+ Create an `app.plugin.js` (the entry point for a config plugin):
97
+
98
+ ```js
99
+ module.exports = require('./plugin/build');
100
+ ```
101
+
102
+ Create a `plugin/tsconfig.json` file. Notice that this uses `tsconfig.plugin` as the base config:
103
+
104
+ ```json
105
+ {
106
+ "extends": "expo-module-scripts/tsconfig.plugin",
107
+ "compilerOptions": {
108
+ "outDir": "build",
109
+ "rootDir": "src"
110
+ },
111
+ "include": ["./src"],
112
+ "exclude": ["**/__mocks__/*", "**/__tests__/*"]
113
+ }
114
+ ```
115
+
116
+ In your `plugin/src/index.ts` file, write your TypeScript config plugin:
117
+
118
+ ```ts
119
+ import { ConfigPlugin } from '@expo/config-plugins';
120
+
121
+ const withNewName: ConfigPlugin<{ name?: string }> = (config, { name = 'my-app' } = {}) => {
122
+ config.name = name;
123
+ return config;
124
+ };
125
+
126
+ export default withNewName;
127
+ ```
128
+
129
+ > 💡 Tip: Using named functions makes debugging easier with `EXPO_DEBUG=true`
130
+
131
+ Optionally, you can add `plugin/jest.config.js` to override the default project Jest preset.
132
+
133
+ ```ts
134
+ module.exports = require('expo-module-scripts/jest-preset-plugin');
135
+ ```
136
+
137
+ Use the following scripts to interact with the plugin:
138
+
139
+ - `yarn build plugin`: Build the plugin.
140
+ - `yarn clean plugin`: Delete the `plugin/build` folder.
141
+ - `yarn lint plugin`: Lint the `plugin/src` folder.
142
+ - `yarn test plugin`: Alias for `npx jest --rootDir ./plugin --config ./plugin/jest.config.js`, uses the project's Jest preset if `plugin/jest.config.js` doesn't exist.
143
+ - `yarn prepare`: Prepare the plugin and module for publishing.
66
144
 
67
145
  ### 🤡 Jest
68
146
 
69
- The Jest preset extends [`jest-expo`](https://github.com/expo/expo/tree/master/packages/jest-expo) or [`jest-expo-enzyme`](https://github.com/expo/expo/tree/master/packages/jest-expo-enzyme) and adds proper TypeScript support and type declarations to the presets.
147
+ The Jest preset extends [`jest-expo`](https://github.com/expo/expo/tree/main/packages/jest-expo) or [`jest-expo-enzyme`](https://github.com/expo/expo/tree/main/packages/jest-expo-enzyme) and adds proper TypeScript support and type declarations to the presets.
70
148
 
71
149
  **For unit testing API-based modules:**
72
150
 
73
- ```json5
151
+ ```json
74
152
  {
75
153
  "jest": {
76
- "preset": "expo-module-scripts/universal"
77
- },
154
+ "preset": "expo-module-scripts"
155
+ }
78
156
  }
79
157
  ```
80
158
 
81
159
  **For unit testing component-based modules:**
82
160
 
83
- ```json5
161
+ ```json
84
162
  {
85
163
  "jest": {
86
164
  "preset": "expo-module-scripts/enzyme"
87
- },
165
+ }
88
166
  }
89
167
  ```
90
168
 
@@ -92,9 +170,9 @@ The Jest preset extends [`jest-expo`](https://github.com/expo/expo/tree/master/p
92
170
 
93
171
  This makes it easier for other members of the community to work with your package. Expo usually has the **MIT** license.
94
172
 
95
- ```json5
173
+ ```json
96
174
  {
97
- "license": "MIT",
175
+ "license": "MIT"
98
176
  }
99
177
  ```
100
178
 
@@ -104,9 +182,9 @@ The [`@expo/webpack-config`](https://www.npmjs.com/package/@expo/webpack-config)
104
182
 
105
183
  [**Learn more about side effects**](https://webpack.js.org/guides/tree-shaking/)
106
184
 
107
- ```json5
185
+ ```json
108
186
  {
109
- "sideEffects": false,
187
+ "sideEffects": false
110
188
  }
111
189
  ```
112
190
 
@@ -118,18 +196,18 @@ We recommend you name the initial file after the module for easier searching. Be
118
196
 
119
197
  [**Learn more about "types" field**](https://webpack.js.org/guides/tree-shaking/)
120
198
 
121
- ```json5
199
+ ```json
122
200
  {
123
201
  "main": "build/Camera.js",
124
- "types": "build/Camera.d.ts",
202
+ "types": "build/Camera.d.ts"
125
203
  }
126
204
  ```
127
205
 
128
206
  > 💡 You technically don't need to define the types file if it's named the same as the `main` file but Expo modules always define it (which is what TypeScript recommends).
129
207
 
130
- ### 🔗 NPM Linking
208
+ ### 🔗 npm Linking
131
209
 
132
- Make your package accessible to NPM users by adding the following fields:
210
+ Make your package accessible to npm users by adding the following fields:
133
211
 
134
212
  Expo modules use the long form object when possible to better accommodate monorepos and hyperlinks:
135
213
 
@@ -137,7 +215,7 @@ Expo modules use the long form object when possible to better accommodate monore
137
215
  - [bugs docs](https://docs.npmjs.com/files/package.json#bugs)
138
216
  - [repository docs](https://docs.npmjs.com/files/package.json#repository)
139
217
 
140
- ```json5
218
+ ```json
141
219
  {
142
220
  "homepage": "https://github.com/YOU/expo-YOUR_PACKAGE#readme",
143
221
  "repository": {
@@ -146,7 +224,7 @@ Expo modules use the long form object when possible to better accommodate monore
146
224
  },
147
225
  "bugs": {
148
226
  "url": "https://github.com/YOU/expo-YOUR_PACKAGE/issues"
149
- },
227
+ }
150
228
  }
151
229
  ```
152
230
 
@@ -168,7 +246,7 @@ For scripts that need to run as part of the npm lifecycle, you'd invoke the comm
168
246
  {
169
247
  "scripts": {
170
248
  "prepare": "expo-module prepare",
171
- "prepublishOnly": "expo-module prepublishOnly",
249
+ "prepublishOnly": "expo-module prepublishOnly"
172
250
  }
173
251
  }
174
252
  ```
@@ -177,7 +255,7 @@ These are the commands:
177
255
 
178
256
  ### configure
179
257
 
180
- This generates common configuration files like `tsonfig.json` for the package. These auto-generated files are meant to be read-only and committed to Git.
258
+ This generates common configuration files like `tsconfig.json` for the package. These auto-generated files are meant to be read-only and committed to Git.
181
259
 
182
260
  ### typecheck
183
261
 
@@ -189,6 +267,10 @@ This compiles the source JS or TypeScript to "compiled" JS that Expo can load. W
189
267
 
190
268
  If we wished to switch to using just Babel with the TypeScript plugin, this package would let us change the implementation of the `build` command and apply it to all packages automatically.
191
269
 
270
+ #### build plugin
271
+
272
+ Running `build plugin` builds the plugin source code in `plugin/src`.
273
+
192
274
  ### test
193
275
 
194
276
  We run tests using Jest with ts-jest, which runs TypeScript and Babel. This setup type checks test files and mimics the `build` command's approach of running `tsc` followed by Babel.
@@ -199,10 +281,27 @@ If we were to use just Babel with the TypeScript plugin for the `build` command,
199
281
 
200
282
  This runs ESLint over the source JS and TypeScript files.
201
283
 
284
+ One of the rules enforced is restricting any imports from the `fbjs` library. As stated in that [library's readme](https://github.com/facebook/fbjs#purpose):
285
+
286
+ > If you are consuming the code here and you are not also a Facebook project, be prepared for a bad time.
287
+
288
+ Replacements for common `fbjs` uses-cases are listed below:
289
+
290
+ - `invariant`- replace with [`invariant`](https://www.npmjs.com/package/invariant)
291
+ - `ExecutionEnvironment`- replace with [`Platform` from `@unimodules/core`](https://github.com/expo/expo/blob/main/packages/%40unimodules/react-native-adapter/src/Platform.ts)
292
+
293
+ #### lint plugin
294
+
295
+ Running `lint plugin` will lints the plugin source code in `plugin/src`.
296
+
202
297
  ### clean
203
298
 
204
299
  This deletes the build directory.
205
300
 
301
+ #### clean plugin
302
+
303
+ Running `clean plugin` will delete the `plugin/build` directory.
304
+
206
305
  ## Lifecycle Commands
207
306
 
208
307
  These are commands to run as part of [the npm scripts lifecycle](https://docs.npmjs.com/misc/scripts).
@@ -215,6 +314,10 @@ Runs `clean` and `build`.
215
314
 
216
315
  Runs `npm-proofread`, which ensures a [dist-tag](https://docs.npmjs.com/cli/dist-tag) is specified when publishing a prerelease version.
217
316
 
218
- ## Unified dependencies
317
+ ## Excluding Files from npm
318
+
319
+ By convention, `expo-module-scripts` uses `.npmignore` to exclude all top-level hidden directories (directories starting with `.`) from being published to npm. This behavior is useful for files that need to be in the Git repository but not in the npm package.
320
+
321
+ ## Unified Dependencies
219
322
 
220
323
  This package depends on common development dependencies like Babel and Jest. The commands for compiling and testing JS need these dependencies, and the most important benefit is that all Expo module packages use the same version of Babel, Jest, their various plugins, and other development dependencies. This does remove the flexibility to customize the dependency versions for each module. We intentionally make this tradeoff to prioritize Expo as a whole over individual modules.
@@ -5,6 +5,18 @@ set -eo pipefail
5
5
  script_dir="$(dirname "$0")"
6
6
 
7
7
  args=("$@")
8
+
9
+ # If the command is used like `yarn build plugin`, set the --build option to point to
10
+ # plugin/tsconfig.json
11
+ if [ "$1" == "plugin" ]; then
12
+ # `--build` must be the first argument, so reset the array
13
+ args=()
14
+ args+=("--build")
15
+ args+=("$(pwd)/plugin")
16
+ # Push the rest of the arguments minus the `plugin` arg
17
+ args+=("${@:2}")
18
+ fi
19
+
8
20
  if [[ -t 1 && (-z "$CI" && -z "$EXPO_NONINTERACTIVE") ]]; then
9
21
  args+=("--watch")
10
22
  fi
@@ -7,4 +7,10 @@ if [[ ! -f package.json ]]; then
7
7
  exit 1
8
8
  fi
9
9
 
10
- rm -rf build
10
+ directory=$1
11
+ # Support `yarn clean plugin` to delete ./plugin/build/
12
+ if [[ -n $directory ]]; then
13
+ rm -rf "$directory/build"
14
+ else
15
+ rm -rf build
16
+ fi
@@ -6,11 +6,71 @@ script_dir="$(dirname "$0")"
6
6
 
7
7
  shopt -s dotglob
8
8
 
9
+ # an optional template file will be synced only if the target file is present in the file system,
10
+ # and its content contains the string `@generated`.
11
+ OPTIONAL_TEMPLATE_FILES=(
12
+ # add a relative file path from `templates/` for each new optional file
13
+ "scripts/with-node.sh"
14
+ )
15
+
16
+ # returns relative file paths inside a given directory without the leading "./".
17
+ # usage: get_relative_files "/path/to/dir"
18
+ get_relative_files() {
19
+ pushd $1 > /dev/null
20
+ local files=$(find . -type f | cut -c 3-)
21
+ popd > /dev/null
22
+ echo $files
23
+ }
24
+
25
+
26
+ # syncs the source file if the target file is missing or the existing file contains `@generated`.
27
+ # usage: sync_file_if_missing "/path/source_path" "/path/target_path"
28
+ sync_file_if_missing() {
29
+ local source=$1
30
+ local target=$2
31
+ # echo "sync_file_if_missing $source -> $target"
32
+ if [ ! -f "$target" ] || grep --quiet "@generated" "$target"; then
33
+ rsync --checksum "$source" "$target"
34
+ fi
35
+ }
36
+
37
+ # syncs the source file if the target file is present in the file system and its content contains `@generated`.
38
+ # usage: sync_file_if_present "/path/source_path" "/path/target_path"
39
+ sync_file_if_present() {
40
+ local source=$1
41
+ local target=$2
42
+ # echo "sync_file_if_present $source -> $target"
43
+ if [ -f "$target" ] && grep --quiet "@generated" "$target"; then
44
+ rsync --checksum "$source" "$target"
45
+ fi
46
+ }
47
+
48
+ # check if a file is listed in `OPTIONAL_TEMPLATE_FILES`.
49
+ # usage: if is_optional_file "path/to/file"; then ... fi
50
+ is_optional_file() {
51
+ local file=$1
52
+ for optional_file in "${OPTIONAL_TEMPLATE_FILES[@]}"; do
53
+ if [ "$file" = "$optional_file" ]; then
54
+ true
55
+ return
56
+ fi
57
+ done
58
+
59
+ false
60
+ return
61
+ }
62
+
63
+ #
64
+ # script main starts from here
65
+ #
66
+
9
67
  "$script_dir/expo-module-readme"
10
68
 
11
- for template_file in "$script_dir"/../templates/*; do
12
- output_file="$(basename "$template_file")"
13
- if [ ! -f "$output_file" ] || grep --quiet "@generated" "$output_file"; then
14
- rsync --checksum "$template_file" "$output_file"
69
+ template_files=$(get_relative_files "$script_dir/../templates")
70
+ for template_relative_file in $template_files; do
71
+ if is_optional_file "$template_relative_file"; then
72
+ sync_file_if_present "$script_dir/../templates/$template_relative_file" "$template_relative_file"
73
+ else
74
+ sync_file_if_missing "$script_dir/../templates/$template_relative_file" "$template_relative_file"
15
75
  fi
16
76
  done
@@ -4,4 +4,21 @@ set -eo pipefail
4
4
 
5
5
  script_dir="$(dirname "$0")"
6
6
 
7
- "$script_dir/expo-module-eslint" --ext .js,.jsx,.ts,.tsx,.d.ts "$@" src
7
+ args=()
8
+
9
+ # If the command is used like `yarn lint plugin` then set the target to `plugin/src`
10
+ if [ "$1" == "plugin" ]; then
11
+ # Push the rest of the arguments minus the `plugin` arg
12
+ args+=("${@:2}")
13
+ args+=("plugin/src")
14
+ if ! [[ -d plugin ]]; then
15
+ # Good DX cuz Expo
16
+ printf "\n\033[1;33mThe \`plugin/src\` folder does not exist in this project; please create it and try again.\033[0m\n\n"
17
+ exit 0
18
+ fi
19
+ else
20
+ args+=("$@")
21
+ args+=("src")
22
+ fi
23
+
24
+ "$script_dir/expo-module-eslint" "${args[@]}"
@@ -6,6 +6,13 @@ script_dir="$(dirname "$0")"
6
6
 
7
7
  export EXPO_NONINTERACTIVE=1
8
8
 
9
+ echo "Configuring module"
9
10
  "$script_dir/expo-module-clean"
10
11
  "$script_dir/expo-module-configure"
11
12
  "$script_dir/expo-module-build"
13
+
14
+ if [[ -d plugin ]]; then
15
+ echo "Configuring plugin"
16
+ "$script_dir/expo-module-clean" plugin
17
+ "$script_dir/expo-module-build" plugin
18
+ fi
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- const path = require('path');
5
4
  const fs = require('fs');
6
5
  const glob = require('glob');
6
+ const path = require('path');
7
7
 
8
8
  function replaceAll(current, replacement, content) {
9
- let regexp = new RegExp(escapeRegExp('${' + current + '}'), 'g');
9
+ const regexp = new RegExp(escapeRegExp('${' + current + '}'), 'g');
10
10
  return content.replace(regexp, replacement);
11
11
  }
12
12
 
@@ -15,53 +15,53 @@ function escapeRegExp(string) {
15
15
  }
16
16
 
17
17
  function removeUnapplicableSections(name, content) {
18
- let opener = `<!--- remove for ${name} --->`;
19
- let closer = `<!--- end remove for ${name} --->`;
18
+ const opener = `<!--- remove for ${name} --->`;
19
+ const closer = `<!--- end remove for ${name} --->`;
20
20
  let nextContent = content;
21
21
 
22
22
  while (nextContent.includes(opener)) {
23
- let openIndex = nextContent.indexOf(opener);
23
+ const openIndex = nextContent.indexOf(opener);
24
24
  let closeIndex = nextContent.indexOf(closer);
25
25
  if (!closeIndex) {
26
26
  console.warn(`Can't find section closer for ${name}`);
27
27
  closeIndex = openIndex + opener.length;
28
28
  }
29
- let section = nextContent.substring(openIndex, closeIndex + closer.length);
29
+ const section = nextContent.substring(openIndex, closeIndex + closer.length);
30
30
  nextContent = nextContent.replace(section, '');
31
31
  }
32
32
  return nextContent;
33
33
  }
34
34
 
35
35
  function removeOptionals(content) {
36
- let regexp = new RegExp(escapeRegExp('<!---') + '.*' + escapeRegExp('--->') + '\n', 'g');
36
+ const regexp = new RegExp(escapeRegExp('<!---') + '.*' + escapeRegExp('--->') + '\n', 'g');
37
37
  return content.replace(regexp, '');
38
38
  }
39
39
 
40
- const DEFAULT_HOMEPAGE = 'https://docs.expo.io/versions/latest/';
40
+ const DEFAULT_HOMEPAGE = 'https://docs.expo.dev/versions/latest/';
41
41
 
42
42
  function generateREADME() {
43
- let template = path.join(__dirname, '..', 'templates', 'README.md');
43
+ const template = path.join(__dirname, '..', 'templates', 'README.md');
44
44
  let readme = fs.readFileSync(template, 'utf8');
45
- let pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
46
- let packageName = pkg.name;
47
- let homepage = pkg.homepage || DEFAULT_HOMEPAGE;
48
- let description = pkg.description || 'Put a description of your Unimodule here';
45
+ const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
46
+ const packageName = pkg.name;
47
+ const homepage = pkg.homepage || DEFAULT_HOMEPAGE;
48
+ const description = pkg.description || 'Put a description of your Unimodule here';
49
49
 
50
50
  // This isn't really accurate, but these all behave the same as far as READMEs go
51
- let isInterface = packageName.endsWith('-interface') || packageName.endsWith('-provider');
51
+ const isInterface = packageName.endsWith('-interface') || packageName.endsWith('-provider');
52
52
 
53
- let isAndroid = fs.existsSync(path.join(process.cwd(), 'android'));
54
- let isIOS = fs.existsSync(path.join(process.cwd(), 'ios'));
53
+ const isAndroid = fs.existsSync(path.join(process.cwd(), 'android'));
54
+ const isIOS = fs.existsSync(path.join(process.cwd(), 'ios'));
55
55
 
56
56
  // Search in docs/versions/unversioned/sdk/*.md - can't find it? Ask what it should be and initialize for them
57
57
  readme = replaceAll('packageName', packageName, readme);
58
58
  readme = replaceAll('description', description, readme);
59
59
 
60
60
  if (isIOS) {
61
- let podspecs = glob.sync('ios/**/*.podspec');
62
- let podspecPath = podspecs[0];
63
- let podName = (() => {
64
- let parts = podspecPath.split('/');
61
+ const podspecs = glob.sync('{ios/**/,}*.podspec');
62
+ const podspecPath = podspecs[0];
63
+ const podName = (() => {
64
+ const parts = podspecPath.split('/');
65
65
  return parts[parts.length - 1].replace('.podspec', '');
66
66
  })();
67
67
 
@@ -81,7 +81,7 @@ function generateREADME() {
81
81
  );
82
82
  } else {
83
83
  docName = (() => {
84
- let parts = homepage.split('/');
84
+ const parts = homepage.split('/');
85
85
  // Handle both with and without trailing slash
86
86
  let name = parts[parts.length - 1];
87
87
  if (name === '') {
@@ -92,7 +92,7 @@ function generateREADME() {
92
92
  }
93
93
  readme = replaceAll('docName', docName, readme);
94
94
  if (isAndroid) {
95
- let androidPackages = glob.sync('android/**/*Package.java');
95
+ const androidPackages = glob.sync('android/src/**/*Package.{java,kt}');
96
96
  let androidPackage;
97
97
  let androidPackagePath = 'expo.modules.yourModule.YourPackage';
98
98
  let androidPackageName = 'YourPackage';
@@ -115,7 +115,7 @@ function generateREADME() {
115
115
  .replace(/\//g, '.')
116
116
  .replace('.java', '');
117
117
  androidPackageName = (() => {
118
- let parts = androidPackagePath.split('.');
118
+ const parts = androidPackagePath.split('.');
119
119
  return parts[parts.length - 1];
120
120
  })();
121
121
 
@@ -133,8 +133,8 @@ function generateREADME() {
133
133
  return removeOptionals(readme);
134
134
  }
135
135
 
136
- let readme = generateREADME();
137
- let readmePath = path.join(process.cwd(), 'README.md');
136
+ const readme = generateREADME();
137
+ const readmePath = path.join(process.cwd(), 'README.md');
138
138
  if (fs.existsSync(readmePath)) {
139
139
  console.log('expo-module-scripts: README.md exists, not updating');
140
140
  } else {
@@ -5,6 +5,22 @@ set -eo pipefail
5
5
  script_dir="$(dirname "$0")"
6
6
 
7
7
  args=("$@")
8
+
9
+ # If the command is used like `yarn test plugin`, set the --rootDir option to the `plugin` directory
10
+ if [ "$1" == "plugin" ]; then
11
+ args=()
12
+ args+=("--rootDir")
13
+ args+=("plugin")
14
+
15
+ if [[ -f plugin/jest.config.js ]]; then
16
+ args+=("--config")
17
+ args+=("plugin/jest.config.js")
18
+ fi
19
+
20
+ # Push the rest of the arguments minus the `plugin` arg
21
+ args+=("${@:2}")
22
+ fi
23
+
8
24
  if [[ -t 1 && (-z "$CI" && -z "$EXPO_NONINTERACTIVE") ]]; then
9
25
  args+=("--watch")
10
26
  fi
package/eslintrc.base.js CHANGED
@@ -8,4 +8,13 @@ module.exports = {
8
8
  globals: { __DEV__: true },
9
9
  },
10
10
  ],
11
+ rules: {
12
+ 'no-restricted-imports': [
13
+ 'warn',
14
+ {
15
+ // fbjs is a Facebook-internal package not intended to be a public API
16
+ patterns: ['fbjs/*', 'fbjs'],
17
+ },
18
+ ],
19
+ },
11
20
  };
@@ -0,0 +1,10 @@
1
+ const nodePreset = {
2
+ testEnvironment: 'node',
3
+ testRegex: '/__tests__/.*(test|spec)\\.[jt]sx?$',
4
+ transform: {
5
+ '^.+\\.[jt]sx?$': ['babel-jest', { configFile: require.resolve('./babel.config.base.js') }],
6
+ },
7
+ watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
8
+ };
9
+
10
+ module.exports = nodePreset;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-module-scripts",
3
- "version": "1.2.0",
3
+ "version": "2.1.0",
4
4
  "description": "A private package for various tasks for Expo module packages like compiling and testing",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -24,20 +24,23 @@
24
24
  "bugs": {
25
25
  "url": "https://github.com/expo/expo/issues"
26
26
  },
27
- "homepage": "https://github.com/expo/expo/tree/master/packages/expo-module-scripts#readme",
27
+ "homepage": "https://github.com/expo/expo/tree/main/packages/expo-module-scripts#readme",
28
28
  "dependencies": {
29
29
  "@babel/cli": "^7.1.2",
30
30
  "@expo/npm-proofread": "^1.0.1",
31
- "@types/jest": "^24.0.11",
32
- "babel-preset-expo": "~8.0.0",
31
+ "@testing-library/react-hooks": "^7.0.1",
32
+ "@tsconfig/node12": "^1.0.9",
33
+ "@types/jest": "^26.0.24",
34
+ "babel-preset-expo": "~9.2.0",
33
35
  "commander": "^2.19.0",
34
- "eslint-config-universe": "^2.1.0",
35
- "find-yarn-workspace-root": "^1.2.1",
36
- "glob": "^7.1.3",
37
- "jest-expo": "~36.0.1",
38
- "jest-expo-enzyme": "^0.0.1",
39
- "ts-jest": "~24.0.2",
40
- "typescript": "^3.7.2"
36
+ "eslint-config-universe": "^11.0.0",
37
+ "find-yarn-workspace-root": "^2.0.0",
38
+ "glob": "^7.1.7",
39
+ "jest-expo": "~46.0.0",
40
+ "jest-expo-enzyme": "^1.2.3",
41
+ "jest-watch-typeahead": "0.6.4",
42
+ "ts-jest": "~26.3.0",
43
+ "typescript": "^4.3.5"
41
44
  },
42
- "gitHead": "4e13b3cb88d9205f14bee7764038ab2dd9ef1fbd"
45
+ "gitHead": "8074a07eb9b07884f66c88cd7001376a9c28ca96"
43
46
  }
@@ -5,17 +5,17 @@ ${description}
5
5
 
6
6
  # API documentation
7
7
 
8
- - [Documentation for the master branch](https://github.com/expo/expo/blob/master/docs/pages/versions/unversioned/sdk/${docName}.md)
9
- - [Documentation for the latest stable release](https://docs.expo.io/versions/latest/sdk/${docName}/)
8
+ - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/${docName}.md)
9
+ - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/${docName}/)
10
10
 
11
11
  <!--- end remove for interfaces --->
12
12
  # Installation in managed Expo projects
13
13
 
14
- For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
14
+ For [managed](https://docs.expo.dev/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
15
15
 
16
16
  # Installation in bare React Native projects
17
17
 
18
- For bare React Native projects, you must ensure that you have [installed and configured the `react-native-unimodules` package](https://github.com/unimodules/react-native-unimodules) before continuing.
18
+ For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.
19
19
 
20
20
  ### Add the package to your npm dependencies
21
21
 
@@ -26,7 +26,7 @@ npm install ${packageName}
26
26
  <!--- remove for no-ios --->
27
27
  ### Configure for iOS
28
28
 
29
- Run `pod install` in the ios directory after installing the npm package.
29
+ Run `npx pod-install` after installing the npm package.
30
30
 
31
31
  <!--- end remove for no-ios --->
32
32
 
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ # Copyright 2018-present 650 Industries. All rights reserved.
4
+ #
5
+ # @generated by expo-module-scripts
6
+ #
7
+ # USAGE:
8
+ # ./with-node.sh command
9
+
10
+ CURR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
11
+
12
+ # Start with a default
13
+ NODE_BINARY=$(command -v node)
14
+ export NODE_BINARY
15
+
16
+ # Override the default with the global environment
17
+ ENV_PATH="$PODS_ROOT/../.xcode.env"
18
+ if [[ -f "$ENV_PATH" ]]; then
19
+ source "$ENV_PATH"
20
+ fi
21
+
22
+ # Override the global with the local environment
23
+ LOCAL_ENV_PATH="${ENV_PATH}.local"
24
+ if [[ -f "$LOCAL_ENV_PATH" ]]; then
25
+ source "$LOCAL_ENV_PATH"
26
+ fi
27
+
28
+ if [[ -n "$NODE_BINARY" && -x "$NODE_BINARY" ]]; then
29
+ echo "Node found at: ${NODE_BINARY}"
30
+ else
31
+ cat >&2 << EOF
32
+ [ERROR] Could not find "node" while running an Xcode build script. You need to specify the path to your Node.js executable by defining an environment variable named NODE_BINARY in your project's .xcode.env or .xcode.env.local file. You can set this up quickly by running:
33
+
34
+ echo "export NODE_BINARY=\$(command -v node)" >> .xcode.env
35
+
36
+ in the ios folder of your project.
37
+ EOF
38
+ exit 1
39
+ fi
40
+
41
+ # Execute argument, if present
42
+ if [[ "$#" -gt 0 ]]; then
43
+ "$NODE_BINARY" $@
44
+ fi
@@ -5,5 +5,5 @@
5
5
  "outDir": "./build"
6
6
  },
7
7
  "include": ["./src"],
8
- "exclude": ["**/__mocks__/*", "**/__tests__/*"]
8
+ "exclude": ["**/__mocks__/*", "**/__tests__/*", "**/__stories__/*"]
9
9
  }
@@ -2,10 +2,9 @@
2
2
  "compilerOptions": {
3
3
  "target": "esnext",
4
4
  "lib": ["dom", "esnext"],
5
- "jsx": "react-native",
5
+ "jsx": "react",
6
6
  "moduleResolution": "node",
7
7
  "esModuleInterop": true,
8
- "allowSyntheticDefaultImports": true,
9
8
  "types": ["jest", "jest-require"],
10
9
  "typeRoots": [
11
10
  "./ts-declarations",
@@ -13,6 +12,7 @@
13
12
  ],
14
13
  "sourceMap": true,
15
14
  "declaration": true,
15
+ "declarationMap": true,
16
16
  "inlineSources": true,
17
17
  "strictNullChecks": true,
18
18
  "strictPropertyInitialization": true,
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@tsconfig/node12/tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true
5
+ }
6
+ }