Skip to content

Commit 03d324a

Browse files
authored
Merge pull request #7291 from IgniteUI/vslavov/ng-add-depenendencies-explicit
refactor(schematics): explicit def of pckgs to be added to app's deps
2 parents 6c947c1 + de67880 commit 03d324a

File tree

4 files changed

+76
-49
lines changed

4 files changed

+76
-49
lines changed

projects/igniteui-angular/schematics/ng-add/add-normalize.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as path from 'path';
33
import { Tree } from '@angular-devkit/schematics';
44
import { getWorkspace, getWorkspacePath } from '@schematics/angular/utility/config';
55
import { WorkspaceProject, ProjectType } from '@schematics/angular/utility/workspace-models';
6+
import { addPackageToPkgJson } from '../utils/dependency-handler';
67

78
const resetPackage = { 'minireset.css': '~0.0.4' };
89

@@ -56,13 +57,8 @@ export function addResetCss(host: Tree): boolean {
5657
}
5758

5859
if (addPackage) {
59-
const targetFile = 'package.json';
60-
if (host.exists(targetFile)) {
61-
const pkgJson = JSON.parse(host.read(targetFile).toString());
62-
pkgJson.dependencies = Object.assign({}, addPackage, pkgJson.dependencies);
63-
host.overwrite(targetFile, JSON.stringify(pkgJson, null, 2) + '\n');
64-
return true;
65-
}
60+
const name = Object.keys(resetPackage)[0];
61+
return addPackageToPkgJson(host, name, resetPackage[name], 'dependencies');
6662
}
6763
return false;
6864
}

projects/igniteui-angular/schematics/ng-add/index.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as path from 'path';
44
import { getWorkspace } from '@schematics/angular/utility/config';
55
import { scssImport, cssImport } from './add-normalize';
66
import { ProjectType } from '@schematics/angular/utility/workspace-models';
7+
import { DEPENDENCIES_MAP, PackageTarget, PackageEntry } from '../utils/dependency-handler';
78

89
describe('ng-add schematics', () => {
910
const collectionPath = path.join(__dirname, '../collection.json');
@@ -57,11 +58,34 @@ describe('ng-add schematics', () => {
5758
expect(Object.keys(pkgJsonData).length).toBeGreaterThan(0);
5859
});
5960

61+
it('should include ALL dependencies in map', () => {
62+
const pkgJson = require('../../package.json');
63+
const allDependencies = Object.assign({}, pkgJson.dependencies, pkgJson.peerDependencies, pkgJson.igxDevDependencies);
64+
for (const key of Object.keys(allDependencies)) {
65+
const expectedPackages: PackageEntry = {
66+
name: key,
67+
target: jasmine.anything() as any
68+
};
69+
expect(DEPENDENCIES_MAP).toContain(expectedPackages, `Dependency ${key} missing in dependencies map!`);
70+
}
71+
});
72+
6073
it('should add packages to package.json dependencies', () => {
74+
const expectedDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.REGULAR).map(dep => dep.name);
75+
const expectedDevDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.DEV).map(dep => dep.name);
6176
runner.runSchematic('ng-add', { normalizeCss: false }, tree);
6277
const pkgJsonData = JSON.parse(tree.readContent('/package.json'));
6378
expect(pkgJsonData.dependencies).toBeTruthy();
6479
expect(pkgJsonData.devDependencies).toBeTruthy();
80+
// Check for explicit dependencies
81+
expect(Object.keys(pkgJsonData.dependencies).length).toEqual(expectedDeps.length, `Different number of added dependencies!`);
82+
expect(Object.keys(pkgJsonData.devDependencies).length).toEqual(expectedDevDeps.length, `Different number of added devDependencies!`);
83+
for (const dependency of expectedDeps) {
84+
expect(pkgJsonData.dependencies.hasOwnProperty(dependency)).toEqual(true, `Dependency ${dependency} is missing from output!`);
85+
}
86+
for (const dependency of expectedDevDeps) {
87+
expect(pkgJsonData.devDependencies.hasOwnProperty(dependency)).toEqual(true, `DevDependency ${dependency} is missing from output!`);
88+
}
6589
});
6690

6791
it('should add the correct igniteui-angular packages to package.json dependencies', () => {

projects/igniteui-angular/schematics/ng-add/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { logSuccess, addDependencies, overwriteJsonFile,
55
getPropertyFromWorkspace, getConfigFile } from '../utils/dependency-handler';
66

77
import { addResetCss } from './add-normalize';
8-
import { getWorkspace, getConfig } from '@schematics/angular/utility/config';
8+
import { getWorkspace } from '@schematics/angular/utility/config';
99
import { WorkspaceSchema } from '@schematics/angular/utility/workspace-models';
1010

1111

projects/igniteui-angular/schematics/utils/dependency-handler.ts

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,41 @@ import { SchematicContext, Rule, SchematicsException } from '@angular-devkit/sch
22
import { Tree } from '@angular-devkit/schematics/src/tree/interface';
33
import { getWorkspace } from '@schematics/angular/utility/config';
44
import { Options } from '../interfaces/options';
5-
import { WorkspaceProject, ProjectType, WorkspaceSchema } from '@schematics/angular/utility/workspace-models';
5+
import { WorkspaceProject, ProjectType } from '@schematics/angular/utility/workspace-models';
6+
7+
8+
export enum PackageTarget {
9+
DEV = 'devDependencies',
10+
REGULAR = 'dependencies',
11+
NONE = 'none'
12+
}
13+
export interface PackageEntry {
14+
name: string;
15+
target: PackageTarget;
16+
}
17+
618

719
const schematicsPackage = '@igniteui/angular-schematics';
20+
/**
21+
* Dependencies are explicitly defined here, so we avoid adding
22+
* unnecessary packages to the consuming project's deps
23+
*/
24+
export const DEPENDENCIES_MAP: PackageEntry[] = [
25+
// dependencies
26+
{ name: 'hammerjs', target: PackageTarget.REGULAR },
27+
{ name: 'jszip', target: PackageTarget.REGULAR },
28+
{ name: 'resize-observer-polyfill', target: PackageTarget.REGULAR },
29+
{ name: '@types/hammerjs', target: PackageTarget.DEV },
30+
{ name: '@types/jszip', target: PackageTarget.DEV },
31+
// peerDependencies
32+
{ name: '@angular/forms', target: PackageTarget.NONE },
33+
{ name: '@angular/common', target: PackageTarget.NONE },
34+
{ name: '@angular/core', target: PackageTarget.NONE },
35+
{ name: '@angular/animations', target: PackageTarget.NONE },
36+
{ name: 'web-animations-js', target: PackageTarget.REGULAR },
37+
// igxDevDependencies
38+
{ name: '@igniteui/angular-schematics', target: PackageTarget.DEV }
39+
];
840

941
function logIncludingDependency(context: SchematicContext, pkg: string, version: string): void {
1042
context.logger.info(`Including ${pkg} - Version: ${version}`);
@@ -52,22 +84,20 @@ export function logSuccess(options: Options): Rule {
5284
export function addDependencies(options: Options): Rule {
5385
return (tree: Tree, context: SchematicContext) => {
5486
const pkgJson = require('../../package.json');
55-
const dependencies = 'dependencies';
56-
const devDependencies = 'devDependencies';
5787

58-
includeDependencies(pkgJson, context, tree, dependencies);
88+
includeDependencies(pkgJson, context, tree);
5989

6090
// Add web-animations-js to dependencies
6191
Object.keys(pkgJson.peerDependencies).forEach(pkg => {
62-
const version = pkgJson.peerDependencies[pkg];
6392
if (pkg.includes('web-animations')) {
64-
addPackageToPkgJson(tree, pkg, version, dependencies);
93+
const version = pkgJson.peerDependencies[pkg];
94+
addPackageToPkgJson(tree, pkg, version, PackageTarget.REGULAR);
6595
logIncludingDependency(context, pkg, version);
6696
return;
6797
}
6898
});
6999

70-
addPackageToPkgJson(tree, schematicsPackage, pkgJson.igxDevDependencies[schematicsPackage], devDependencies);
100+
addPackageToPkgJson(tree, schematicsPackage, pkgJson.igxDevDependencies[schematicsPackage], PackageTarget.DEV);
71101
return tree;
72102
};
73103
}
@@ -102,13 +132,17 @@ export function getPropertyFromWorkspace(targetProp: string, workspace: any, cur
102132
return null;
103133
}
104134

105-
function includeDependencies(pkgJson: any, context: SchematicContext, tree: Tree, dependenciesKey: string) {
135+
function includeDependencies(pkgJson: any, context: SchematicContext, tree: Tree) {
106136
Object.keys(pkgJson.dependencies).forEach(pkg => {
107137
const version = pkgJson.dependencies[pkg];
138+
const entry = DEPENDENCIES_MAP.find(e => e.name === pkg);
139+
if (!entry || entry.target === PackageTarget.NONE) {
140+
return;
141+
}
108142
switch (pkg) {
109143
case 'hammerjs':
110144
logIncludingDependency(context, pkg, version);
111-
addPackageToPkgJson(tree, pkg, version, dependenciesKey);
145+
addPackageToPkgJson(tree, pkg, version, entry.target);
112146

113147
const workspace = getWorkspace(tree);
114148
const project = workspace.projects[workspace.defaultProject];
@@ -126,42 +160,13 @@ function includeDependencies(pkgJson: any, context: SchematicContext, tree: Tree
126160
break;
127161
default:
128162
logIncludingDependency(context, pkg, version);
129-
addPackageToPkgJson(tree, pkg, version, dependenciesKey);
163+
addPackageToPkgJson(tree, pkg, version, entry.target);
130164
break;
131165
}
132166
});
133167
}
134168

135-
/**
136-
* Add an item to an angular.json section, within the architect
137-
* @param workspace Angular Workspace Schema (angular.json)
138-
* @param key Architect tool key to add option to
139-
*/
140-
function addItemToAngularWorkspace(workspace: WorkspaceSchema, key: string, item: string): boolean {
141-
const currentProjectName = workspace.defaultProject;
142-
if (currentProjectName) {
143-
if (!workspace.projects[currentProjectName].architect) {
144-
workspace.projects[currentProjectName].architect = {};
145-
}
146-
if (!workspace.projects[currentProjectName].architect[key]) {
147-
workspace.projects[currentProjectName].architect[key] = {};
148-
}
149-
if (!workspace.projects[currentProjectName].architect[key].options) {
150-
workspace.projects[currentProjectName].architect[key].options = {};
151-
}
152-
if (!workspace.projects[currentProjectName].architect[key].options.scripts) {
153-
workspace.projects[currentProjectName].architect[key].options.scripts = [];
154-
}
155-
if (!workspace.projects[currentProjectName].architect[key].options.scripts.includes(item)) {
156-
workspace.projects[currentProjectName].architect[key].options.scripts.push(item);
157-
return true;
158-
}
159-
160-
return false;
161-
}
162-
}
163-
164-
function addPackageToPkgJson(tree: Tree, pkg: string, version: string, target: string): Tree {
169+
export function addPackageToPkgJson(tree: Tree, pkg: string, version: string, target: string): boolean {
165170
const targetFile = 'package.json';
166171
if (tree.exists(targetFile)) {
167172
const sourceText = tree.read(targetFile).toString();
@@ -179,7 +184,9 @@ function addPackageToPkgJson(tree: Tree, pkg: string, version: string, target: s
179184
.reduce((result, key) => (result[key] = json[target][key]) && result, {});
180185
tree.overwrite(targetFile, JSON.stringify(json, null, 2) + '\n');
181186
}
187+
188+
return true;
182189
}
183190

184-
return tree;
191+
return false;
185192
}

0 commit comments

Comments
 (0)