@react-native/core-cli-utils 0.75.0-nightly-20240427-e2ad6696d → 0.75.0-nightly-20240429-b7de91666
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/package.json +5 -5
- package/src/index.flow.js +24 -0
- package/src/monorepo.js +23 -0
- package/src/private/android.js +128 -0
- package/src/private/apple.js +153 -0
- package/src/private/clean.js +203 -0
- package/src/private/utils.js +67 -0
- package/{dist/public/version.js.flow → src/public/version.js} +19 -12
- package/dist/index.d.ts +0 -12
- package/dist/index.flow.d.ts +0 -20
- package/dist/index.flow.js +0 -72
- package/dist/index.flow.js.flow +0 -24
- package/dist/index.js +0 -32
- package/dist/index.js.flow +0 -12
- package/dist/private/android.d.ts +0 -70
- package/dist/private/android.js +0 -102
- package/dist/private/android.js.flow +0 -85
- package/dist/private/apple.d.ts +0 -54
- package/dist/private/apple.js +0 -133
- package/dist/private/apple.js.flow +0 -68
- package/dist/private/clean.d.ts +0 -59
- package/dist/private/clean.js +0 -188
- package/dist/private/clean.js.flow +0 -77
- package/dist/private/types.d.ts +0 -16
- package/dist/private/types.js +0 -1
- package/dist/private/utils.d.ts +0 -28
- package/dist/private/utils.js +0 -64
- package/dist/private/utils.js.flow +0 -38
- package/dist/public/version.d.ts +0 -27
- package/dist/public/version.js +0 -60
- /package/{dist/private/types.js.flow → src/private/types.js} +0 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native/core-cli-utils",
|
|
3
|
-
"version": "0.75.0-nightly-
|
|
3
|
+
"version": "0.75.0-nightly-20240429-b7de91666",
|
|
4
4
|
"description": "React Native CLI library for Frameworks to build on",
|
|
5
|
-
"main": "./src/index.js",
|
|
5
|
+
"main": "./src/index.flow.js",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
"directory": "packages/core-cli-utils"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
|
-
".": "./dist/index.js",
|
|
13
|
+
".": "./dist/index.flow.js",
|
|
14
14
|
"./package.json": "./package.json",
|
|
15
15
|
"./version.js": "./dist/public/version.js"
|
|
16
16
|
},
|
|
17
|
-
"types": "./dist/index.d.ts",
|
|
17
|
+
"types": "./dist/index.flow.d.ts",
|
|
18
18
|
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/core-cli-utils#readme",
|
|
19
19
|
"keywords": [
|
|
20
20
|
"cli-utils",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"node": ">=18"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"
|
|
28
|
+
"src"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {},
|
|
31
31
|
"devDependencies": {}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// @babel/register doesn't like export {foo} from './bar'; statements,
|
|
13
|
+
// so we have to jump through hoops here.
|
|
14
|
+
import {tasks as _android} from './private/android.js';
|
|
15
|
+
import {tasks as _apple} from './private/apple.js';
|
|
16
|
+
import {tasks as _clean} from './private/clean.js';
|
|
17
|
+
import * as _version from './public/version.js';
|
|
18
|
+
|
|
19
|
+
export const android = _android;
|
|
20
|
+
export const apple = _apple;
|
|
21
|
+
export const clean = _clean;
|
|
22
|
+
export const version = _version;
|
|
23
|
+
|
|
24
|
+
export type {Task} from './private/types';
|
package/src/monorepo.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall react_native
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Should only used when called in the monorepo when we don't want to use the `yarn run build`
|
|
12
|
+
// step to transpile to project. When used as a vanilla npm package, it should be built and
|
|
13
|
+
// exported with `dist/index.flow.js` as main.
|
|
14
|
+
//
|
|
15
|
+
// The reason for this workaround is that flow-api-translator can't understand ESM and CJS style
|
|
16
|
+
// exports in the same file. Throw in a bit of Flow in the mix and it all goes to hell.
|
|
17
|
+
//
|
|
18
|
+
// See packages/helloworld/cli.js for an example of how to swap this out in the monorepo.
|
|
19
|
+
if (process.env.BUILD_EXCLUDE_BABEL_REGISTER == null) {
|
|
20
|
+
require('../../../scripts/build/babel-register').registerForMonorepo();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = require('./index.flow.js');
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {Task} from './types';
|
|
13
|
+
import type {ExecaPromise} from 'execa';
|
|
14
|
+
|
|
15
|
+
import {isWindows, task, toPascalCase} from './utils';
|
|
16
|
+
import execa from 'execa';
|
|
17
|
+
|
|
18
|
+
type AndroidBuildMode = 'debug' | 'release';
|
|
19
|
+
|
|
20
|
+
type AndroidBuild = {
|
|
21
|
+
sourceDir: string,
|
|
22
|
+
appName: string,
|
|
23
|
+
mode: AndroidBuildMode,
|
|
24
|
+
gradleArgs?: Array<string>,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function gradle(cwd: string, ...args: string[]): ExecaPromise {
|
|
28
|
+
const gradlew = isWindows ? 'gradlew.bat' : './gradlew';
|
|
29
|
+
return execa(gradlew, args, {
|
|
30
|
+
cwd,
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//
|
|
36
|
+
// Gradle Task wrappers
|
|
37
|
+
//
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Assembles an Android app using Gradle
|
|
41
|
+
*/
|
|
42
|
+
export const assemble = (
|
|
43
|
+
cwd: string,
|
|
44
|
+
appName: string,
|
|
45
|
+
mode: AndroidBuildMode,
|
|
46
|
+
...args: $ReadOnlyArray<string>
|
|
47
|
+
): ExecaPromise =>
|
|
48
|
+
gradle(cwd, `${appName}:assemble${toPascalCase(mode)}`, ...args);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Assembles and tests an Android app using Gradle
|
|
52
|
+
*/
|
|
53
|
+
export const build = (
|
|
54
|
+
cwd: string,
|
|
55
|
+
appName: string,
|
|
56
|
+
mode: AndroidBuildMode,
|
|
57
|
+
...args: $ReadOnlyArray<string>
|
|
58
|
+
): ExecaPromise =>
|
|
59
|
+
gradle(cwd, `${appName}:build${toPascalCase(mode)}`, ...args);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Installs an Android app using Gradle
|
|
63
|
+
*/
|
|
64
|
+
export const install = (
|
|
65
|
+
cwd: string,
|
|
66
|
+
appName: string,
|
|
67
|
+
mode: AndroidBuildMode,
|
|
68
|
+
...args: $ReadOnlyArray<string>
|
|
69
|
+
): ExecaPromise =>
|
|
70
|
+
gradle(cwd, `${appName}:install${toPascalCase(mode)}`, ...args);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Runs a custom Gradle task if your frameworks needs aren't handled by assemble, build or install.
|
|
74
|
+
*/
|
|
75
|
+
export const customTask = (
|
|
76
|
+
cwd: string,
|
|
77
|
+
customTaskName: string,
|
|
78
|
+
...args: $ReadOnlyArray<string>
|
|
79
|
+
): ExecaPromise => gradle(cwd, customTaskName, ...args);
|
|
80
|
+
|
|
81
|
+
const FIRST = 1;
|
|
82
|
+
|
|
83
|
+
//
|
|
84
|
+
// Android Tasks
|
|
85
|
+
//
|
|
86
|
+
type AndroidTasks = {
|
|
87
|
+
assemble: (
|
|
88
|
+
options: AndroidBuild,
|
|
89
|
+
...args: $ReadOnlyArray<string>
|
|
90
|
+
) => {run: Task<ExecaPromise>},
|
|
91
|
+
build: (
|
|
92
|
+
options: AndroidBuild,
|
|
93
|
+
...args: $ReadOnlyArray<string>
|
|
94
|
+
) => {run: Task<ExecaPromise>},
|
|
95
|
+
install: (
|
|
96
|
+
options: AndroidBuild,
|
|
97
|
+
...args: $ReadOnlyArray<string>
|
|
98
|
+
) => {run: Task<ExecaPromise>},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const tasks: AndroidTasks = {
|
|
102
|
+
assemble: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray<string>) => ({
|
|
103
|
+
run: task(FIRST, 'Assemble Android App', () =>
|
|
104
|
+
assemble(options.sourceDir, options.appName, options.mode, ...gradleArgs),
|
|
105
|
+
),
|
|
106
|
+
}),
|
|
107
|
+
build: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray<string>) => ({
|
|
108
|
+
run: task(FIRST, 'Assembles and tests Android App', () =>
|
|
109
|
+
build(options.sourceDir, options.appName, options.mode, ...gradleArgs),
|
|
110
|
+
),
|
|
111
|
+
}),
|
|
112
|
+
/**
|
|
113
|
+
* Useful extra gradle arguments:
|
|
114
|
+
*
|
|
115
|
+
* -PreactNativeDevServerPort=8081 sets the port for the installed app to point towards a Metro
|
|
116
|
+
* server on (for example) 8081.
|
|
117
|
+
*/
|
|
118
|
+
install: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray<string>) => ({
|
|
119
|
+
run: task(FIRST, 'Installs the assembled Android App', () =>
|
|
120
|
+
install(options.sourceDir, options.appName, options.mode, ...gradleArgs),
|
|
121
|
+
),
|
|
122
|
+
}),
|
|
123
|
+
|
|
124
|
+
// We are not supporting launching the app and setting up the tunnel for metro <-> app, this is
|
|
125
|
+
// a framework concern. For an example of how one could do this, please look at the community
|
|
126
|
+
// CLI's code:
|
|
127
|
+
// https://github.com/react-native-community/cli/blob/54d48a4e08a1aef334ae6168788e0157a666b4f5/packages/cli-platform-android/src/commands/runAndroid/index.ts#L272C1-L290C2
|
|
128
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {Task} from './types';
|
|
13
|
+
import type {ExecaPromise} from 'execa';
|
|
14
|
+
|
|
15
|
+
import {assertDependencies, isOnPath, task} from './utils';
|
|
16
|
+
import execa from 'execa';
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
|
|
20
|
+
type AppleBuildMode = 'Debug' | 'Release';
|
|
21
|
+
|
|
22
|
+
type AppleBuildOptions = {
|
|
23
|
+
isWorkspace: boolean,
|
|
24
|
+
name: string,
|
|
25
|
+
mode: AppleBuildMode,
|
|
26
|
+
scheme?: string,
|
|
27
|
+
destination?: string, // Device or Simulator or UUID
|
|
28
|
+
...AppleOptions,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type AppleBootstrapOption = {
|
|
32
|
+
// Enabled by default
|
|
33
|
+
newArchitecture: boolean,
|
|
34
|
+
...AppleOptions,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type AppleInstallApp = {
|
|
38
|
+
// Install the app on a simulator or device, typically this is the description from
|
|
39
|
+
// `xcrun simctl list devices`
|
|
40
|
+
device: string,
|
|
41
|
+
appPath: string,
|
|
42
|
+
bundleId: string,
|
|
43
|
+
...AppleOptions,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type AppleOptions = {
|
|
47
|
+
// The directory where the Xcode project is located
|
|
48
|
+
cwd: string,
|
|
49
|
+
// The environment variables to pass to the build command
|
|
50
|
+
env?: {[key: string]: string | void, ...},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const FIRST = 1,
|
|
54
|
+
SECOND = 2,
|
|
55
|
+
THIRD = 3;
|
|
56
|
+
|
|
57
|
+
/* eslint sort-keys: "off" */
|
|
58
|
+
export const tasks = {
|
|
59
|
+
// 1. Setup your environment for building the iOS apps
|
|
60
|
+
bootstrap: (
|
|
61
|
+
options: AppleBootstrapOption,
|
|
62
|
+
): {
|
|
63
|
+
validate: Task<void>,
|
|
64
|
+
installRubyGems: Task<ExecaPromise>,
|
|
65
|
+
installDependencies: Task<ExecaPromise>,
|
|
66
|
+
} => ({
|
|
67
|
+
validate: task(FIRST, 'Check Cocoapods and bundle are available', () => {
|
|
68
|
+
assertDependencies(
|
|
69
|
+
isOnPath('pod', 'CocoaPods'),
|
|
70
|
+
isOnPath('bundle', "Bundler to manage Ruby's gems"),
|
|
71
|
+
);
|
|
72
|
+
}),
|
|
73
|
+
installRubyGems: task(SECOND, 'Install Ruby Gems', () =>
|
|
74
|
+
execa('bundle', ['install'], {
|
|
75
|
+
cwd: options.cwd,
|
|
76
|
+
}),
|
|
77
|
+
),
|
|
78
|
+
installDependencies: task(THIRD, 'Install CocoaPods dependencies', () =>
|
|
79
|
+
execa('bundle', ['exec', 'pod', 'install'], {
|
|
80
|
+
cwd: options.cwd,
|
|
81
|
+
env: {RCT_NEW_ARCH_ENABLED: options.newArchitecture ? '1' : '0'},
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
}),
|
|
85
|
+
|
|
86
|
+
// 2. Build the iOS app using a setup environment
|
|
87
|
+
build: (
|
|
88
|
+
options: AppleBuildOptions,
|
|
89
|
+
...args: $ReadOnlyArray<string>
|
|
90
|
+
): {
|
|
91
|
+
validate: Task<void>,
|
|
92
|
+
hasPodsInstalled: Task<void>,
|
|
93
|
+
build: Task<ExecaPromise>,
|
|
94
|
+
} => ({
|
|
95
|
+
validate: task(
|
|
96
|
+
FIRST,
|
|
97
|
+
"Check you've run xcode-select --install for xcodebuild",
|
|
98
|
+
() => {
|
|
99
|
+
assertDependencies(isOnPath('xcodebuild', 'Xcode Commandline Tools'));
|
|
100
|
+
},
|
|
101
|
+
),
|
|
102
|
+
hasPodsInstalled: task(FIRST, 'Check Pods are installed', () => {
|
|
103
|
+
for (const file of ['Podfile.lock', 'Pods']) {
|
|
104
|
+
try {
|
|
105
|
+
fs.accessSync(
|
|
106
|
+
path.join(options.cwd, file),
|
|
107
|
+
/* eslint-disable-next-line no-bitwise */
|
|
108
|
+
fs.constants.F_OK | fs.constants.R_OK,
|
|
109
|
+
);
|
|
110
|
+
} catch {
|
|
111
|
+
throw new Error('Please run: yarn run boostrap ios');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}),
|
|
115
|
+
build: task(SECOND, 'build an app artifact', () => {
|
|
116
|
+
const _args = [
|
|
117
|
+
options.isWorkspace ? '-workspace' : '-project',
|
|
118
|
+
options.name,
|
|
119
|
+
];
|
|
120
|
+
if (options.scheme != null) {
|
|
121
|
+
_args.push('-scheme', options.scheme);
|
|
122
|
+
}
|
|
123
|
+
if (options.destination != null) {
|
|
124
|
+
_args.push('-destination', options.destination);
|
|
125
|
+
}
|
|
126
|
+
_args.push(...args);
|
|
127
|
+
return execa('xcodebuild', _args, {cwd: options.cwd, env: options.env});
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
|
|
131
|
+
// 3. Install the built app on a simulator or device
|
|
132
|
+
ios: {
|
|
133
|
+
install: (
|
|
134
|
+
options: AppleInstallApp,
|
|
135
|
+
): {validate: Task<void>, install: Task<ExecaPromise>} => ({
|
|
136
|
+
validate: task(
|
|
137
|
+
FIRST,
|
|
138
|
+
"Check you've run xcode-select --install for xcrun",
|
|
139
|
+
() => {
|
|
140
|
+
assertDependencies(
|
|
141
|
+
isOnPath('xcrun', 'An Xcode Commandline tool: xcrun'),
|
|
142
|
+
);
|
|
143
|
+
},
|
|
144
|
+
),
|
|
145
|
+
install: task(SECOND, 'Install the app on a simulator', () =>
|
|
146
|
+
execa('xcrun', ['simctl', 'install', options.device, options.appPath], {
|
|
147
|
+
cwd: options.cwd,
|
|
148
|
+
env: options.env,
|
|
149
|
+
}),
|
|
150
|
+
),
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {Task} from './types';
|
|
13
|
+
import type {ExecaPromise, Options as ExecaOptions} from 'execa';
|
|
14
|
+
|
|
15
|
+
import {assertDependencies, isMacOS, isOnPath, isWindows, task} from './utils';
|
|
16
|
+
import execa from 'execa';
|
|
17
|
+
import {existsSync, readdirSync, rm} from 'fs';
|
|
18
|
+
import os from 'os';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
|
|
21
|
+
const FIRST = 1,
|
|
22
|
+
SECOND = 2;
|
|
23
|
+
|
|
24
|
+
const rmrf = (pathname: string) => {
|
|
25
|
+
if (!existsSync(pathname)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
rm(pathname, {force: true, maxRetries: 3, recursive: true});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Removes the contents of a directory matching a given pattern, but keeps the directory.
|
|
33
|
+
* @private
|
|
34
|
+
*/
|
|
35
|
+
export function deleteDirectoryContents(
|
|
36
|
+
directory: string,
|
|
37
|
+
filePattern: RegExp,
|
|
38
|
+
): () => Promise<void> {
|
|
39
|
+
return async function deleteDirectoryContentsAction() {
|
|
40
|
+
const base = path.dirname(directory);
|
|
41
|
+
const files = readdirSync(base).filter((filename: string) =>
|
|
42
|
+
filePattern.test(filename),
|
|
43
|
+
);
|
|
44
|
+
for (const filename of files) {
|
|
45
|
+
rmrf(path.join(base, filename));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Removes a directory recursively.
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
export function deleteDirectory(directory: string): () => Promise<void> {
|
|
55
|
+
return async function cleanDirectoryAction() {
|
|
56
|
+
rmrf(directory);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Deletes the contents of the tmp directory matching a given pattern.
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
export function deleteTmpDirectoryContents(
|
|
65
|
+
filepattern: RegExp,
|
|
66
|
+
): () => Promise<void> {
|
|
67
|
+
return deleteDirectoryContents(os.tmpdir(), filepattern);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const platformGradlew = isWindows ? 'gradlew.bat' : 'gradlew';
|
|
71
|
+
|
|
72
|
+
type CocoaPodsClean = {
|
|
73
|
+
clean: Task<ExecaPromise>,
|
|
74
|
+
};
|
|
75
|
+
type AndroidClean = {
|
|
76
|
+
validate: Task<void>,
|
|
77
|
+
run: Task<ExecaPromise>,
|
|
78
|
+
};
|
|
79
|
+
type MetroClean = {
|
|
80
|
+
metro: Task<Promise<void>>,
|
|
81
|
+
haste: Task<Promise<void>>,
|
|
82
|
+
react_native: Task<Promise<void>>,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
type NpmClean = {
|
|
86
|
+
node_modules: Task<Promise<void>>,
|
|
87
|
+
verify_cache: Task<ExecaPromise>,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
type WatchmanClean = {
|
|
91
|
+
stop: Task<ExecaPromise>,
|
|
92
|
+
cache: Task<ExecaPromise>,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type YarnClean = {
|
|
96
|
+
clean: Task<ExecaPromise>,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
type CleanTasks = {
|
|
100
|
+
android: (andoirdSrcDir: ?string, opts?: ExecaOptions) => AndroidClean,
|
|
101
|
+
cocoapods: CocoaPodsClean,
|
|
102
|
+
metro: () => MetroClean,
|
|
103
|
+
npm: (projectRootDir: string) => NpmClean,
|
|
104
|
+
watchman: (projectRootDir: string) => WatchmanClean,
|
|
105
|
+
yarn: (projectRootDir: string) => YarnClean,
|
|
106
|
+
cocoapods?: (projectRootDir: string) => CocoaPodsClean,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// The tasks that cleanup various build artefacts.
|
|
110
|
+
/* eslint sort-keys: "off" */
|
|
111
|
+
export const tasks: CleanTasks = {
|
|
112
|
+
/**
|
|
113
|
+
* Cleans up the Android Gradle cache
|
|
114
|
+
*/
|
|
115
|
+
android: (androidSrcDir: ?string, opts?: ExecaOptions) => ({
|
|
116
|
+
validate: task(FIRST, 'Check gradlew is available', () => {
|
|
117
|
+
assertDependencies(isOnPath(platformGradlew, 'Gradle wrapper'));
|
|
118
|
+
}),
|
|
119
|
+
run: task(SECOND, '🧹 Clean Gradle cache', () => {
|
|
120
|
+
const gradlew = path.join(androidSrcDir ?? 'android', platformGradlew);
|
|
121
|
+
const script = path.basename(gradlew);
|
|
122
|
+
const cwd = path.dirname(gradlew);
|
|
123
|
+
return execa(isWindows ? script : './' + script, ['clean'], {
|
|
124
|
+
cwd,
|
|
125
|
+
...opts,
|
|
126
|
+
});
|
|
127
|
+
}),
|
|
128
|
+
}),
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Aggressively cleans up all Metro caches.
|
|
132
|
+
*/
|
|
133
|
+
metro: () => ({
|
|
134
|
+
metro: task(
|
|
135
|
+
FIRST,
|
|
136
|
+
'🧹 Clean Metro cache',
|
|
137
|
+
deleteTmpDirectoryContents(/^metro-.+/),
|
|
138
|
+
),
|
|
139
|
+
haste: task(
|
|
140
|
+
FIRST,
|
|
141
|
+
'🧹 Clean Haste cache',
|
|
142
|
+
deleteTmpDirectoryContents(/^haste-map-.+/),
|
|
143
|
+
),
|
|
144
|
+
react_native: task(
|
|
145
|
+
FIRST,
|
|
146
|
+
'🧹 Clean React Native cache',
|
|
147
|
+
deleteTmpDirectoryContents(/^react-.+/),
|
|
148
|
+
),
|
|
149
|
+
}),
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Cleans up the `node_modules` folder and optionally garbage collects the npm cache.
|
|
153
|
+
*/
|
|
154
|
+
npm: (projectRootDir: string) => ({
|
|
155
|
+
node_modules: task(
|
|
156
|
+
FIRST,
|
|
157
|
+
'🧹 Clean node_modules',
|
|
158
|
+
deleteDirectory(path.join(projectRootDir, 'node_modules')),
|
|
159
|
+
),
|
|
160
|
+
verify_cache: task(SECOND, '🔬 Verify npm cache', (opts?: ExecaOptions) =>
|
|
161
|
+
execa('npm', ['cache', 'verify'], {cwd: projectRootDir, ...opts}),
|
|
162
|
+
),
|
|
163
|
+
}),
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Stops Watchman and clears its cache
|
|
167
|
+
*/
|
|
168
|
+
watchman: (projectRootDir: string) => ({
|
|
169
|
+
stop: task(FIRST, '✋ Stop Watchman', (opts?: ExecaOptions) =>
|
|
170
|
+
execa(isWindows ? 'tskill' : 'killall', ['watchman'], {
|
|
171
|
+
cwd: projectRootDir,
|
|
172
|
+
...opts,
|
|
173
|
+
}),
|
|
174
|
+
),
|
|
175
|
+
cache: task(SECOND, '🧹 Delete Watchman cache', (opts?: ExecaOptions) =>
|
|
176
|
+
execa('watchman', ['watch-del-all'], {cwd: projectRootDir, ...opts}),
|
|
177
|
+
),
|
|
178
|
+
}),
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Cleans up the Yarn cache
|
|
182
|
+
*/
|
|
183
|
+
yarn: (projectRootDir: string) => ({
|
|
184
|
+
clean: task(FIRST, '🧹 Clean Yarn cache', (opts?: ExecaOptions) =>
|
|
185
|
+
execa('yarn', ['cache', 'clean'], {cwd: projectRootDir, ...opts}),
|
|
186
|
+
),
|
|
187
|
+
}),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
if (isMacOS) {
|
|
191
|
+
/**
|
|
192
|
+
* Cleans up the local and global CocoaPods cache
|
|
193
|
+
*/
|
|
194
|
+
tasks.cocoapods = (projectRootDir: string) => ({
|
|
195
|
+
// TODO: add project root
|
|
196
|
+
clean: task(FIRST, '🧹 Clean CocoaPods pod cache', (opts?: ExecaOptions) =>
|
|
197
|
+
execa('bundle', ['exec', 'pod', 'deintegrate'], {
|
|
198
|
+
cwd: projectRootDir,
|
|
199
|
+
...opts,
|
|
200
|
+
}),
|
|
201
|
+
),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {Task} from './types';
|
|
13
|
+
|
|
14
|
+
import execa from 'execa';
|
|
15
|
+
import os from 'os';
|
|
16
|
+
|
|
17
|
+
export function task<R>(
|
|
18
|
+
order: number,
|
|
19
|
+
label: string,
|
|
20
|
+
action: Task<R>['action'],
|
|
21
|
+
): Task<R> {
|
|
22
|
+
return {
|
|
23
|
+
action,
|
|
24
|
+
label,
|
|
25
|
+
order,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const isWindows = os.platform() === 'win32';
|
|
30
|
+
export const isMacOS = os.platform() === 'darwin';
|
|
31
|
+
|
|
32
|
+
export const toPascalCase = (label: string): string =>
|
|
33
|
+
label.length === 0 ? '' : label[0].toUpperCase() + label.slice(1);
|
|
34
|
+
|
|
35
|
+
type PathCheckResult = {
|
|
36
|
+
found: boolean,
|
|
37
|
+
dep: string,
|
|
38
|
+
description: string,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function isOnPath(dep: string, description: string): PathCheckResult {
|
|
42
|
+
const cmd = isWindows ? ['where', [dep]] : ['command', ['-v', dep]];
|
|
43
|
+
try {
|
|
44
|
+
const args = isWindows ? ['where', [dep]] : ['command', ['-v', dep]];
|
|
45
|
+
return {
|
|
46
|
+
dep,
|
|
47
|
+
description,
|
|
48
|
+
found: execa.sync(...cmd).exitCode === 0,
|
|
49
|
+
};
|
|
50
|
+
} catch {
|
|
51
|
+
return {
|
|
52
|
+
dep,
|
|
53
|
+
description,
|
|
54
|
+
found: false,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function assertDependencies(
|
|
60
|
+
...deps: $ReadOnlyArray<ReturnType<typeof isOnPath>>
|
|
61
|
+
) {
|
|
62
|
+
for (const {found, dep, description} of deps) {
|
|
63
|
+
if (!found) {
|
|
64
|
+
throw new Error(`"${dep}" not found, ${description}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -27,20 +27,27 @@
|
|
|
27
27
|
//
|
|
28
28
|
// For react-native@0.75.0 you have to have a version of XCode >= 12
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
ANDROID_NDK:
|
|
32
|
-
ANDROID_SDK:
|
|
30
|
+
export const android = {
|
|
31
|
+
ANDROID_NDK: '>= 23.x',
|
|
32
|
+
ANDROID_SDK: '>= 33.x',
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
export const apple = {
|
|
36
|
+
COCOAPODS: '>= 1.10.0',
|
|
37
|
+
XCODE: '>= 12.x',
|
|
38
|
+
};
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
BUN:
|
|
39
|
-
JAVA:
|
|
40
|
-
NODE_JS:
|
|
41
|
-
NPM:
|
|
42
|
-
RUBY:
|
|
43
|
-
YARN:
|
|
40
|
+
export const common = {
|
|
41
|
+
BUN: '>= 1.0.0',
|
|
42
|
+
JAVA: '>= 17 <= 20',
|
|
43
|
+
NODE_JS: '>= 18',
|
|
44
|
+
NPM: '>= 4.x',
|
|
45
|
+
RUBY: '>= 2.6.10',
|
|
46
|
+
YARN: '>= 1.10.x',
|
|
44
47
|
};
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
export const all = {
|
|
50
|
+
...apple,
|
|
51
|
+
...android,
|
|
52
|
+
...common,
|
|
53
|
+
};
|
package/dist/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @format
|
|
9
|
-
* @oncall react_native
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
export * from "./index.flow.js";
|