feat(core): use inputs to determine package dependencies (#13966)

This commit is contained in:
Denis Frenademetz 2023-03-14 16:02:00 +01:00 committed by GitHub
parent 9acd7757ae
commit ebdb193f0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 701 additions and 85 deletions

View File

@ -1070,13 +1070,15 @@ Convert an Nx Generator into an Angular Devkit Schematic.
#### Parameters #### Parameters
| Name | Type | | Name | Type |
| :---------------------- | :---------------------------------------------------------------- | | :---------------------------- | :---------------------------------------------------------------- |
| `projectName` | `string` | | `projectName` | `string` |
| `graph` | [`ProjectGraph`](../../devkit/documents/nrwl_devkit#projectgraph) | | `graph` | [`ProjectGraph`](../../devkit/documents/nrwl_devkit#projectgraph) |
| `options` | `Object` | | `options` | `Object` |
| `options.isProduction?` | `boolean` | | `options.helperDependencies?` | `string`[] |
| `options.root?` | `string` | | `options.isProduction?` | `boolean` |
| `options.root?` | `string` |
| `options.target?` | `string` |
#### Returns #### Returns

View File

@ -1070,13 +1070,15 @@ Convert an Nx Generator into an Angular Devkit Schematic.
#### Parameters #### Parameters
| Name | Type | | Name | Type |
| :---------------------- | :---------------------------------------------------------------- | | :---------------------------- | :---------------------------------------------------------------- |
| `projectName` | `string` | | `projectName` | `string` |
| `graph` | [`ProjectGraph`](../../devkit/documents/nrwl_devkit#projectgraph) | | `graph` | [`ProjectGraph`](../../devkit/documents/nrwl_devkit#projectgraph) |
| `options` | `Object` | | `options` | `Object` |
| `options.isProduction?` | `boolean` | | `options.helperDependencies?` | `string`[] |
| `options.root?` | `string` | | `options.isProduction?` | `boolean` |
| `options.root?` | `string` |
| `options.target?` | `string` |
#### Returns #### Returns

View File

@ -6,7 +6,7 @@ import {
UpdatePackageJsonOption, UpdatePackageJsonOption,
} from './update-package-json'; } from './update-package-json';
import { vol } from 'memfs'; import { vol } from 'memfs';
import { ExecutorContext, ProjectGraph } from '@nrwl/devkit'; import { DependencyType, ExecutorContext, ProjectGraph } from '@nrwl/devkit';
import { DependentBuildableProjectNode } from '../buildable-libs-utils'; import { DependentBuildableProjectNode } from '../buildable-libs-utils';
jest.mock('nx/src/utils/workspace-root', () => ({ jest.mock('nx/src/utils/workspace-root', () => ({
@ -298,7 +298,24 @@ describe('updatePackageJson', () => {
outputs: ['{workspaceRoot}/dist/libs/lib1'], outputs: ['{workspaceRoot}/dist/libs/lib1'],
}, },
}, },
files: [], files: [
{
file: 'test.ts',
hash: '',
dependencies: [
{
type: DependencyType.static,
target: 'npm:external1',
source: '@org/lib1',
},
{
type: DependencyType.static,
target: 'npm:external2',
source: '@org/lib1',
},
],
},
],
}, },
}, },
}, },
@ -330,8 +347,16 @@ describe('updatePackageJson', () => {
}, },
dependencies: { dependencies: {
'@org/lib1': [ '@org/lib1': [
{ source: '@org/lib1', target: 'npm:external1', type: 'static' }, {
{ source: '@org/lib1', target: 'npm:external2', type: 'static' }, source: '@org/lib1',
target: 'npm:external1',
type: DependencyType.static,
},
{
source: '@org/lib1',
target: 'npm:external2',
type: DependencyType.static,
},
], ],
}, },
}; };

View File

@ -54,6 +54,7 @@ export function updatePackageJson(
if (options.updateBuildableProjectDepsInPackageJson) { if (options.updateBuildableProjectDepsInPackageJson) {
packageJson = createPackageJson(context.projectName, context.projectGraph, { packageJson = createPackageJson(context.projectName, context.projectGraph, {
target: context.targetName,
root: context.root, root: context.root,
// By default we remove devDependencies since this is a production build. // By default we remove devDependencies since this is a production build.
isProduction: true, isProduction: true,

View File

@ -84,6 +84,7 @@ export default async function buildExecutor(
context.projectName, context.projectName,
context.projectGraph, context.projectGraph,
{ {
target: context.targetName,
root: context.root, root: context.root,
isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build. isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build.
} }

View File

@ -186,7 +186,7 @@ export class Hasher {
} }
} }
const DEFAULT_INPUTS = [ const DEFAULT_INPUTS: ReadonlyArray<InputDefinition> = [
{ {
projects: 'self', projects: 'self',
fileset: '{projectRoot}/**/*', fileset: '{projectRoot}/**/*',
@ -221,11 +221,7 @@ class TaskHasher {
if (!projectNode) { if (!projectNode) {
return this.hashExternalDependency(task.target.project); return this.hashExternalDependency(task.target.project);
} }
const namedInputs = { const namedInputs = getNamedInputs(this.nxJson, projectNode);
default: [{ fileset: '{projectRoot}/**/*' }],
...this.nxJson.namedInputs,
...projectNode.data.namedInputs,
};
const targetData = projectNode.data.targets[task.target.target]; const targetData = projectNode.data.targets[task.target.target];
const targetDefaults = (this.nxJson.targetDefaults || {})[ const targetDefaults = (this.nxJson.targetDefaults || {})[
task.target.target task.target.target
@ -399,9 +395,7 @@ class TaskHasher {
projectName: string, projectName: string,
inputs: ExpandedSelfInput[] inputs: ExpandedSelfInput[]
): Promise<PartialHash[]> { ): Promise<PartialHash[]> {
const filesets = inputs const filesets = extractPatternsFromFileSets(inputs);
.filter((r) => !!r['fileset'])
.map((r) => r['fileset']);
const projectFilesets = []; const projectFilesets = [];
const workspaceFilesets = []; const workspaceFilesets = [];
@ -563,9 +557,52 @@ class TaskHasher {
} }
} }
export function getNamedInputs(
nxJson: NxJsonConfiguration,
project: ProjectGraphProjectNode
) {
return {
default: [{ fileset: '{projectRoot}/**/*' }],
...nxJson.namedInputs,
...project.data.namedInputs,
};
}
export function getTargetInputs(
nxJson: NxJsonConfiguration,
projectNode: ProjectGraphProjectNode,
target: string
) {
const namedInputs = getNamedInputs(nxJson, projectNode);
const targetData = projectNode.data.targets[target];
const targetDefaults = (nxJson.targetDefaults || {})[target];
const inputs = splitInputsIntoSelfAndDependencies(
targetData.inputs || targetDefaults?.inputs || DEFAULT_INPUTS,
namedInputs
);
const selfInputs = extractPatternsFromFileSets(inputs.selfInputs);
const dependencyInputs = extractPatternsFromFileSets(
inputs.depsInputs.map((s) => expandNamedInput(s.input, namedInputs)).flat()
);
return { selfInputs, dependencyInputs };
}
export function extractPatternsFromFileSets(
inputs: readonly ExpandedSelfInput[]
): string[] {
return inputs
.filter((c): c is { fileset: string } => !!c['fileset'])
.map((c) => c['fileset']);
}
export function splitInputsIntoSelfAndDependencies( export function splitInputsIntoSelfAndDependencies(
inputs: (InputDefinition | string)[], inputs: ReadonlyArray<InputDefinition | string>,
namedInputs: { [inputName: string]: (InputDefinition | string)[] } namedInputs: { [inputName: string]: ReadonlyArray<InputDefinition | string> }
): { ): {
depsInputs: { input: string }[]; depsInputs: { input: string }[];
selfInputs: ExpandedSelfInput[]; selfInputs: ExpandedSelfInput[];
@ -591,8 +628,8 @@ export function splitInputsIntoSelfAndDependencies(
} }
function expandSelfInputs( function expandSelfInputs(
inputs: (InputDefinition | string)[], inputs: ReadonlyArray<InputDefinition | string>,
namedInputs: { [inputName: string]: (InputDefinition | string)[] } namedInputs: { [inputName: string]: ReadonlyArray<InputDefinition | string> }
): ExpandedSelfInput[] { ): ExpandedSelfInput[] {
const expanded = []; const expanded = [];
for (const d of inputs) { for (const d of inputs) {
@ -623,7 +660,7 @@ function expandSelfInputs(
export function expandNamedInput( export function expandNamedInput(
input: string, input: string,
namedInputs: { [inputName: string]: (InputDefinition | string)[] } namedInputs: { [inputName: string]: ReadonlyArray<InputDefinition | string> }
): ExpandedSelfInput[] { ): ExpandedSelfInput[] {
namedInputs ||= {}; namedInputs ||= {};
if (!namedInputs[input]) throw new Error(`Input '${input}' is not defined`); if (!namedInputs[input]) throw new Error(`Input '${input}' is not defined`);

View File

@ -0,0 +1,502 @@
import * as fs from 'fs';
import * as configModule from '../config/configuration';
import { DependencyType } from '../config/project-graph';
import * as hashModule from '../hasher/hasher';
import { createPackageJson } from './create-package-json';
import * as fileutilsModule from './fileutils';
describe('createPackageJson', () => {
it('should add additional dependencies', () => {
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
jest.spyOn(fileutilsModule, 'readJsonFile').mockReturnValue({
dependencies: {
typescript: '4.8.4',
tslib: '2.4.0',
},
});
expect(
createPackageJson(
'lib1',
{
nodes: {
lib1: {
type: 'lib',
name: 'lib1',
data: { files: [], targets: {}, root: '' },
},
},
externalNodes: {
'npm:tslib': {
type: 'npm',
name: 'npm:tslib',
data: { version: '2.4.0', hash: '', packageName: 'tslib' },
},
},
dependencies: {},
},
{ helperDependencies: ['npm:tslib'] }
)
).toEqual({
dependencies: {
tslib: '2.4.0',
},
name: 'lib1',
version: '0.0.1',
});
});
it('should only add file dependencies if target is specified', () => {
jest.spyOn(configModule, 'readNxJson').mockReturnValueOnce({
namedInputs: {
default: ['{projectRoot}/**/*'],
production: ['!{projectRoot}/**/*.spec.ts'],
},
targetDefaults: {
build: {
inputs: ['default', 'production', '^production'],
},
},
});
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
jest.spyOn(fileutilsModule, 'readJsonFile').mockReturnValue({
dependencies: {
axios: '1.0.0',
tslib: '2.4.0',
jest: '29.0.0',
typescript: '4.8.4',
},
});
expect(
createPackageJson(
'lib1',
{
nodes: {
lib1: {
type: 'lib',
name: 'lib1',
data: {
root: 'libs/lib1',
targets: {
build: {},
},
files: [
{
file: 'libs/lib1/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:typescript',
source: 'lib1',
},
],
hash: '',
},
{
file: 'libs/lib1/src/main2.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib2',
source: 'lib1',
},
],
hash: '',
},
{
file: 'libs/lib1/src/main.spec.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:jest',
source: 'lib1',
},
],
hash: '',
},
],
},
},
lib2: {
type: 'lib',
name: 'lib2',
data: {
root: 'libs/lib2',
targets: {
build: {},
},
files: [
{
file: 'libs/lib2/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:axios',
source: 'lib2',
},
],
hash: '',
},
{
file: 'libs/lib2/src/main.spec.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:jest',
source: 'lib2',
},
],
hash: '',
},
],
},
},
},
externalNodes: {
'npm:tslib': {
type: 'npm',
name: 'npm:tslib',
data: { version: '2.4.0', hash: '', packageName: 'tslib' },
},
'npm:typescript': {
type: 'npm',
name: 'npm:typescript',
data: { version: '4.8.4', hash: '', packageName: 'typescript' },
},
'npm:jest': {
type: 'npm',
name: 'npm:jest',
data: { version: '29.0.0', hash: '', packageName: 'jest' },
},
'npm:axios': {
type: 'npm',
name: 'npm:jest',
data: { version: '1.0.0', hash: '', packageName: 'axios' },
},
},
dependencies: {},
},
{
target: 'build',
isProduction: true,
helperDependencies: ['npm:tslib'],
}
)
).toEqual({
dependencies: {
axios: '1.0.0',
tslib: '2.4.0',
typescript: '4.8.4',
},
name: 'lib1',
version: '0.0.1',
});
});
it('should only add all dependencies if target is not specified', () => {
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
jest.spyOn(fileutilsModule, 'readJsonFile').mockReturnValue({
dependencies: {
axios: '1.0.0',
tslib: '2.4.0',
jest: '29.0.0',
typescript: '4.8.4',
},
});
expect(
createPackageJson(
'lib1',
{
nodes: {
lib1: {
type: 'lib',
name: 'lib1',
data: {
root: 'libs/lib1',
targets: {
build: {},
},
files: [
{
file: 'libs/lib1/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:typescript',
source: 'lib1',
},
],
hash: '',
},
{
file: 'libs/lib1/src/main2.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib2',
source: 'lib1',
},
],
hash: '',
},
{
file: 'libs/lib1/src/main.spec.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:jest',
source: 'lib1',
},
],
hash: '',
},
],
},
},
lib2: {
type: 'lib',
name: 'lib2',
data: {
root: 'libs/lib2',
targets: {
build: {},
},
files: [
{
file: 'libs/lib2/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:axios',
source: 'lib2',
},
],
hash: '',
},
{
file: 'libs/lib2/src/main.spec.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:jest',
source: 'lib2',
},
],
hash: '',
},
],
},
},
},
externalNodes: {
'npm:tslib': {
type: 'npm',
name: 'npm:tslib',
data: { version: '2.4.0', hash: '', packageName: 'tslib' },
},
'npm:typescript': {
type: 'npm',
name: 'npm:typescript',
data: { version: '4.8.4', hash: '', packageName: 'typescript' },
},
'npm:jest': {
type: 'npm',
name: 'npm:jest',
data: { version: '29.0.0', hash: '', packageName: 'jest' },
},
'npm:axios': {
type: 'npm',
name: 'npm:axios',
data: { version: '1.0.0', hash: '', packageName: 'axios' },
},
},
dependencies: {},
},
{ isProduction: true, helperDependencies: ['npm:tslib'] }
)
).toEqual({
dependencies: {
axios: '1.0.0',
jest: '29.0.0',
tslib: '2.4.0',
typescript: '4.8.4',
},
name: 'lib1',
version: '0.0.1',
});
});
it('should cache filterUsingGlobPatterns', () => {
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
jest.spyOn(fileutilsModule, 'readJsonFile').mockReturnValue({
dependencies: {
axios: '1.0.0',
tslib: '2.4.0',
jest: '29.0.0',
typescript: '4.8.4',
},
});
const filterUsingGlobPatternsSpy = jest.spyOn(
hashModule,
'filterUsingGlobPatterns'
);
expect(
createPackageJson(
'lib1',
{
nodes: {
lib1: {
type: 'lib',
name: 'lib1',
data: {
root: 'libs/lib1',
targets: {
build: {},
},
files: [
{
file: 'libs/lib1/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib3',
source: 'lib1',
},
],
hash: '',
},
{
file: 'libs/lib1/src/main2.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib2',
source: 'lib1',
},
],
hash: '',
},
],
},
},
lib2: {
type: 'lib',
name: 'lib2',
data: {
root: 'libs/lib2',
targets: {
build: {},
},
files: [
{
file: 'libs/lib2/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib4',
source: 'lib2',
},
],
hash: '',
},
],
},
},
lib3: {
type: 'lib',
name: 'lib3',
data: {
root: 'libs/lib3',
targets: {
build: {},
},
files: [
{
file: 'libs/lib3/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'lib4',
source: 'lib3',
},
],
hash: '',
},
],
},
},
lib4: {
type: 'lib',
name: 'lib4',
data: {
root: 'libs/lib4',
targets: {
build: {},
},
files: [
{
file: 'libs/lib2/src/main.ts',
dependencies: [
{
type: DependencyType.static,
target: 'npm:axios',
source: 'lib2',
},
],
hash: '',
},
],
},
},
},
externalNodes: {
'npm:axios': {
type: 'npm',
name: 'npm:axios',
data: { version: '1.0.0', hash: '', packageName: 'axios' },
},
},
dependencies: {},
},
{ isProduction: true }
)
).toEqual({
dependencies: {
axios: '1.0.0',
},
name: 'lib1',
version: '0.0.1',
});
expect(filterUsingGlobPatternsSpy).toHaveBeenNthCalledWith(
1,
'libs/lib1',
expect.anything(),
expect.anything()
);
expect(filterUsingGlobPatternsSpy).toHaveBeenNthCalledWith(
2,
'libs/lib3',
expect.anything(),
expect.anything()
);
expect(filterUsingGlobPatternsSpy).toHaveBeenNthCalledWith(
3,
'libs/lib4',
expect.anything(),
expect.anything()
);
expect(filterUsingGlobPatternsSpy).toHaveBeenNthCalledWith(
4,
'libs/lib2',
expect.anything(),
expect.anything()
);
expect(filterUsingGlobPatternsSpy).toHaveBeenCalledTimes(4);
});
});

View File

@ -1,9 +1,17 @@
import { readJsonFile } from './fileutils'; import { readJsonFile } from './fileutils';
import { sortObjectByKeys } from './object-sort'; import { sortObjectByKeys } from './object-sort';
import { ProjectGraph } from '../config/project-graph'; import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
import { PackageJson } from './package-json'; import { PackageJson } from './package-json';
import { existsSync } from 'fs'; import { existsSync } from 'fs';
import { workspaceRoot } from './workspace-root'; import { workspaceRoot } from './workspace-root';
import { filterUsingGlobPatterns, getTargetInputs } from '../hasher/hasher';
import { readNxJson } from '../config/configuration';
interface NpmDeps {
readonly dependencies: Record<string, string>;
readonly peerDependencies: Record<string, string>;
readonly peerDependenciesMeta: Record<string, { optional: boolean }>;
}
/** /**
* Creates a package.json in the output directory for support to install dependencies within containers. * Creates a package.json in the output directory for support to install dependencies within containers.
@ -15,11 +23,42 @@ export function createPackageJson(
projectName: string, projectName: string,
graph: ProjectGraph, graph: ProjectGraph,
options: { options: {
target?: string;
root?: string; root?: string;
isProduction?: boolean; isProduction?: boolean;
helperDependencies?: string[];
} = {} } = {}
): PackageJson { ): PackageJson {
const npmDeps = findAllNpmDeps(projectName, graph); const projectNode = graph.nodes[projectName];
const { selfInputs, dependencyInputs } = options.target
? getTargetInputs(readNxJson(), projectNode, options.target)
: { selfInputs: [], dependencyInputs: [] };
const npmDeps: NpmDeps = {
dependencies: {},
peerDependencies: {},
peerDependenciesMeta: {},
};
const seen = new Set<string>();
options.helperDependencies?.forEach((dep) => {
seen.add(dep);
npmDeps.dependencies[graph.externalNodes[dep].data.packageName] =
graph.externalNodes[dep].data.version;
recursivelyCollectPeerDependencies(dep, graph, npmDeps, seen);
});
findAllNpmDeps(
projectNode,
graph,
npmDeps,
seen,
dependencyInputs,
selfInputs
);
// default package.json if one does not exist // default package.json if one does not exist
let packageJson: PackageJson = { let packageJson: PackageJson = {
name: projectName, name: projectName,
@ -104,64 +143,73 @@ export function createPackageJson(
} }
function findAllNpmDeps( function findAllNpmDeps(
projectName: string, projectNode: ProjectGraphProjectNode,
graph: ProjectGraph, graph: ProjectGraph,
list: { npmDeps: NpmDeps,
dependencies: Record<string, string>; seen: Set<string>,
peerDependencies: Record<string, string>; dependencyPatterns: string[],
peerDependenciesMeta: Record<string, { optional: boolean }>; rootPatterns?: string[]
} = { dependencies: {}, peerDependencies: {}, peerDependenciesMeta: {} }, ): void {
seen = new Set<string>() if (seen.has(projectNode.name)) return;
) {
const node = graph.externalNodes[projectName];
if (seen.has(projectName)) { seen.add(projectNode.name);
// if it's in peerDependencies, move it to regular dependencies
// since this is a direct dependency of the project
if (node && list.peerDependencies[node.data.packageName]) {
list.dependencies[node.data.packageName] = node.data.version;
delete list.peerDependencies[node.data.packageName];
}
return list;
}
seen.add(projectName); const projectFiles = filterUsingGlobPatterns(
projectNode.data.root,
projectNode.data.files,
rootPatterns ?? dependencyPatterns
);
if (node) { const projectDependencies = new Set<string>();
list.dependencies[node.data.packageName] = node.data.version;
recursivelyCollectPeerDependencies(node.name, graph, list, seen); projectFiles.forEach((fileData) =>
} else { fileData.dependencies?.forEach((dep) => projectDependencies.add(dep.target))
// we are not interested in the dependencies of external projects );
graph.dependencies[projectName]?.forEach((dep) => {
if (dep.type === 'static' || dep.type === 'dynamic') { for (const dep of projectDependencies) {
findAllNpmDeps(dep.target, graph, list, seen); const node = graph.externalNodes[dep];
if (seen.has(dep)) {
// if it's in peerDependencies, move it to regular dependencies
// since this is a direct dependency of the project
if (node && npmDeps.peerDependencies[node.data.packageName]) {
npmDeps.dependencies[node.data.packageName] = node.data.version;
delete npmDeps.peerDependencies[node.data.packageName];
} }
}); } else {
if (node) {
seen.add(dep);
npmDeps.dependencies[node.data.packageName] = node.data.version;
recursivelyCollectPeerDependencies(node.name, graph, npmDeps, seen);
} else {
findAllNpmDeps(
graph.nodes[dep],
graph,
npmDeps,
seen,
dependencyPatterns
);
}
}
} }
return list;
} }
function recursivelyCollectPeerDependencies( function recursivelyCollectPeerDependencies(
projectName: string, projectName: string,
graph: ProjectGraph, graph: ProjectGraph,
list: { npmDeps: NpmDeps,
dependencies: Record<string, string>; seen: Set<string>
peerDependencies: Record<string, string>;
peerDependenciesMeta: Record<string, { optional: boolean }>;
},
seen = new Set<string>()
) { ) {
const npmPackage = graph.externalNodes[projectName]; const npmPackage = graph.externalNodes[projectName];
if (!npmPackage) { if (!npmPackage) {
return list; return npmDeps;
} }
const packageName = npmPackage.data.packageName; const packageName = npmPackage.data.packageName;
try { try {
const packageJson = require(`${packageName}/package.json`); const packageJson = require(`${packageName}/package.json`);
if (!packageJson.peerDependencies) { if (!packageJson.peerDependencies) {
return list; return npmDeps;
} }
Object.keys(packageJson.peerDependencies) Object.keys(packageJson.peerDependencies)
@ -171,21 +219,21 @@ function recursivelyCollectPeerDependencies(
.forEach((node) => { .forEach((node) => {
if (!seen.has(node.name)) { if (!seen.has(node.name)) {
seen.add(node.name); seen.add(node.name);
list.peerDependencies[node.data.packageName] = node.data.version; npmDeps.peerDependencies[node.data.packageName] = node.data.version;
if ( if (
packageJson.peerDependenciesMeta && packageJson.peerDependenciesMeta &&
packageJson.peerDependenciesMeta[node.data.packageName] && packageJson.peerDependenciesMeta[node.data.packageName] &&
packageJson.peerDependenciesMeta[node.data.packageName].optional packageJson.peerDependenciesMeta[node.data.packageName].optional
) { ) {
list.peerDependenciesMeta[node.data.packageName] = { npmDeps.peerDependenciesMeta[node.data.packageName] = {
optional: true, optional: true,
}; };
} }
recursivelyCollectPeerDependencies(node.name, graph, list, seen); recursivelyCollectPeerDependencies(node.name, graph, npmDeps, seen);
} }
}); });
return list; return npmDeps;
} catch (e) { } catch (e) {
return list; return npmDeps;
} }
} }

View File

@ -54,17 +54,15 @@ export class GeneratePackageJsonPlugin implements WebpackPluginInstance {
}); });
} }
if (helperDependencies.length > 0) {
this.projectGraph.dependencies[this.context.projectName] =
this.projectGraph.dependencies[this.context.projectName].concat(
helperDependencies
);
}
const packageJson = createPackageJson( const packageJson = createPackageJson(
this.context.projectName, this.context.projectName,
this.projectGraph, this.projectGraph,
{ root: this.context.root, isProduction: true } {
target: this.context.targetName,
root: this.context.root,
isProduction: true,
helperDependencies: helperDependencies.map((dep) => dep.target),
}
); );
packageJson.main = packageJson.main ?? this.options.outputFileName; packageJson.main = packageJson.main ?? this.options.outputFileName;