@nx/react-native 19.2.0-canary.20240604-0594deb → 19.2.0-rc.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.
Files changed (26) hide show
  1. package/package.json +8 -8
  2. package/plugins/plugin.js +1 -1
  3. package/project.json +1 -1
  4. package/src/executors/build-android/build-android.impl.ts +0 -69
  5. package/src/executors/build-ios/build-ios.impl.ts +0 -77
  6. package/src/executors/bundle/bundle.impl.ts +0 -77
  7. package/src/executors/ensure-symlink/ensure-symlink.impl.ts +0 -22
  8. package/src/executors/pod-install/pod-install.impl.ts +0 -21
  9. package/src/executors/run-android/run-android.impl.ts +0 -94
  10. package/src/executors/run-ios/run-ios.impl.ts +0 -92
  11. package/src/executors/start/start.impl.ts +0 -111
  12. package/src/executors/storybook/storybook.impl.ts +0 -93
  13. package/src/executors/sync-deps/sync-deps.impl.ts +0 -140
  14. package/src/executors/upgrade/upgrade.impl.ts +0 -64
  15. package/src/generators/application/application.spec.ts +0 -260
  16. package/src/generators/application/lib/normalize-options.spec.ts +0 -211
  17. package/src/generators/component/component.spec.ts +0 -129
  18. package/src/generators/init/init.spec.ts +0 -40
  19. package/src/generators/library/library.spec.ts +0 -423
  20. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.spec.ts +0 -37
  21. package/src/migrations/update-18-0-0/add-web-configuration.spec.ts +0 -39
  22. package/src/migrations/update-18-0-0/remove-block-list.spec.ts +0 -68
  23. package/src/migrations/update-18-0-0/remove-symlink-target.spec.ts +0 -40
  24. package/src/utils/add-linting.spec.ts +0 -42
  25. package/src/utils/ensure-node-modules-symlink.spec.ts +0 -108
  26. package/src/utils/find-all-npm-dependencies.spec.ts +0 -103
@@ -1,93 +0,0 @@
1
- import { join, relative, resolve, dirname } from 'path';
2
- import { ExecutorContext, logger, readJsonFile } from '@nx/devkit';
3
- import { fileExists } from '@nx/workspace/src/utilities/fileutils';
4
- import * as chalk from 'chalk';
5
- import { sync as globSync } from 'glob';
6
-
7
- import { ReactNativeStorybookOptions } from './schema';
8
- import {
9
- displayNewlyAddedDepsMessage,
10
- syncDeps,
11
- } from '../sync-deps/sync-deps.impl';
12
- import { writeFileSync } from 'fs-extra';
13
- import { PackageJson } from 'nx/src/utils/package-json';
14
-
15
- /**
16
- * TODO (@xiongemi): remove this function in v20.
17
- * @deprecated Going to use the default react storybook target. Use @nx/react:storybook executor instead.
18
- */
19
- export default async function* reactNativeStorybookExecutor(
20
- options: ReactNativeStorybookOptions,
21
- context: ExecutorContext
22
- ): AsyncGenerator<{ success: boolean }> {
23
- const { syncDeps: isSyncDepsEnabled = true } = options;
24
-
25
- const projectRoot =
26
- context.projectsConfigurations.projects[context.projectName].root;
27
- logger.info(
28
- `${chalk.bold.cyan(
29
- 'info'
30
- )} To see your Storybook stories on the device, you should start your mobile app for the <platform> of your choice (typically ios or android).`
31
- );
32
-
33
- // add storybook addons to app's package.json
34
- const packageJsonPath = join(context.root, projectRoot, 'package.json');
35
- const workspacePackageJsonPath = join(context.root, 'package.json');
36
-
37
- const workspacePackageJson = readJsonFile<PackageJson>(
38
- workspacePackageJsonPath
39
- );
40
- const projectPackageJson = readJsonFile<PackageJson>(packageJsonPath);
41
-
42
- if (isSyncDepsEnabled && fileExists(packageJsonPath))
43
- displayNewlyAddedDepsMessage(
44
- context.projectName,
45
- await syncDeps(
46
- context.projectName,
47
- projectPackageJson,
48
- packageJsonPath,
49
- workspacePackageJson,
50
- context.projectGraph,
51
- [
52
- `@storybook/react-native`,
53
- '@storybook/addon-ondevice-actions',
54
- '@storybook/addon-ondevice-backgrounds',
55
- '@storybook/addon-ondevice-controls',
56
- '@storybook/addon-ondevice-notes',
57
- '@react-native-async-storage/async-storage',
58
- 'react-native-safe-area-context',
59
- ]
60
- )
61
- );
62
-
63
- runCliStorybook(context.root, options);
64
- yield { success: true };
65
- }
66
-
67
- export function runCliStorybook(
68
- workspaceRoot: string,
69
- options: ReactNativeStorybookOptions
70
- ) {
71
- const storiesFiles: string[] = options.searchDir.flatMap((dir) => {
72
- const storyFilePaths: string[] = globSync(join(dir, options.pattern));
73
-
74
- return storyFilePaths.map((storyFilePath) => {
75
- const loaderPath: string = resolve(dirname(options.outputFile));
76
- return relative(loaderPath, storyFilePath);
77
- });
78
- });
79
-
80
- if (storiesFiles.length === 0) {
81
- logger.warn(`${chalk.bold.yellow('warn')} No stories found.`);
82
- }
83
-
84
- const newContents = `// Auto-generated file created by nx
85
- // DO NOT EDIT.
86
- export function loadStories() {
87
- return [
88
- ${storiesFiles.map((story) => `require('${story}')`).join(',\n')}
89
- ];
90
- }`;
91
-
92
- writeFileSync(join(workspaceRoot, options.outputFile), newContents);
93
- }
@@ -1,140 +0,0 @@
1
- import { join } from 'path';
2
- import * as chalk from 'chalk';
3
- import {
4
- ExecutorContext,
5
- ProjectGraph,
6
- logger,
7
- readCachedProjectGraph,
8
- readJsonFile,
9
- writeJsonFile,
10
- } from '@nx/devkit';
11
-
12
- import { ReactNativeSyncDepsOptions } from './schema';
13
- import { findAllNpmDependencies } from '../../utils/find-all-npm-dependencies';
14
- import { PackageJson } from 'nx/src/utils/package-json';
15
-
16
- export interface ReactNativeSyncDepsOutput {
17
- success: boolean;
18
- }
19
-
20
- export default async function* syncDepsExecutor(
21
- options: ReactNativeSyncDepsOptions,
22
- context: ExecutorContext
23
- ): AsyncGenerator<ReactNativeSyncDepsOutput> {
24
- const projectRoot =
25
- context.projectsConfigurations.projects[context.projectName].root;
26
-
27
- const workspacePackageJsonPath = join(context.root, 'package.json');
28
- const projectPackageJsonPath = join(
29
- context.root,
30
- projectRoot,
31
- 'package.json'
32
- );
33
-
34
- const workspacePackageJson = readJsonFile(workspacePackageJsonPath);
35
- const projectPackageJson = readJsonFile(projectPackageJsonPath);
36
- displayNewlyAddedDepsMessage(
37
- context.projectName,
38
- await syncDeps(
39
- context.projectName,
40
- projectPackageJson,
41
- projectPackageJsonPath,
42
- workspacePackageJson,
43
- context.projectGraph,
44
- typeof options.include === 'string'
45
- ? options.include.split(',')
46
- : options.include,
47
- typeof options.exclude === 'string'
48
- ? options.exclude.split(',')
49
- : options.exclude,
50
- options.all
51
- )
52
- );
53
-
54
- yield { success: true };
55
- }
56
-
57
- export async function syncDeps(
58
- projectName: string,
59
- projectPackageJson: PackageJson,
60
- projectPackageJsonPath: string,
61
- workspacePackageJson: PackageJson,
62
- projectGraph: ProjectGraph = readCachedProjectGraph(),
63
- include: string[] = [],
64
- exclude: string[] = [],
65
- all: boolean = false
66
- ): Promise<string[]> {
67
- let npmDeps = all
68
- ? Object.keys(workspacePackageJson.dependencies || {})
69
- : findAllNpmDependencies(projectGraph, projectName);
70
- let npmDevdeps = all
71
- ? Object.keys(workspacePackageJson.devDependencies || {})
72
- : [];
73
-
74
- const newDeps = [];
75
- let updated = false;
76
-
77
- if (!projectPackageJson.dependencies) {
78
- projectPackageJson.dependencies = {};
79
- updated = true;
80
- }
81
-
82
- if (include && include.length) {
83
- npmDeps.push(...include);
84
- }
85
- if (exclude && exclude.length) {
86
- npmDeps = npmDeps.filter((dep) => !exclude.includes(dep));
87
- }
88
-
89
- if (!projectPackageJson.devDependencies) {
90
- projectPackageJson.devDependencies = {};
91
- }
92
- if (!projectPackageJson.dependencies) {
93
- projectPackageJson.dependencies = {};
94
- }
95
-
96
- npmDeps.forEach((dep) => {
97
- if (
98
- !projectPackageJson.dependencies[dep] &&
99
- !projectPackageJson.devDependencies[dep]
100
- ) {
101
- projectPackageJson.dependencies[dep] = '*';
102
- newDeps.push(dep);
103
- updated = true;
104
- }
105
- });
106
- npmDevdeps.forEach((dep) => {
107
- if (
108
- !projectPackageJson.dependencies[dep] &&
109
- !projectPackageJson.devDependencies[dep]
110
- ) {
111
- projectPackageJson.devDependencies[dep] = '*';
112
- newDeps.push(dep);
113
- updated = true;
114
- }
115
- });
116
-
117
- if (updated) {
118
- writeJsonFile(projectPackageJsonPath, projectPackageJson);
119
- }
120
-
121
- return newDeps;
122
- }
123
-
124
- export function displayNewlyAddedDepsMessage(
125
- projectName: string,
126
- deps: string[]
127
- ) {
128
- if (deps.length > 0) {
129
- logger.info(`${chalk.bold.cyan(
130
- 'info'
131
- )} Added entries to 'package.json' for '${projectName}' (for autolink):
132
- ${deps.map((d) => chalk.bold.cyan(`"${d}": "*"`)).join('\n ')}`);
133
- } else {
134
- logger.info(
135
- `${chalk.bold.cyan(
136
- 'info'
137
- )} Dependencies for '${projectName}' are up to date! No changes made.`
138
- );
139
- }
140
- }
@@ -1,64 +0,0 @@
1
- import { ExecutorContext } from '@nx/devkit';
2
- import { resolve as pathResolve } from 'path';
3
- import { ChildProcess, fork } from 'child_process';
4
-
5
- import { UpgradeExecutorSchema } from './schema';
6
-
7
- export interface ReactNativeUpgradeOutput {
8
- success: boolean;
9
- }
10
-
11
- /**
12
- * This executor is equivalent to `npx react-native upgrade`.
13
- * https://github.com/react-native-community/cli/blob/main/packages/cli/src/commands/upgrade/upgrade.ts
14
- */
15
- export default async function* upgradeExecutor(
16
- options: UpgradeExecutorSchema,
17
- context: ExecutorContext
18
- ): AsyncGenerator<ReactNativeUpgradeOutput> {
19
- const projectRoot =
20
- context.projectsConfigurations.projects[context.projectName].root;
21
-
22
- await runCliUpgrade(context.root, projectRoot);
23
- yield { success: true };
24
- }
25
-
26
- export function runCliUpgrade(
27
- workspaceRoot: string,
28
- projectRoot: string
29
- ): Promise<ChildProcess> {
30
- return new Promise<ChildProcess>((resolve, reject) => {
31
- const childProcess = fork(
32
- require.resolve('react-native/cli.js'),
33
- ['upgrade'],
34
- {
35
- stdio: 'inherit',
36
- cwd: pathResolve(workspaceRoot, projectRoot),
37
- env: process.env,
38
- }
39
- );
40
-
41
- /**
42
- * Ensure the child process is killed when the parent exits
43
- */
44
- const processExitListener = (signal?: number | NodeJS.Signals) => () => {
45
- childProcess.kill(signal);
46
- process.exit();
47
- };
48
- process.once('exit', (signal) => childProcess.kill(signal));
49
- process.once('SIGTERM', processExitListener);
50
- process.once('SIGINT', processExitListener);
51
- process.once('SIGQUIT', processExitListener);
52
-
53
- childProcess.on('error', (err) => {
54
- reject(err);
55
- });
56
- childProcess.on('exit', (code) => {
57
- if (code === 0) {
58
- resolve(childProcess);
59
- } else {
60
- reject(code);
61
- }
62
- });
63
- });
64
- }
@@ -1,260 +0,0 @@
1
- import 'nx/src/internal-testing-utils/mock-project-graph';
2
-
3
- import {
4
- Tree,
5
- getProjects,
6
- readJson,
7
- readProjectConfiguration,
8
- } from '@nx/devkit';
9
- import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
10
- import { Linter } from '@nx/eslint';
11
- import { reactNativeApplicationGenerator } from './application';
12
-
13
- describe('app', () => {
14
- let appTree: Tree;
15
-
16
- beforeEach(() => {
17
- appTree = createTreeWithEmptyWorkspace();
18
- appTree.write('.gitignore', '');
19
- });
20
-
21
- it('should update configuration', async () => {
22
- await reactNativeApplicationGenerator(appTree, {
23
- name: 'my-app',
24
- displayName: 'myApp',
25
- linter: Linter.EsLint,
26
- e2eTestRunner: 'none',
27
- install: false,
28
- projectNameAndRootFormat: 'as-provided',
29
- unitTestRunner: 'none',
30
- bundler: 'vite',
31
- });
32
- const projects = getProjects(appTree);
33
-
34
- expect(projects.get('my-app').root).toEqual('my-app');
35
- });
36
-
37
- it('should update nx.json', async () => {
38
- await reactNativeApplicationGenerator(appTree, {
39
- name: 'my-app',
40
- displayName: 'myApp',
41
- tags: 'one,two',
42
- linter: Linter.EsLint,
43
- e2eTestRunner: 'none',
44
- install: false,
45
- projectNameAndRootFormat: 'as-provided',
46
- unitTestRunner: 'none',
47
- bundler: 'vite',
48
- });
49
-
50
- const projectConfiguration = readProjectConfiguration(appTree, 'my-app');
51
- expect(projectConfiguration).toMatchObject({
52
- tags: ['one', 'two'],
53
- });
54
- });
55
-
56
- it('should generate files', async () => {
57
- await reactNativeApplicationGenerator(appTree, {
58
- name: 'my-app',
59
- displayName: 'myApp',
60
- linter: Linter.EsLint,
61
- e2eTestRunner: 'none',
62
- install: false,
63
- projectNameAndRootFormat: 'as-provided',
64
- unitTestRunner: 'jest',
65
- bundler: 'vite',
66
- });
67
- expect(appTree.exists('my-app/src/app/App.tsx')).toBeTruthy();
68
- expect(appTree.exists('my-app/src/main.tsx')).toBeTruthy();
69
-
70
- const tsconfig = readJson(appTree, 'my-app/tsconfig.json');
71
- expect(tsconfig.extends).toEqual('../tsconfig.base.json');
72
-
73
- expect(appTree.exists('my-app/.eslintrc.json')).toBe(true);
74
- expect(appTree.read('my-app/jest.config.ts', 'utf-8'))
75
- .toMatchInlineSnapshot(`
76
- "module.exports = {
77
- displayName: 'my-app',
78
- preset: 'react-native',
79
- resolver: '@nx/jest/plugins/resolver',
80
- moduleFileExtensions: ['ts', 'js', 'html', 'tsx', 'jsx'],
81
- setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
82
- moduleNameMapper: {
83
- '\\\\.svg$': '@nx/react-native/plugins/jest/svg-mock',
84
- },
85
- transform: {
86
- '^.+.(js|ts|tsx)$': [
87
- 'babel-jest',
88
- {
89
- configFile: __dirname + '/.babelrc.js',
90
- },
91
- ],
92
- '^.+.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$': require.resolve(
93
- 'react-native/jest/assetFileTransformer.js'
94
- ),
95
- },
96
- coverageDirectory: '../coverage/my-app',
97
- };
98
- "
99
- `);
100
- });
101
-
102
- it('should generate targets', async () => {
103
- await reactNativeApplicationGenerator(appTree, {
104
- name: 'my-app',
105
- displayName: 'myApp',
106
- linter: Linter.EsLint,
107
- e2eTestRunner: 'none',
108
- install: false,
109
- projectNameAndRootFormat: 'as-provided',
110
- unitTestRunner: 'jest',
111
- bundler: 'vite',
112
- });
113
-
114
- expect(appTree.exists('my-app/jest.config.ts')).toBeTruthy();
115
- });
116
-
117
- it('should extend from root tsconfig.json when no tsconfig.base.json', async () => {
118
- appTree.rename('tsconfig.base.json', 'tsconfig.json');
119
-
120
- await reactNativeApplicationGenerator(appTree, {
121
- name: 'my-app',
122
- displayName: 'myApp',
123
- linter: Linter.EsLint,
124
- e2eTestRunner: 'none',
125
- install: false,
126
- projectNameAndRootFormat: 'as-provided',
127
- unitTestRunner: 'none',
128
- bundler: 'vite',
129
- });
130
-
131
- const tsconfig = readJson(appTree, 'my-app/tsconfig.json');
132
- expect(tsconfig.extends).toEqual('../tsconfig.json');
133
- });
134
-
135
- describe('detox', () => {
136
- it('should create e2e app with directory', async () => {
137
- await reactNativeApplicationGenerator(appTree, {
138
- name: 'my-app',
139
- directory: 'my-dir',
140
- linter: Linter.EsLint,
141
- e2eTestRunner: 'detox',
142
- install: false,
143
- projectNameAndRootFormat: 'as-provided',
144
- bundler: 'vite',
145
- unitTestRunner: 'none',
146
- });
147
-
148
- const projects = getProjects(appTree);
149
- expect(projects.get('my-app').root).toEqual('my-dir');
150
-
151
- expect(appTree.exists('my-dir-e2e/.detoxrc.json')).toBeTruthy();
152
- const detoxrc = appTree.read('my-dir-e2e/.detoxrc.json', 'utf-8');
153
- // Strip trailing commas
154
- const detoxrcJson = JSON.parse(
155
- detoxrc.replace(/(?<=(true|false|null|["\d}\]])\s*),(?=\s*[}\]])/g, '')
156
- );
157
- expect(detoxrcJson.apps).toEqual({
158
- 'android.debug': {
159
- binaryPath:
160
- '../my-dir/android/app/build/outputs/apk/debug/app-debug.apk',
161
- build:
162
- 'cd ../my-dir/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
163
- type: 'android.apk',
164
- },
165
- 'android.release': {
166
- binaryPath:
167
- '../my-dir/android/app/build/outputs/apk/release/app-release.apk',
168
- build:
169
- 'cd ../my-dir/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release',
170
- type: 'android.apk',
171
- },
172
- 'ios.debug': {
173
- binaryPath:
174
- '../my-dir/ios/build/Build/Products/Debug-iphonesimulator/MyApp.app',
175
- build:
176
- "cd ../my-dir/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
177
- type: 'ios.app',
178
- },
179
- 'ios.release': {
180
- binaryPath:
181
- '../my-dir/ios/build/Build/Products/Release-iphonesimulator/MyApp.app',
182
- build:
183
- "cd ../my-dir/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
184
- type: 'ios.app',
185
- },
186
- });
187
- });
188
-
189
- it('should create e2e app without directory', async () => {
190
- await reactNativeApplicationGenerator(appTree, {
191
- name: 'my-app',
192
- linter: Linter.EsLint,
193
- e2eTestRunner: 'detox',
194
- install: false,
195
- projectNameAndRootFormat: 'as-provided',
196
- bundler: 'vite',
197
- unitTestRunner: 'none',
198
- });
199
-
200
- const projects = getProjects(appTree);
201
- expect(projects.get('my-app').root).toEqual('my-app');
202
-
203
- const detoxrc = appTree.read('my-app-e2e/.detoxrc.json', 'utf-8');
204
- // Strip trailing commas
205
- const detoxrcJson = JSON.parse(
206
- detoxrc.replace(/(?<=(true|false|null|["\d}\]])\s*),(?=\s*[}\]])/g, '')
207
- );
208
- expect(detoxrcJson.apps).toEqual({
209
- 'android.debug': {
210
- binaryPath:
211
- '../my-app/android/app/build/outputs/apk/debug/app-debug.apk',
212
- build:
213
- 'cd ../my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
214
- type: 'android.apk',
215
- },
216
- 'android.release': {
217
- binaryPath:
218
- '../my-app/android/app/build/outputs/apk/release/app-release.apk',
219
- build:
220
- 'cd ../my-app/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release',
221
- type: 'android.apk',
222
- },
223
- 'ios.debug': {
224
- binaryPath:
225
- '../my-app/ios/build/Build/Products/Debug-iphonesimulator/MyApp.app',
226
- build:
227
- "cd ../my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
228
- type: 'ios.app',
229
- },
230
- 'ios.release': {
231
- binaryPath:
232
- '../my-app/ios/build/Build/Products/Release-iphonesimulator/MyApp.app',
233
- build:
234
- "cd ../my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
235
- type: 'ios.app',
236
- },
237
- });
238
- });
239
- });
240
-
241
- describe('--skipPackageJson', () => {
242
- it('should not add or update dependencies when true', async () => {
243
- const packageJsonBefore = readJson(appTree, 'package.json');
244
-
245
- await reactNativeApplicationGenerator(appTree, {
246
- name: 'my-app',
247
- displayName: 'myApp',
248
- linter: Linter.EsLint,
249
- e2eTestRunner: 'none',
250
- install: false,
251
- skipPackageJson: true,
252
- projectNameAndRootFormat: 'as-provided',
253
- unitTestRunner: 'none',
254
- bundler: 'webpack',
255
- });
256
-
257
- expect(readJson(appTree, 'package.json')).toEqual(packageJsonBefore);
258
- });
259
- });
260
- });