polymer-cli
Version:
A commandline tool for Polymer projects
215 lines • 10 kB
JavaScript
;
/**
* @license
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
// Be careful with these imports. As many as possible should be dynamic imports
// in the run method in order to minimize startup time from loading unused code.
const logging = require("plylog");
const polymer_project_config_1 = require("polymer-project-config");
const util_1 = require("../util");
const logger = logging.getLogger('cli.command.build');
// This flag is special because it doesn't necessarily trigger a one-off single
// build.
const autoBasePath = 'auto-base-path';
class BuildCommand {
constructor() {
this.name = 'build';
this.aliases = [];
this.description = 'Builds an application-style project';
this.args = [
{
name: 'name',
type: String,
description: 'The build name. Defaults to "default".',
},
{
name: 'preset',
type: String,
description: 'A preset configuration to base your build on. ' +
'User-defined options will override preset options. Optional. ' +
'Available presets: "es5-bundled", "es6-bundled", "es6-unbundled". '
},
{
name: 'js-compile',
type: Boolean,
description: 'Compile ES2015 JavaScript features down to ES5 for ' +
'older browsers.'
},
{
name: 'js-transform-modules-to-amd',
type: Boolean,
description: 'Transform ES modules to AMD modules.',
},
{
name: 'js-transform-import-meta',
type: Boolean,
description: 'Rewrite import.meta expressions to objects with inline URLs.',
},
{
name: 'js-minify',
type: Boolean,
description: 'Minify inlined and external JavaScript.'
},
{
name: 'css-minify',
type: Boolean,
description: 'Minify inlined and external CSS.'
},
{
name: 'html-minify',
type: Boolean,
description: 'Minify HTML by removing comments and whitespace.'
},
{
name: 'bundle',
type: Boolean,
description: 'Combine build source and dependency files together into ' +
'a minimum set of bundles. Useful for reducing the number of ' +
'requests needed to serve your application.'
},
{
name: 'add-service-worker',
type: Boolean,
description: 'Generate a service worker for your application to ' +
'cache all files and assets on the client.'
},
{
name: 'add-push-manifest',
type: Boolean,
description: 'Generate a push manifest for your application for http2' +
'push-enabled servers to read.'
},
{
name: 'sw-precache-config',
type: String,
description: 'Path to a file that exports configuration options for ' +
'the generated service worker. These options match those supported ' +
'by the sw-precache library. See ' +
'https://github.com/GoogleChrome/sw-precache#options-parameter ' +
'for a list of all supported options.'
},
{
name: 'insert-prefetch-links',
type: Boolean,
description: 'Add dependency prefetching by inserting ' +
'`<link rel="prefetch">` tags into entrypoint and ' +
'`<link rel="import">` tags into fragments and shell for all ' +
'dependencies.'
},
{
name: 'base-path',
type: String,
description: 'Updates the <base> tag if found in the entrypoint document.'
},
{
name: autoBasePath,
type: Boolean,
description: 'For all builds, set the entrypoint <base> tag to match ' +
'the build name. Does not necessarily trigger a one-off build.',
},
];
}
/**
* Converts command-line build arguments to the `ProjectBuildOptions` format
* that our build understands, applying the preset if one was given.
*/
commandOptionsToBuildOptions(options) {
const buildOptions = {};
const validBuildOptions = new Set(this.args.map(({ name }) => name));
// This flag is special. It affects the top-level config, not an individual
// build.
validBuildOptions.delete(autoBasePath);
for (const buildOption of Object.keys(options)) {
if (validBuildOptions.has(buildOption)) {
const [prefix, ...rest] = buildOption.split('-');
if (['css', 'html', 'js'].indexOf(prefix) !== -1) {
const option = util_1.dashToCamelCase(rest.join('-'));
// tslint:disable-next-line: no-any Scary and unsafe!
buildOptions[prefix] = buildOptions[prefix] || {};
// tslint:disable-next-line: no-any Scary and unsafe!
buildOptions[prefix][util_1.dashToCamelCase(option)] =
options[buildOption];
}
else {
// tslint:disable-next-line: no-any Scary and unsafe!
buildOptions[util_1.dashToCamelCase(buildOption)] =
options[buildOption];
}
}
}
if (options[autoBasePath]) {
buildOptions.basePath = true;
}
return polymer_project_config_1.applyBuildPreset(buildOptions);
}
run(options, config) {
return __awaiter(this, void 0, void 0, function* () {
// Defer dependency loading until this specific command is run
const del = yield Promise.resolve().then(() => require('del'));
const buildLib = yield Promise.resolve().then(() => require('../build/build'));
const polymerBuild = yield Promise.resolve().then(() => require('polymer-build'));
const path = yield Promise.resolve().then(() => require('path'));
let build = buildLib.build;
const mainBuildDirectoryName = buildLib.mainBuildDirectoryName;
// Validate our configuration and exit if a problem is found.
// Neccessary for a clean build.
config.validate();
// Support passing a custom build function via options.env
if (options['env'] && options['env'].build) {
logger.debug('build function passed in options, using that for build');
build = options['env'].build;
}
logger.info(`Clearing ${mainBuildDirectoryName}${path.sep} directory...`);
yield del([mainBuildDirectoryName]);
const mzfs = yield Promise.resolve().then(() => require('mz/fs'));
yield mzfs.mkdir(mainBuildDirectoryName);
const polymerProject = new polymerBuild.PolymerProject(config);
// If any the build command flags were passed as CLI arguments, generate
// a single build based on those flags alone.
const hasOneOffBuildArgumentPassed = this.args.some((arg) => {
return typeof options[arg.name] !== 'undefined' &&
arg.name !== autoBasePath;
});
if (hasOneOffBuildArgumentPassed) {
yield build(this.commandOptionsToBuildOptions(options), polymerProject);
return;
}
// If no build flags were passed but 1+ polymer.json build configuration(s)
// exist, generate a build for each configuration found.
if (config.builds) {
const promises = config.builds.map((buildOptions) => {
if (options[autoBasePath]) {
buildOptions.basePath = true;
}
return build(buildOptions, polymerProject);
});
promises.push(mzfs.writeFile(path.join(mainBuildDirectoryName, 'polymer.json'), config.toJSON()));
yield Promise.all(promises);
return;
}
// If no builds were defined, just generate a default build.
yield build({}, polymerProject);
});
}
}
exports.BuildCommand = BuildCommand;
//# sourceMappingURL=build.js.map