Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat new builder #132

Merged
merged 11 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading