fix(react-native): add all flag to sync-deps (#21821)
This commit is contained in:
parent
27cf3082da
commit
0f0074c91f
@ -22,6 +22,11 @@
|
|||||||
"items": { "type": "string" },
|
"items": { "type": "string" },
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "An array of npm packages to exclude."
|
"description": "An array of npm packages to exclude."
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Copy all dependencies and devDependencies from the workspace root package.json.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"presets": []
|
"presets": []
|
||||||
|
|||||||
@ -22,6 +22,11 @@
|
|||||||
"items": { "type": "string" },
|
"items": { "type": "string" },
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "An array of npm packages to exclude."
|
"description": "An array of npm packages to exclude."
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Copy all dependencies and devDependencies from the workspace root package.json.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"presets": []
|
"presets": []
|
||||||
|
|||||||
@ -215,18 +215,34 @@ describe('@nx/react-native (legacy)', () => {
|
|||||||
return `import AsyncStorage from '@react-native-async-storage/async-storage';${content}`;
|
return `import AsyncStorage from '@react-native-async-storage/async-storage';${content}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runCLIAsync(`sync-deps ${appName}`);
|
||||||
|
let result = readJson(join('apps', appName, 'package.json'));
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
dependencies: {
|
||||||
|
'@react-native-async-storage/async-storage': '*',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await runCLIAsync(
|
await runCLIAsync(
|
||||||
`sync-deps ${appName} --include=react-native-image-picker`
|
`sync-deps ${appName} --include=react-native-image-picker`
|
||||||
);
|
);
|
||||||
|
result = readJson(join('apps', appName, 'package.json'));
|
||||||
const result = readJson(join('apps', appName, 'package.json'));
|
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
dependencies: {
|
dependencies: {
|
||||||
|
'@react-native-async-storage/async-storage': '*',
|
||||||
|
'react-native-image-picker': '*',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await runCLIAsync(`sync-deps ${appName} --all`);
|
||||||
|
result = readJson(join('apps', appName, 'package.json'));
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
dependencies: {
|
||||||
|
'@react-native-async-storage/async-storage': '*',
|
||||||
'react-native-image-picker': '*',
|
'react-native-image-picker': '*',
|
||||||
'react-native': '*',
|
|
||||||
},
|
},
|
||||||
devDependencies: {
|
devDependencies: {
|
||||||
'@react-native-async-storage/async-storage': '*',
|
'@nx/react-native': '*',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
export interface ExpoSyncDepsOptions {
|
export interface ExpoSyncDepsOptions {
|
||||||
include: string[] | string; // default is an empty array []
|
include: string[] | string; // default is an empty array []
|
||||||
exclude: string[] | string; // default is an empty array []
|
exclude: string[] | string; // default is an empty array []
|
||||||
|
all: boolean; // default is false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,11 @@
|
|||||||
},
|
},
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "An array of npm packages to exclude."
|
"description": "An array of npm packages to exclude."
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Copy all dependencies and devDependencies from the workspace root package.json.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,16 @@ import { join } from 'path';
|
|||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import {
|
import {
|
||||||
ExecutorContext,
|
ExecutorContext,
|
||||||
|
ProjectGraph,
|
||||||
logger,
|
logger,
|
||||||
|
readCachedProjectGraph,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
|
||||||
import { ExpoSyncDepsOptions } from './schema';
|
import { ExpoSyncDepsOptions } from './schema';
|
||||||
|
import { findAllNpmDependencies } from '../../utils/find-all-npm-dependencies';
|
||||||
|
import { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export interface ReactNativeSyncDepsOutput {
|
export interface ReactNativeSyncDepsOutput {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
@ -19,17 +23,31 @@ export default async function* syncDepsExecutor(
|
|||||||
): AsyncGenerator<ReactNativeSyncDepsOutput> {
|
): AsyncGenerator<ReactNativeSyncDepsOutput> {
|
||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
|
|
||||||
|
const workspacePackageJsonPath = join(context.root, 'package.json');
|
||||||
|
const projectPackageJsonPath = join(
|
||||||
|
context.root,
|
||||||
|
projectRoot,
|
||||||
|
'package.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
const workspacePackageJson = readJsonFile(workspacePackageJsonPath);
|
||||||
|
const projectPackageJson = readJsonFile(projectPackageJsonPath);
|
||||||
displayNewlyAddedDepsMessage(
|
displayNewlyAddedDepsMessage(
|
||||||
context.projectName,
|
context.projectName,
|
||||||
await syncDeps(
|
await syncDeps(
|
||||||
projectRoot,
|
context.projectName,
|
||||||
context.root,
|
projectPackageJson,
|
||||||
|
projectPackageJsonPath,
|
||||||
|
workspacePackageJson,
|
||||||
|
context.projectGraph,
|
||||||
typeof options.include === 'string'
|
typeof options.include === 'string'
|
||||||
? options.include.split(',')
|
? options.include.split(',')
|
||||||
: options.include,
|
: options.include,
|
||||||
typeof options.exclude === 'string'
|
typeof options.exclude === 'string'
|
||||||
? options.exclude.split(',')
|
? options.exclude.split(',')
|
||||||
: options.exclude
|
: options.exclude,
|
||||||
|
options.all
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -37,23 +55,27 @@ export default async function* syncDepsExecutor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function syncDeps(
|
export async function syncDeps(
|
||||||
projectRoot: string,
|
projectName: string,
|
||||||
workspaceRoot: string,
|
projectPackageJson: PackageJson,
|
||||||
|
projectPackageJsonPath: string,
|
||||||
|
workspacePackageJson: PackageJson,
|
||||||
|
projectGraph: ProjectGraph = readCachedProjectGraph(),
|
||||||
include: string[] = [],
|
include: string[] = [],
|
||||||
exclude: string[] = []
|
exclude: string[] = [],
|
||||||
|
all: boolean = false
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const workspacePackageJsonPath = join(workspaceRoot, 'package.json');
|
let npmDeps = all
|
||||||
const workspacePackageJson = readJsonFile(workspacePackageJsonPath);
|
? Object.keys(workspacePackageJson.dependencies || {})
|
||||||
let npmDeps = Object.keys(workspacePackageJson.dependencies || {});
|
: findAllNpmDependencies(projectGraph, projectName);
|
||||||
let npmDevdeps = Object.keys(workspacePackageJson.devDependencies || {});
|
let npmDevdeps = all
|
||||||
|
? Object.keys(workspacePackageJson.devDependencies || {})
|
||||||
|
: [];
|
||||||
|
|
||||||
const packageJsonPath = join(workspaceRoot, projectRoot, 'package.json');
|
|
||||||
const packageJson = readJsonFile(packageJsonPath);
|
|
||||||
const newDeps = [];
|
const newDeps = [];
|
||||||
let updated = false;
|
let updated = false;
|
||||||
|
|
||||||
if (!packageJson.dependencies) {
|
if (!projectPackageJson.dependencies) {
|
||||||
packageJson.dependencies = {};
|
projectPackageJson.dependencies = {};
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,30 +86,36 @@ export async function syncDeps(
|
|||||||
npmDeps = npmDeps.filter((dep) => !exclude.includes(dep));
|
npmDeps = npmDeps.filter((dep) => !exclude.includes(dep));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packageJson.devDependencies) {
|
if (!projectPackageJson.devDependencies) {
|
||||||
packageJson.devDependencies = {};
|
projectPackageJson.devDependencies = {};
|
||||||
}
|
}
|
||||||
if (!packageJson.dependencies) {
|
if (!projectPackageJson.dependencies) {
|
||||||
packageJson.dependencies = {};
|
projectPackageJson.dependencies = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
npmDeps.forEach((dep) => {
|
npmDeps.forEach((dep) => {
|
||||||
if (!packageJson.dependencies[dep] && !packageJson.devDependencies[dep]) {
|
if (
|
||||||
packageJson.dependencies[dep] = '*';
|
!projectPackageJson.dependencies[dep] &&
|
||||||
|
!projectPackageJson.devDependencies[dep]
|
||||||
|
) {
|
||||||
|
projectPackageJson.dependencies[dep] = '*';
|
||||||
newDeps.push(dep);
|
newDeps.push(dep);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
npmDevdeps.forEach((dep) => {
|
npmDevdeps.forEach((dep) => {
|
||||||
if (!packageJson.dependencies[dep] && !packageJson.devDependencies[dep]) {
|
if (
|
||||||
packageJson.devDependencies[dep] = '*';
|
!projectPackageJson.dependencies[dep] &&
|
||||||
|
!projectPackageJson.devDependencies[dep]
|
||||||
|
) {
|
||||||
|
projectPackageJson.devDependencies[dep] = '*';
|
||||||
newDeps.push(dep);
|
newDeps.push(dep);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
writeJsonFile(packageJsonPath, packageJson);
|
writeJsonFile(projectPackageJsonPath, projectPackageJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newDeps;
|
return newDeps;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ExecutorContext, names } from '@nx/devkit';
|
import { ExecutorContext, names, readJsonFile } from '@nx/devkit';
|
||||||
import { resolve as pathResolve } from 'path';
|
import { join, resolve as pathResolve } from 'path';
|
||||||
import { ChildProcess, fork } from 'child_process';
|
import { ChildProcess, fork } from 'child_process';
|
||||||
|
|
||||||
import { resolveEas } from '../../utils/resolve-eas';
|
import { resolveEas } from '../../utils/resolve-eas';
|
||||||
@ -23,10 +23,27 @@ export default async function* buildExecutor(
|
|||||||
): AsyncGenerator<ReactNativeUpdateOutput> {
|
): AsyncGenerator<ReactNativeUpdateOutput> {
|
||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
|
const workspacePackageJsonPath = join(context.root, 'package.json');
|
||||||
|
const projectPackageJsonPath = join(
|
||||||
|
context.root,
|
||||||
|
projectRoot,
|
||||||
|
'package.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
const workspacePackageJson = readJsonFile(workspacePackageJsonPath);
|
||||||
|
const projectPackageJson = readJsonFile(projectPackageJsonPath);
|
||||||
|
|
||||||
await installAsync(context.root, { packages: ['expo-updates'] });
|
await installAsync(context.root, { packages: ['expo-updates'] });
|
||||||
displayNewlyAddedDepsMessage(
|
displayNewlyAddedDepsMessage(
|
||||||
context.projectName,
|
context.projectName,
|
||||||
await syncDeps(projectRoot, context.root, ['expo-updates'])
|
await syncDeps(
|
||||||
|
context.projectName,
|
||||||
|
projectPackageJson,
|
||||||
|
projectPackageJsonPath,
|
||||||
|
workspacePackageJson,
|
||||||
|
context.projectGraph,
|
||||||
|
['expo-updates']
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
103
packages/expo/src/utils/find-all-npm-dependencies.spec.ts
Normal file
103
packages/expo/src/utils/find-all-npm-dependencies.spec.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import { findAllNpmDependencies } from './find-all-npm-dependencies';
|
||||||
|
import { DependencyType, ProjectGraph } from '@nx/devkit';
|
||||||
|
|
||||||
|
test('findAllNpmDependencies', () => {
|
||||||
|
const graph: ProjectGraph = {
|
||||||
|
nodes: {
|
||||||
|
myapp: {
|
||||||
|
type: 'app',
|
||||||
|
name: 'myapp',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib1: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib1',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib2: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib2',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib3: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib3',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
externalNodes: {
|
||||||
|
'npm:react-native-image-picker': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-image-picker',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-image-picker',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:react-native-dialog': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-dialog',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-dialog',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:react-native-snackbar': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-snackbar',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-snackbar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:@nx/react-native': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:@nx/react-native',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: '@nx/react-native',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
myapp: [
|
||||||
|
{ type: DependencyType.static, source: 'myapp', target: 'lib1' },
|
||||||
|
{ type: DependencyType.static, source: 'myapp', target: 'lib2' },
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'myapp',
|
||||||
|
target: 'npm:react-native-image-picker',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'myapp',
|
||||||
|
target: 'npm:@nx/react-native',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lib1: [
|
||||||
|
{ type: DependencyType.static, source: 'lib1', target: 'lib2' },
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-snackbar',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lib2: [{ type: DependencyType.static, source: 'lib2', target: 'lib3' }],
|
||||||
|
lib3: [
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-dialog',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = findAllNpmDependencies(graph, 'myapp');
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
'react-native-dialog',
|
||||||
|
'react-native-snackbar',
|
||||||
|
'react-native-image-picker',
|
||||||
|
]);
|
||||||
|
});
|
||||||
35
packages/expo/src/utils/find-all-npm-dependencies.ts
Normal file
35
packages/expo/src/utils/find-all-npm-dependencies.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { ProjectGraph } from '@nx/devkit';
|
||||||
|
|
||||||
|
export function findAllNpmDependencies(
|
||||||
|
graph: ProjectGraph,
|
||||||
|
projectName: string,
|
||||||
|
list: string[] = [],
|
||||||
|
seen = new Set<string>()
|
||||||
|
) {
|
||||||
|
// In case of bad circular dependencies
|
||||||
|
if (seen.has(projectName)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
seen.add(projectName);
|
||||||
|
|
||||||
|
const node = graph.externalNodes[projectName];
|
||||||
|
|
||||||
|
// Don't want to include '@nx/react-native' and '@nx/expo' because React Native
|
||||||
|
// autolink will warn that the package has no podspec file for iOS.
|
||||||
|
if (node) {
|
||||||
|
if (
|
||||||
|
node.name !== `npm:@nx/react-native` &&
|
||||||
|
node.name !== `npm:@nrwl/react-native` &&
|
||||||
|
node.name !== `npm:@nx/expo` &&
|
||||||
|
node.name !== `npm:@nrwl/expo`
|
||||||
|
) {
|
||||||
|
list.push(node.data.packageName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// it's workspace project, search for it's dependencies
|
||||||
|
graph.dependencies[projectName]?.forEach((dep) =>
|
||||||
|
findAllNpmDependencies(graph, dep.target, list, seen)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
@ -41,9 +41,11 @@ export default async function* reactNativeStorybookExecutor(
|
|||||||
displayNewlyAddedDepsMessage(
|
displayNewlyAddedDepsMessage(
|
||||||
context.projectName,
|
context.projectName,
|
||||||
await syncDeps(
|
await syncDeps(
|
||||||
|
context.projectName,
|
||||||
projectPackageJson,
|
projectPackageJson,
|
||||||
packageJsonPath,
|
packageJsonPath,
|
||||||
workspacePackageJson,
|
workspacePackageJson,
|
||||||
|
context.projectGraph,
|
||||||
[
|
[
|
||||||
`@storybook/react-native`,
|
`@storybook/react-native`,
|
||||||
'@storybook/addon-ondevice-actions',
|
'@storybook/addon-ondevice-actions',
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
export interface ReactNativeSyncDepsOptions {
|
export interface ReactNativeSyncDepsOptions {
|
||||||
include: string[] | string; // default is an empty array []
|
include: string[] | string; // default is an empty array []
|
||||||
exclude: string[] | string; // default is an empty array []
|
exclude: string[] | string; // default is an empty array []
|
||||||
|
all: boolean; // default is false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,11 @@
|
|||||||
},
|
},
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "An array of npm packages to exclude."
|
"description": "An array of npm packages to exclude."
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Copy all dependencies and devDependencies from the workspace root package.json.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,15 @@ import { join } from 'path';
|
|||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import {
|
import {
|
||||||
ExecutorContext,
|
ExecutorContext,
|
||||||
|
ProjectGraph,
|
||||||
logger,
|
logger,
|
||||||
|
readCachedProjectGraph,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
|
||||||
import { ReactNativeSyncDepsOptions } from './schema';
|
import { ReactNativeSyncDepsOptions } from './schema';
|
||||||
|
import { findAllNpmDependencies } from '../../utils/find-all-npm-dependencies';
|
||||||
import { PackageJson } from 'nx/src/utils/package-json';
|
import { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export interface ReactNativeSyncDepsOutput {
|
export interface ReactNativeSyncDepsOutput {
|
||||||
@ -33,15 +36,18 @@ export default async function* syncDepsExecutor(
|
|||||||
displayNewlyAddedDepsMessage(
|
displayNewlyAddedDepsMessage(
|
||||||
context.projectName,
|
context.projectName,
|
||||||
await syncDeps(
|
await syncDeps(
|
||||||
|
context.projectName,
|
||||||
projectPackageJson,
|
projectPackageJson,
|
||||||
projectPackageJsonPath,
|
projectPackageJsonPath,
|
||||||
workspacePackageJson,
|
workspacePackageJson,
|
||||||
|
context.projectGraph,
|
||||||
typeof options.include === 'string'
|
typeof options.include === 'string'
|
||||||
? options.include.split(',')
|
? options.include.split(',')
|
||||||
: options.include,
|
: options.include,
|
||||||
typeof options.exclude === 'string'
|
typeof options.exclude === 'string'
|
||||||
? options.exclude.split(',')
|
? options.exclude.split(',')
|
||||||
: options.exclude
|
: options.exclude,
|
||||||
|
options.all
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -49,14 +55,21 @@ export default async function* syncDepsExecutor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function syncDeps(
|
export async function syncDeps(
|
||||||
|
projectName: string,
|
||||||
projectPackageJson: PackageJson,
|
projectPackageJson: PackageJson,
|
||||||
projectPackageJsonPath: string,
|
projectPackageJsonPath: string,
|
||||||
workspacePackageJson: PackageJson,
|
workspacePackageJson: PackageJson,
|
||||||
|
projectGraph: ProjectGraph = readCachedProjectGraph(),
|
||||||
include: string[] = [],
|
include: string[] = [],
|
||||||
exclude: string[] = []
|
exclude: string[] = [],
|
||||||
|
all: boolean = false
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
let npmDeps = Object.keys(workspacePackageJson.dependencies || {});
|
let npmDeps = all
|
||||||
let npmDevdeps = Object.keys(workspacePackageJson.devDependencies || {});
|
? Object.keys(workspacePackageJson.dependencies || {})
|
||||||
|
: findAllNpmDependencies(projectGraph, projectName);
|
||||||
|
let npmDevdeps = all
|
||||||
|
? Object.keys(workspacePackageJson.devDependencies || {})
|
||||||
|
: [];
|
||||||
|
|
||||||
const newDeps = [];
|
const newDeps = [];
|
||||||
let updated = false;
|
let updated = false;
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
output,
|
output,
|
||||||
|
readCachedProjectGraph,
|
||||||
readJson,
|
readJson,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
@ -98,22 +99,19 @@ export async function reactNativeApplicationGeneratorInternal(
|
|||||||
joinPathFragments(host.root, options.iosProjectRoot)
|
joinPathFragments(host.root, options.iosProjectRoot)
|
||||||
);
|
);
|
||||||
if (options.install) {
|
if (options.install) {
|
||||||
const workspacePackageJsonPath = joinPathFragments('package.json');
|
|
||||||
const projectPackageJsonPath = joinPathFragments(
|
const projectPackageJsonPath = joinPathFragments(
|
||||||
options.appProjectRoot,
|
options.appProjectRoot,
|
||||||
'package.json'
|
'package.json'
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspacePackageJson = readJson<PackageJson>(
|
const workspacePackageJson = readJson<PackageJson>(host, 'package.json');
|
||||||
host,
|
|
||||||
workspacePackageJsonPath
|
|
||||||
);
|
|
||||||
const projectPackageJson = readJson<PackageJson>(
|
const projectPackageJson = readJson<PackageJson>(
|
||||||
host,
|
host,
|
||||||
projectPackageJsonPath
|
projectPackageJsonPath
|
||||||
);
|
);
|
||||||
|
|
||||||
await syncDeps(
|
await syncDeps(
|
||||||
|
options.name,
|
||||||
projectPackageJson,
|
projectPackageJson,
|
||||||
projectPackageJsonPath,
|
projectPackageJsonPath,
|
||||||
workspacePackageJson
|
workspacePackageJson
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
import { findAllNpmDependencies } from './find-all-npm-dependencies';
|
||||||
|
import { DependencyType, ProjectGraph } from '@nx/devkit';
|
||||||
|
|
||||||
|
test('findAllNpmDependencies', () => {
|
||||||
|
const graph: ProjectGraph = {
|
||||||
|
nodes: {
|
||||||
|
myapp: {
|
||||||
|
type: 'app',
|
||||||
|
name: 'myapp',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib1: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib1',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib2: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib2',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
lib3: {
|
||||||
|
type: 'lib',
|
||||||
|
name: 'lib3',
|
||||||
|
data: { files: [] },
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
externalNodes: {
|
||||||
|
'npm:react-native-image-picker': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-image-picker',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-image-picker',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:react-native-dialog': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-dialog',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-dialog',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:react-native-snackbar': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:react-native-snackbar',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: 'react-native-snackbar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'npm:@nx/react-native': {
|
||||||
|
type: 'npm',
|
||||||
|
name: 'npm:@nx/react-native',
|
||||||
|
data: {
|
||||||
|
version: '1',
|
||||||
|
packageName: '@nx/react-native',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
myapp: [
|
||||||
|
{ type: DependencyType.static, source: 'myapp', target: 'lib1' },
|
||||||
|
{ type: DependencyType.static, source: 'myapp', target: 'lib2' },
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'myapp',
|
||||||
|
target: 'npm:react-native-image-picker',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'myapp',
|
||||||
|
target: 'npm:@nx/react-native',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lib1: [
|
||||||
|
{ type: DependencyType.static, source: 'lib1', target: 'lib2' },
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-snackbar',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lib2: [{ type: DependencyType.static, source: 'lib2', target: 'lib3' }],
|
||||||
|
lib3: [
|
||||||
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-dialog',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = findAllNpmDependencies(graph, 'myapp');
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
'react-native-dialog',
|
||||||
|
'react-native-snackbar',
|
||||||
|
'react-native-image-picker',
|
||||||
|
]);
|
||||||
|
});
|
||||||
35
packages/react-native/src/utils/find-all-npm-dependencies.ts
Normal file
35
packages/react-native/src/utils/find-all-npm-dependencies.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { ProjectGraph } from '@nx/devkit';
|
||||||
|
|
||||||
|
export function findAllNpmDependencies(
|
||||||
|
graph: ProjectGraph,
|
||||||
|
projectName: string,
|
||||||
|
list: string[] = [],
|
||||||
|
seen = new Set<string>()
|
||||||
|
) {
|
||||||
|
// In case of bad circular dependencies
|
||||||
|
if (seen.has(projectName)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
seen.add(projectName);
|
||||||
|
|
||||||
|
const node = graph.externalNodes[projectName];
|
||||||
|
|
||||||
|
// Don't want to include '@nx/react-native' and '@nx/expo' because React Native
|
||||||
|
// autolink will warn that the package has no podspec file for iOS.
|
||||||
|
if (node) {
|
||||||
|
if (
|
||||||
|
node.name !== `npm:@nx/react-native` &&
|
||||||
|
node.name !== `npm:@nrwl/react-native` &&
|
||||||
|
node.name !== `npm:@nx/expo` &&
|
||||||
|
node.name !== `npm:@nrwl/expo`
|
||||||
|
) {
|
||||||
|
list.push(node.data.packageName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// it's workspace project, search for it's dependencies
|
||||||
|
graph.dependencies[projectName]?.forEach((dep) =>
|
||||||
|
findAllNpmDependencies(graph, dep.target, list, seen)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user