Skip to content

Commit 1b9a0bd

Browse files
authored
feat: add cordova-builders ng-add (#467)
1 parent cde97b7 commit 1b9a0bd

File tree

8 files changed

+2381
-3726
lines changed

8 files changed

+2381
-3726
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.DS_Store
2+
Thumbs.db
3+
UserInterfaceState.xcuserstate
4+
.env
15
node_modules
26
**/*.js
37
**/*.d.ts

package-lock.json

Lines changed: 2223 additions & 3726 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import type { Rule, Tree } from '@angular-devkit/schematics';
2+
import { chain, SchematicsException } from '@angular-devkit/schematics';
3+
import { getWorkspace } from '@schematics/angular/utility/workspace';
4+
5+
import { addArchitectBuilder, getDefaultAngularAppName } from './../utils/config';
6+
import type { Schema as AddOptions } from './schema';
7+
8+
function addCordovaBuilder(projectName: string): Rule {
9+
return (host: Tree) => {
10+
addArchitectBuilder(host, projectName, 'ionic-cordova-serve', {
11+
builder: '@ionic/cordova-builders:cordova-serve',
12+
options: {
13+
cordovaBuildTarget: `${projectName}:ionic-cordova-build`,
14+
devServerTarget: `${projectName}:serve`,
15+
},
16+
configurations: {
17+
production: {
18+
cordovaBuildTarget: `${projectName}:ionic-cordova-build:production`,
19+
devServerTarget: `${projectName}:serve:production`,
20+
},
21+
},
22+
});
23+
addArchitectBuilder(host, projectName, 'ionic-cordova-build', {
24+
builder: '@ionic/cordova-builders:cordova-build',
25+
options: {
26+
browserTarget: `${projectName}:build`,
27+
},
28+
configurations: {
29+
production: {
30+
browserTarget: `${projectName}:build:production`,
31+
},
32+
},
33+
});
34+
return host;
35+
};
36+
}
37+
38+
export default function ngAdd(options: AddOptions): Rule {
39+
return async (host: Tree) => {
40+
const workspace = await getWorkspace(host);
41+
if (!options.project) {
42+
options.project = getDefaultAngularAppName(workspace);
43+
}
44+
const project = workspace.projects.get(options.project);
45+
46+
if (!project || project.extensions.projectType !== 'application') {
47+
throw new SchematicsException(`Ionic Add requires a project type of "application".`);
48+
}
49+
50+
return chain([addCordovaBuilder(options.project)]);
51+
};
52+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface Schema {
2+
project?: string;
3+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"$id": "ionicNgAdd",
4+
"title": "Ionic Add options",
5+
"type": "object",
6+
"properties": {
7+
"project": {
8+
"type": "string",
9+
"description": "The name of the project.",
10+
"$default": {
11+
"$source": "projectName"
12+
}
13+
}
14+
},
15+
"required": []
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"ng-add": {
5+
"description": "Add Cordova builders to your project",
6+
"factory": "./add",
7+
"schema": "./add/schema.json"
8+
}
9+
}
10+
}

packages/cordova-builders/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"@angular-devkit/architect": "^0.1300.1",
3939
"@angular-devkit/build-angular": "^13.0.1",
4040
"@angular-devkit/core": "^13.0.1",
41+
"@angular-devkit/schematics": "^13.0.1",
42+
"@schematics/angular": "^13.0.1",
4143
"cheerio": "^1.0.0-rc.10",
4244
"colorette": "^2.0.16",
4345
"copy-webpack-plugin": "^9.0.1",
@@ -51,5 +53,6 @@
5153
"typescript": ">=4.4.2 <4.5"
5254
},
5355
"builders": "./builders.json",
56+
"schematics": "./collection.json",
5457
"gitHead": "35dbfaa5d93cb165387321a3f8a0f43e604f5d02"
5558
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type { Tree } from '@angular-devkit/schematics';
2+
import { SchematicsException } from '@angular-devkit/schematics';
3+
4+
const CONFIG_PATH = 'angular.json';
5+
6+
export function getDefaultAngularAppName(config: any): string {
7+
const projects = config.projects;
8+
const projectNames = Object.keys(projects);
9+
10+
for (const projectName of projectNames) {
11+
const projectConfig = projects[projectName];
12+
if (isAngularBrowserProject(projectConfig)) {
13+
return projectName;
14+
}
15+
}
16+
17+
return projectNames[0];
18+
}
19+
20+
export function addArchitectBuilder(
21+
host: Tree,
22+
projectName: string,
23+
builderName: string,
24+
builderOpts: any
25+
): void | never {
26+
const config = readConfig(host);
27+
const appConfig = getAngularAppConfig(config, projectName);
28+
appConfig.architect[builderName] = builderOpts;
29+
writeConfig(host, config);
30+
}
31+
32+
export function readConfig(host: Tree): any {
33+
const sourceText = host.read(CONFIG_PATH)?.toString('utf-8');
34+
if (!sourceText) {
35+
return;
36+
}
37+
return JSON.parse(sourceText);
38+
}
39+
40+
export function writeConfig(host: Tree, config: JSON): void {
41+
host.overwrite(CONFIG_PATH, JSON.stringify(config, null, 2));
42+
}
43+
44+
function isAngularBrowserProject(projectConfig: any): boolean {
45+
if (projectConfig.projectType === 'application') {
46+
const buildConfig = projectConfig.architect.build;
47+
return buildConfig.builder === '@angular-devkit/build-angular:browser';
48+
}
49+
50+
return false;
51+
}
52+
53+
export function getAngularAppConfig(config: any, projectName: string): any | never {
54+
// eslint-disable-next-line no-prototype-builtins
55+
if (!config.projects.hasOwnProperty(projectName)) {
56+
throw new SchematicsException(`Could not find project: ${projectName}`);
57+
}
58+
59+
const projectConfig = config.projects[projectName];
60+
if (isAngularBrowserProject(projectConfig)) {
61+
return projectConfig;
62+
}
63+
64+
if (config.projectType !== 'application') {
65+
throw new SchematicsException(`Invalid projectType for ${projectName}: ${config.projectType}`);
66+
} else {
67+
const buildConfig = projectConfig.architect.build;
68+
throw new SchematicsException(`Invalid builder for ${projectName}: ${buildConfig.builder}`);
69+
}
70+
}

0 commit comments

Comments
 (0)