Skip to content

Commit

Permalink
feat(): support Angular 8 (#132)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: this updates dependencies for Angular 8. Users are
    required to update to 8.0.0 of Angular/Angular CLI in order to use
    this. In order to migrate, please see https://update.angular.io
  • Loading branch information
mhartington committed Jun 25, 2019
1 parent a7e6bf4 commit 166d547
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 192 deletions.
6 changes: 4 additions & 2 deletions builders.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{
"builders": {
"cordova-build": {
"class": "./builders/cordova-build",
"implementation": "./builders/cordova-build/index",
"schema": "./builders/cordova-build/schema.json",
"description": "Perform a browser build with Cordova assets."
},


"cordova-serve": {
"class": "./builders/cordova-serve",
"implementation": "./builders/cordova-serve/index",
"schema": "./builders/cordova-serve/schema.json",
"description": "Run the dev-server with Cordova assets."
}
Expand Down
124 changes: 20 additions & 104 deletions builders/cordova-build/index.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,25 @@
import { BuildEvent, Builder, BuilderConfiguration, BuilderContext, BuilderDescription } from '@angular-devkit/architect';
import { BrowserBuilderSchema } from '@angular-devkit/build-angular/src/browser/schema';
import { getSystemPath, join, normalize } from '@angular-devkit/core';
import { writeFileSync } from 'fs';
import { Observable, of } from 'rxjs';
import { concatMap, tap } from 'rxjs/operators';
import { BuilderContext, createBuilder, targetFromTargetString } from '@angular-devkit/architect';
import { json } from '@angular-devkit/core';

import { CordovaBuildBuilderSchema } from './schema';

export { CordovaBuildBuilderSchema };

export class CordovaBuildBuilder implements Builder<CordovaBuildBuilderSchema> {
constructor(public context: BuilderContext) {}

run(builderConfig: BuilderConfiguration<CordovaBuildBuilderSchema>): Observable<BuildEvent> {
const [ project, target, configuration ] = builderConfig.options.browserTarget.split(':');
const browserTargetSpec = { project, target, configuration, overrides: {} };

let browserConfig = this.context.architect.getBuilderConfiguration<BrowserBuilderSchema>(browserTargetSpec);
let browserDescription: BuilderDescription;

return of(null).pipe(
concatMap(() => this.context.architect.getBuilderDescription(browserConfig)),
tap(description => browserDescription = description),
concatMap(() => this.context.architect.validateBuilderOptions(browserConfig, browserDescription)),
tap(config => browserConfig = config),
tap(() => this.validateBuilderConfig(builderConfig.options)),
tap(() => this.prepareBrowserConfig(builderConfig.options, browserConfig.options)),
concatMap(() => of(this.context.architect.getBuilder(browserDescription, this.context))),
concatMap(builder => builder.run(browserConfig))
);
}

// Mutates builderOptions
validateBuilderConfig(builderOptions: CordovaBuildBuilderSchema) {
// if we're mocking cordova.js, don't build cordova bundle
if (builderOptions.cordovaMock) {
builderOptions.cordovaAssets = false;
}

if (builderOptions.cordovaAssets && !builderOptions.platform) {
throw new Error('The `--platform` option is required with `--cordova-assets`');
}
}

// Mutates browserOptions
prepareBrowserConfig(options: CordovaBuildBuilderSchema, browserOptions: BrowserBuilderSchema) {
const cordovaBasePath = normalize(options.cordovaBasePath ? options.cordovaBasePath : '.');
import { prepareBrowserConfig, validateBuilderConfig } from '../utils';

if (typeof options.sourceMap !== 'undefined') {
browserOptions.sourceMap = options.sourceMap;
}

// We always need to output the build to `www` because it is a hard
// requirement of Cordova.
browserOptions.outputPath = join(cordovaBasePath, normalize('www'));

// Cordova CLI will error if `www` is missing. The Angular CLI deletes it
// by default. Let's keep it around.
browserOptions.deleteOutputPath = false;

if (options.consolelogs) {
// Write the config to a file, and then include that in the bundle so it loads on window
const configPath = getSystemPath(join(normalize(__dirname), '../../assets', normalize('consolelog-config.js')));
writeFileSync(configPath, `window.Ionic = window.Ionic || {}; Ionic.ConsoleLogServerConfig = { wsPort: ${options.consolelogsPort} }`);

browserOptions.scripts.push({
input: configPath,
bundleName: 'consolelogs',
lazy: false,
});

browserOptions.scripts.push({
input: getSystemPath(join(normalize(__dirname), '../../assets', normalize('consolelogs.js'))),
bundleName: 'consolelogs',
lazy: false,
});
}

if (options.cordovaMock) {
browserOptions.scripts.push({
input: getSystemPath(join(normalize(__dirname), '../../assets', normalize('cordova.js'))),
bundleName: 'cordova',
lazy: false,
});
} else if (options.cordovaAssets) {
const platformWWWPath = join(cordovaBasePath, normalize(`platforms/${options.platform}/platform_www`));

// Add Cordova www assets that were generated whenever platform(s) and
// plugin(s) are added. This includes `cordova.js`,
// `cordova_plugins.js`, and all plugin JS.
browserOptions.assets.push({
glob: '**/*',
input: getSystemPath(platformWWWPath),
output: './',
});
import { CordovaBuildBuilderSchema } from './schema';

// Register `cordova.js` as a global script so it is included in
// `index.html`.
browserOptions.scripts.push({
input: getSystemPath(join(platformWWWPath, normalize('cordova.js'))),
bundleName: 'cordova',
lazy: false,
});
}
}
export async function buildCordova(
options: CordovaBuildBuilderSchema,
context: BuilderContext
) {
context.reportStatus(`running cordova build...`);
// Get angular browser build target
const browserTargetSpec = targetFromTargetString(options.browserTarget);
// Get browser build options
const browserBuildTargetOptions = await context.getTargetOptions(browserTargetSpec);

const formattedOptions = validateBuilderConfig(options);
const newOptions = prepareBrowserConfig(formattedOptions, browserBuildTargetOptions);

const browserBuild = await context.scheduleTarget(browserTargetSpec, newOptions);
return browserBuild.result;
}

export default CordovaBuildBuilder;
export default createBuilder<json.JsonObject & CordovaBuildBuilderSchema>(buildCordova);
96 changes: 28 additions & 68 deletions builders/cordova-serve/index.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,42 @@
import { BuildEvent, Builder, BuilderConfiguration, BuilderContext, BuilderDescription } from '@angular-devkit/architect';
import { NormalizedBrowserBuilderSchema } from '@angular-devkit/build-angular/src/browser/schema';
import { DevServerBuilder, DevServerBuilderOptions } from '@angular-devkit/build-angular/src/dev-server';
import { Path, virtualFs } from '@angular-devkit/core';
import * as fs from 'fs';
import { Observable, from, of } from 'rxjs';
import { concatMap, tap } from 'rxjs/operators';
import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString } from '@angular-devkit/architect';
import { json } from '@angular-devkit/core';

import { CordovaBuildBuilder, CordovaBuildBuilderSchema } from '../cordova-build';
import { prepareBrowserConfig } from '../utils';

import { createConsoleLogServer } from './log-server';
import { CordovaServeBuilderSchema } from './schema';

export class CordovaServeBuilder implements Builder<CordovaServeBuilderSchema> {
constructor(public context: BuilderContext) {}
export type CordovaDevServerBuilderOptions = CordovaServeBuilderSchema & json.JsonObject;

run(builderConfig: BuilderConfiguration<CordovaServeBuilderSchema>): Observable<BuildEvent> {
const { options: cordovaServeOptions } = builderConfig;
const { devServerTarget, port, host, ssl } = cordovaServeOptions;
const [ project, target, configuration ] = devServerTarget.split(':');
export async function serveCordova(
options: CordovaServeBuilderSchema,
context: BuilderContext
): Promise<BuilderOutput> {
return new Promise(async () => {
context.reportStatus(`running cordova serve...`);
const { devServerTarget, cordovaBuildTarget, port, host, ssl } = options;

const devServerTargetSpec = { project, target, configuration, overrides: { port, host, ssl } };
const devServerBuilderConfig = this.context.architect.getBuilderConfiguration<DevServerBuilderOptions>(devServerTargetSpec);
// Getting the original browser build options
const cordovaBuildTargetSpec = targetFromTargetString(cordovaBuildTarget);
const cordovaBuildTargetOptions = await context.getTargetOptions(cordovaBuildTargetSpec) as { browserTarget: string };
const browserBuildTargetSpec = targetFromTargetString(cordovaBuildTargetOptions.browserTarget);

let devServerDescription: BuilderDescription;
let cordovaBuildConfig: BuilderConfiguration<CordovaBuildBuilderSchema>;
// What we actually need....
const browserBuildTargetOptions = await context.getTargetOptions(browserBuildTargetSpec);

return of(null).pipe(
concatMap(() => this.context.architect.getBuilderDescription(devServerBuilderConfig)),
tap(description => devServerDescription = description),
concatMap(() => this.context.architect.validateBuilderOptions(devServerBuilderConfig, devServerDescription)),
concatMap(() => this._getCordovaBuildConfig(cordovaServeOptions)),
tap(config => cordovaBuildConfig = config),
concatMap(() => of(new CordovaDevServerBuilder(this.context, cordovaBuildConfig.options))),
concatMap(builder => builder.run(devServerBuilderConfig))
);
}
// Modifying those options to pass in cordova-speicfic stuff
prepareBrowserConfig(options, browserBuildTargetOptions);

protected _getCordovaBuildConfig(cordovaServeOptions: CordovaServeBuilderSchema): Observable<BuilderConfiguration<CordovaBuildBuilderSchema>> {
const {
platform,
cordovaBasePath,
cordovaAssets,
cordovaMock,
consolelogs,
consolelogsPort,
sourceMap,
} = cordovaServeOptions;

const [ project, target, configuration ] = cordovaServeOptions.cordovaBuildTarget.split(':');
const cordovaBuildTargetSpec = { project, target, configuration, overrides: { platform, cordovaBasePath, cordovaAssets, cordovaMock, consolelogs, consolelogsPort, sourceMap } };
const cordovaBuildTargetConfig = this.context.architect.getBuilderConfiguration<CordovaBuildBuilderSchema>(cordovaBuildTargetSpec);

return this.context.architect.getBuilderDescription(cordovaBuildTargetConfig).pipe(
concatMap(cordovaBuildDescription => this.context.architect.validateBuilderOptions(cordovaBuildTargetConfig, cordovaBuildDescription))
);
}
}

class CordovaDevServerBuilder extends DevServerBuilder {
constructor(context: BuilderContext, public cordovaBuildOptions: CordovaBuildBuilderSchema) {
super(context);
}

run(builderConfig: BuilderConfiguration<DevServerBuilderOptions>): Observable<BuildEvent> {
if (this.cordovaBuildOptions.consolelogs && this.cordovaBuildOptions.consolelogsPort) {
return from(createConsoleLogServer(builderConfig.options.host, this.cordovaBuildOptions.consolelogsPort))
.pipe(_ => super.run(builderConfig));
if (options.consolelogs && options.consolelogsPort) {
await createConsoleLogServer(host, options.consolelogsPort);
}
return super.run(builderConfig);
}

buildWebpackConfig(root: Path, projectRoot: Path, host: virtualFs.Host<fs.Stats>, browserOptions: NormalizedBrowserBuilderSchema) {
const builder = new CordovaBuildBuilder(this.context);
builder.validateBuilderConfig(this.cordovaBuildOptions);
builder.prepareBrowserConfig(this.cordovaBuildOptions, browserOptions);
const devServerTargetSpec = targetFromTargetString(devServerTarget);
const devServerTargetOptions = await context.getTargetOptions(devServerTargetSpec);

return super.buildWebpackConfig(root, projectRoot, host, browserOptions);
}
return context
.scheduleTarget(devServerTargetSpec, { host, port, ssl }, devServerTargetOptions)
.then(buildEvent => ({ ...buildEvent }));
});
}

export default CordovaServeBuilder;
export default createBuilder<CordovaDevServerBuilderOptions, any>(serveCordova);
1 change: 0 additions & 1 deletion builders/cordova-serve/log-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export async function createConsoleLogServer(host: string, port: number): Promis

// pretty print objects and arrays (no newlines for arrays)
msg.data = msg.data.map(d => JSON.stringify(d, undefined, d && d.length ? '' : ' '));

if (status) {
process.stdout.write(`[${status('console.' + msg.type)}]: ${msg.data.join(' ')}\n`);
} else {
Expand Down
6 changes: 3 additions & 3 deletions builders/cordova-serve/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ export interface CordovaServeBuilderSchema {
cordovaBuildTarget: string;
devServerTarget: string;
platform?: string;
port?: number;
host?: string;
ssl?: boolean;
port: number;
host: string;
ssl: boolean;
cordovaBasePath?: string;
sourceMap?: boolean;
cordovaAssets?: boolean;
Expand Down

0 comments on commit 166d547

Please sign in to comment.