Skip to content

Commit b176cbe

Browse files
committed
feat(schematics): ng-add basic integration
1 parent 973dbf9 commit b176cbe

File tree

15 files changed

+417
-9
lines changed

15 files changed

+417
-9
lines changed

package.json

+9-4
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,30 @@
99
"lib": "ng",
1010
"watch:lib:dev": "ng build coreui-angular --watch --configuration production",
1111
"build:lib:prod": "ng build coreui-angular",
12+
"postbuild:lib:prod": "npm run build --prefix projects/coreui-angular",
1213
"test:lib:dev": "ng test coreui-angular",
1314
"test:lib:prod": "ng test coreui-angular --karma-config=projects/coreui-angular/karma.conf.github.js",
14-
"prepublish:lib": "npm run prepublish:icons && ng lint coreui-angular && ng test coreui-angular --watch=false && ng build coreui-angular",
15+
"prepublish:lib": "npm run prepublish:icons && ng lint coreui-angular && ng test coreui-angular --watch=false && npm run build:lib:prod",
1516
"publish:lib": "cd dist/coreui-angular/ && npm publish --tag next --dry-run",
1617
"lint:lib": "ng lint coreui-angular",
1718
"link:lib": "cd dist/coreui-angular/ && npm link",
1819
"chartjs": "ng",
1920
"watch:chartjs:dev": "ng build coreui-angular-chartjs --watch --configuration development",
2021
"build:chartjs:prod": "ng build coreui-angular-chartjs",
22+
"postbuild:chartjs:prod": "npm run build --prefix projects/coreui-angular-chartjs",
2123
"test:chartjs:dev": "ng test coreui-angular-chartjs",
2224
"test:chartjs:prod": "ng test coreui-angular-chartjs --karma-config=projects/coreui-angular-chartjs/karma.conf.github.js",
23-
"prepublish:chartjs": "ng lint coreui-angular-chartjs && ng test coreui-angular-chartjs --watch=false && ng build coreui-angular-chartjs",
25+
"prepublish:chartjs": "ng lint coreui-angular-chartjs && ng test coreui-angular-chartjs --watch=false && npm run build:chartjs:prod",
2426
"publish:chartjs": "cd dist/coreui-angular-chartjs/ && npm publish --tag next --dry-run",
2527
"lint:chartjs": "ng lint coreui-angular-chartjs",
2628
"link:chartjs": "cd dist/coreui-angular-chartjs/ && npm link",
2729
"icons": "ng",
2830
"watch:icons:dev": "ng build coreui-icons-angular --watch --configuration production",
2931
"build:icons:prod": "ng build coreui-icons-angular",
32+
"postbuild:icons:prod": "npm run build --prefix projects/coreui-icons-angular",
3033
"test:icons:dev": "ng test coreui-icons-angular",
3134
"test:icons:prod": "ng test coreui-icons-angular --karma-config=projects/coreui-icons-angular/karma.conf.github.js",
32-
"prepublish:icons": "ng lint coreui-icons-angular && ng test coreui-icons-angular --watch=false && ng build coreui-icons-angular",
35+
"prepublish:icons": "ng lint coreui-icons-angular && ng test coreui-icons-angular --watch=false && npm run build:icons:prod",
3336
"publish:icons": "cd dist/coreui-icons-angular/ && npm publish --tag next --dry-run",
3437
"lint:icons": "ng lint coreui-icons-angular",
3538
"link:icons": "cd dist/coreui-icons-angular/ && npm link"
@@ -57,6 +60,7 @@
5760
},
5861
"devDependencies": {
5962
"@angular-devkit/build-angular": "^18.1.1",
63+
"@angular-devkit/schematics": "^18.1.1",
6064
"@angular-eslint/builder": "18.1.0",
6165
"@angular-eslint/eslint-plugin": "18.1.0",
6266
"@angular-eslint/eslint-plugin-template": "18.1.0",
@@ -70,6 +74,7 @@
7074
"@types/node": "^20.14.11",
7175
"@typescript-eslint/eslint-plugin": "^7.17.0",
7276
"@typescript-eslint/parser": "^7.17.0",
77+
"copyfiles": "^2.4.1",
7378
"eslint": "^8.57.0",
7479
"jasmine-core": "^5.2.0",
7580
"karma": "^6.4.3",
@@ -105,7 +110,7 @@
105110
"version_short": "5.2"
106111
},
107112
"engines": {
108-
"node": "^18.19.0 || ^20.9.0",
113+
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
109114
"npm": ">=9"
110115
}
111116
}

projects/coreui-angular-chartjs/package.json

+13-1
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,17 @@
4141
"component",
4242
"chartjs",
4343
"angular"
44-
]
44+
],
45+
"devDependencies": {
46+
"copyfiles": "file:../../node_modules/copyfiles",
47+
"typescript": "file:../../node_modules/typescript"
48+
},
49+
"schematics": "./schematics/collection.json",
50+
"scripts": {
51+
"build": "tsc -p tsconfig.schematics.json",
52+
"postbuild": "copyfiles schematics/*/files/** schematics/collection.json ../../dist/coreui-angular-chartjs/"
53+
},
54+
"ng-add": {
55+
"save": true
56+
}
4557
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"ng-add": {
5+
"description": "Add @coreui/angular-chartjs library to the project.",
6+
"factory": "./ng-add/index#ngAdd"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { chain, Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
2+
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
3+
import { addPackageToPackageJson, getPackageVersionFromPackageJson, PackageJson } from './package-config';
4+
import * as pkgJson from '../../package.json';
5+
6+
export function addCoreUIAngularChartJs(): Rule {
7+
return (tree: Tree, context: SchematicContext) => {
8+
context.logger.info('Installing @coreui/angular-chartjs ...');
9+
context.addTask(new NodePackageInstallTask());
10+
return tree;
11+
};
12+
}
13+
14+
export function ngAdd(): Rule {
15+
return (tree: Tree, context: SchematicContext) => {
16+
context.logger.info(``);
17+
context.logger.info('Installing @coreui/angular-chartjs dependencies...');
18+
const ngCoreVersionTag = getPackageVersionFromPackageJson(tree, '@angular/core');
19+
context.logger.info(`@angular/core version ${ngCoreVersionTag}`);
20+
if (!ngCoreVersionTag) {
21+
throw new SchematicsException('@angular/core version not found');
22+
}
23+
const pkg = pkgJson as PackageJson;
24+
const libPeerDeps: string[] = ['@coreui/chartjs', 'chart.js'];
25+
libPeerDeps.forEach((dep: string) => {
26+
const version = pkg.peerDependencies[dep];
27+
context.logger.info(`Including ${dep} version ${version}`);
28+
addPackageToPackageJson(tree, dep, version);
29+
});
30+
const libDeps: string[] = ['lodash-es'];
31+
libDeps.forEach((dep: string) => {
32+
const version = pkg.dependencies[dep];
33+
context.logger.info(`Including ${dep} version ${version}`);
34+
addPackageToPackageJson(tree, dep, version);
35+
});
36+
37+
return chain([addCoreUIAngularChartJs()]);
38+
};
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import { Tree } from '@angular-devkit/schematics';
10+
11+
export interface PackageJson {
12+
dependencies: Record<string, string>;
13+
peerDependencies: Record<string, string>;
14+
}
15+
16+
/**
17+
* Sorts the keys of the given object.
18+
* @returns A new object instance with sorted keys
19+
*/
20+
function sortObjectByKeys(obj: Record<string, string>) {
21+
return Object.keys(obj)
22+
.sort()
23+
.reduce(
24+
(result, key) => {
25+
result[key] = obj[key];
26+
return result;
27+
},
28+
{} as Record<string, string>
29+
);
30+
}
31+
32+
/** Adds a package to the package.json in the given host tree. */
33+
export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree {
34+
if (host.exists('package.json')) {
35+
const sourceText = host.read('package.json')!.toString('utf-8');
36+
const json = JSON.parse(sourceText) as PackageJson;
37+
38+
if (!json.dependencies) {
39+
json.dependencies = {};
40+
}
41+
42+
if (!json.dependencies[pkg]) {
43+
json.dependencies[pkg] = version;
44+
json.dependencies = sortObjectByKeys(json.dependencies);
45+
}
46+
47+
host.overwrite('package.json', JSON.stringify(json, null, 2));
48+
}
49+
50+
return host;
51+
}
52+
53+
/** Gets the version of the specified package by looking at the package.json in the given tree. */
54+
export function getPackageVersionFromPackageJson(tree: Tree, name: string): string | null {
55+
if (!tree.exists('package.json')) {
56+
return null;
57+
}
58+
59+
const packageJson = JSON.parse(tree.read('package.json')!.toString('utf8')) as PackageJson;
60+
61+
if (packageJson.dependencies && packageJson.dependencies[name]) {
62+
return packageJson.dependencies[name];
63+
}
64+
65+
return null;
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"lib": [
5+
"ES2022",
6+
"dom"
7+
],
8+
"declaration": true,
9+
"module": "commonjs",
10+
"moduleResolution": "node",
11+
"noEmitOnError": true,
12+
"noFallthroughCasesInSwitch": true,
13+
"noImplicitAny": true,
14+
"noImplicitThis": true,
15+
"noUnusedParameters": true,
16+
"noUnusedLocals": true,
17+
"rootDir": "schematics",
18+
"outDir": "../../dist/coreui-angular-chartjs/schematics",
19+
"resolveJsonModule": true,
20+
"skipDefaultLibCheck": true,
21+
"skipLibCheck": true,
22+
"sourceMap": true,
23+
"strictNullChecks": true,
24+
"target": "ES2022",
25+
"types": [
26+
"jasmine",
27+
"node"
28+
]
29+
},
30+
"include": [
31+
"schematics/**/*"
32+
],
33+
"exclude": [
34+
"schematics/*/files/**/*"
35+
]
36+
}

projects/coreui-angular/package.json

+15-3
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"@angular/common": "^18.1.0",
2929
"@angular/core": "^18.1.0",
3030
"@angular/router": "^18.1.0",
31-
"@coreui/coreui": "^5.0.0",
32-
"@coreui/icons-angular": "~5.2.0",
31+
"@coreui/coreui": "^5.1.0",
32+
"@coreui/icons-angular": "~5.2.8",
3333
"rxjs": "^7.8.1"
3434
},
3535
"repository": {
@@ -49,5 +49,17 @@
4949
"component",
5050
"components"
5151
],
52-
"eslintConfig": {}
52+
"eslintConfig": {},
53+
"devDependencies": {
54+
"copyfiles": "file:../../node_modules/copyfiles",
55+
"typescript": "file:../../node_modules/typescript"
56+
},
57+
"schematics": "./schematics/collection.json",
58+
"scripts": {
59+
"build": "tsc -p tsconfig.schematics.json",
60+
"postbuild": "copyfiles schematics/*/files/** schematics/collection.json ../../dist/coreui-angular/"
61+
},
62+
"ng-add": {
63+
"save": true
64+
}
5365
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"ng-add": {
5+
"description": "Add @coreui/angular library to the project.",
6+
"factory": "./ng-add/index#ngAdd"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { chain, Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
2+
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
3+
import { addPackageToPackageJson, getPackageVersionFromPackageJson, PackageJson } from './package-config';
4+
import * as pkgJson from '../../package.json';
5+
6+
const addCoreUIIconsAngular = (): Rule => {
7+
return (tree: Tree, context: SchematicContext) => {
8+
context.logger.info(`Installing @coreui/icons-angular as dependency`);
9+
context.addTask(new NodePackageInstallTask({ packageName: '@coreui/icons-angular' }));
10+
return tree;
11+
};
12+
};
13+
14+
const addCoreUIAngular = (): Rule => {
15+
return (tree: Tree, context: SchematicContext) => {
16+
context.logger.info(`Installing @coreui/angular as dependency`);
17+
context.addTask(new NodePackageInstallTask());
18+
return tree;
19+
};
20+
};
21+
22+
export function ngAdd(): Rule {
23+
return (tree: Tree, context: SchematicContext) => {
24+
context.logger.info(``);
25+
context.logger.info('Installing @coreui/angular dependencies...');
26+
const ngCoreVersionTag = getPackageVersionFromPackageJson(tree, '@angular/core');
27+
context.logger.info(`@angular/core version ${ngCoreVersionTag}`);
28+
if (!ngCoreVersionTag) {
29+
throw new SchematicsException('@angular/core version not found');
30+
}
31+
const projDeps = ['@angular/animations', '@angular/common', '@angular/core', '@angular/router'];
32+
projDeps.forEach((dep) => {
33+
addPackageToPackageJson(tree, dep, ngCoreVersionTag);
34+
});
35+
36+
const pkg = pkgJson as PackageJson;
37+
const libPeerDeps: string[] = ['@angular/cdk', '@coreui/coreui'];
38+
libPeerDeps.forEach((dep: string) => {
39+
const version = pkg.peerDependencies[dep];
40+
context.logger.info(`Including ${dep} version ${version}`);
41+
addPackageToPackageJson(tree, dep, version);
42+
});
43+
const libDeps: string[] = ['@popperjs/core'];
44+
libDeps.forEach((dep: string) => {
45+
const version = pkg.dependencies[dep];
46+
context.logger.info(`Including ${dep} version ${version}`);
47+
addPackageToPackageJson(tree, dep, version);
48+
});
49+
50+
return chain([addCoreUIIconsAngular(), addCoreUIAngular()]);
51+
};
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import { Tree } from '@angular-devkit/schematics';
10+
11+
export interface PackageJson {
12+
dependencies: Record<string, string>;
13+
peerDependencies: Record<string, string>;
14+
}
15+
16+
/**
17+
* Sorts the keys of the given object.
18+
* @returns A new object instance with sorted keys
19+
*/
20+
function sortObjectByKeys(obj: Record<string, string>) {
21+
return Object.keys(obj)
22+
.sort()
23+
.reduce(
24+
(result, key) => {
25+
result[key] = obj[key];
26+
return result;
27+
},
28+
{} as Record<string, string>
29+
);
30+
}
31+
32+
/** Adds a package to the package.json in the given host tree. */
33+
export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree {
34+
if (host.exists('package.json')) {
35+
const sourceText = host.read('package.json')!.toString('utf-8');
36+
const json = JSON.parse(sourceText) as PackageJson;
37+
38+
if (!json.dependencies) {
39+
json.dependencies = {};
40+
}
41+
42+
if (!json.dependencies[pkg]) {
43+
json.dependencies[pkg] = version;
44+
json.dependencies = sortObjectByKeys(json.dependencies);
45+
}
46+
47+
host.overwrite('package.json', JSON.stringify(json, null, 2));
48+
}
49+
50+
return host;
51+
}
52+
53+
/** Gets the version of the specified package by looking at the package.json in the given tree. */
54+
export function getPackageVersionFromPackageJson(tree: Tree, name: string): string | null {
55+
if (!tree.exists('package.json')) {
56+
return null;
57+
}
58+
59+
const packageJson = JSON.parse(tree.read('package.json')!.toString('utf8')) as PackageJson;
60+
61+
if (packageJson.dependencies && packageJson.dependencies[name]) {
62+
return packageJson.dependencies[name];
63+
}
64+
65+
return null;
66+
}

0 commit comments

Comments
 (0)