Skip to content
5 changes: 3 additions & 2 deletions packages/cli/src/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ export const globalArguments: ArgDescriptor[] = [
{
name: 'npm',
type: Boolean,
description: 'Sets npm mode: component directory is "node_modules" ' +
'and the package name is read from package.json',
description: 'Sets npm mode: dependencies are installed from npm, ' +
'component directory is "node_modules" and the package name is read ' +
'from package.json',
},
{
name: 'module-resolution',
Expand Down
15 changes: 11 additions & 4 deletions packages/cli/src/commands/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,34 @@ export class InstallCommand implements Command {
aliases = ['i'];

// TODO(justinfagnani): Expand and link to eventual doc on variants.
description = 'installs Bower dependencies, optionally installing "variants"';
description = 'Installs project dependencies from npm or Bower (optionally ' +
'installing "variants").';

args = [
{
name: 'variants',
type: Boolean,
defaultValue: false,
description: 'Whether to install variants'
description: 'Whether to install Bower variants'
},
{
name: 'offline',
type: Boolean,
defaultValue: false,
description: 'Don\'t hit the network'
description: 'Don\'t hit the network when installing Bower dependencies'
},
];

async run(options: CommandOptions, _config: ProjectConfig): Promise<void> {
async run(options: CommandOptions, config: ProjectConfig): Promise<void> {
// Defer dependency loading until this specific command is run
const install =
require('../install/install').install as typeof installTypeOnly;

// Use `npm` from the config, if available and not passed as a CLI arg.
if (options.npm === undefined && config.npm !== undefined) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really do this in a unified place

options.npm = config.npm;
}

await install(options);
}
}
29 changes: 22 additions & 7 deletions packages/cli/src/install/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@

import * as bower from 'bower';
import {read as readBowerJson} from 'bower-json';
import * as child_process from 'child_process';
import * as path from 'path';
import * as logging from 'plylog';
import * as util from 'util';

import defaultBowerConfig = require('bower/lib/config');
import BowerLogger = require('bower-logger');
import StandardRenderer = require('bower/lib/renderers/StandardRenderer');
import BowerProject = require('bower/lib/core/Project');

const exec = util.promisify(child_process.exec);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sadly not available in node 6, we just aren't running node 6 integration tests currently (see #136)

const logger = logging.getLogger('cli.install');

type JsonValue = string|number|boolean|null|JsonObject|JsonArray;
Expand All @@ -35,25 +38,37 @@ interface JsonArray extends Array<JsonValue> {}
export interface Options {
variants?: boolean;
offline?: boolean;
npm?: boolean;
}

export async function install(options?: Options): Promise<void> {
if (options && options.npm) {
await npmInstall();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Equivalent and simpler: return npmInstall()

return;
}

// default to false
const offline = options == null ? false : options.offline === true;
// default to false
const variants = options == null ? false : options.variants === true;

await Promise.all([
installDefault(offline),
variants ? installVariants(offline) : Promise.resolve(),
bowerInstallDefault(offline),
variants ? bowerInstallVariants(offline) : Promise.resolve(),
]);
}

async function npmInstall() {
logger.info('Installing npm dependencies...');
await exec('npm install', {cwd: process.cwd()});
logger.info('Finished installing npm dependencies.');
}

/**
* Performs a Bower install, optionally with a specific JSON configuration and
* output directory.
*/
async function _install(
async function _bowerInstall(
offline: boolean,
bowerJson?: JsonObject,
componentDirectory?: string,
Expand Down Expand Up @@ -90,13 +105,13 @@ async function _install(
await project.install([], {save: false, offline}, config);
}

async function installDefault(offline: boolean): Promise<void> {
async function bowerInstallDefault(offline: boolean): Promise<void> {
logger.info(`Installing default Bower components...`);
await _install(offline);
await _bowerInstall(offline);
logger.info(`Finished installing default Bower components`);
}

async function installVariants(offline: boolean): Promise<void> {
async function bowerInstallVariants(offline: boolean): Promise<void> {
const bowerJson = await new Promise<any>((resolve, reject) => {
const config = defaultBowerConfig({
save: false,
Expand All @@ -120,7 +135,7 @@ async function installVariants(offline: boolean): Promise<void> {
const variantDirectory = `bower_components-${variantName}`;
logger.info(
`Installing variant ${variantName} to ${variantDirectory}...`);
await _install(offline, variantBowerJson, variantDirectory, variantName);
await _bowerInstall(offline, variantBowerJson, variantDirectory, variantName);
logger.info(`Finished installing variant ${variantName}`);
}));
}
Expand Down
7 changes: 1 addition & 6 deletions packages/cli/src/test/integration/integration_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ import {createApplicationGenerator} from '../../init/application/application';
import {runCommand} from './run-command';
import {createElementGenerator} from '../../init/element/element';
import {createGithubGenerator} from '../../init/github';
import * as child_process from 'child_process';
import * as util from 'util';
const exec = util.promisify(child_process.exec);

// A zero priveledge github token of a nonce account, used for quota.
const githubToken = '8d8622bf09bb1d85cb411b5e475a35e742a7ce35';
Expand All @@ -42,9 +39,7 @@ suite('integration tests', function() {
await runGenerator(createElementGenerator('polymer-3.x'))
.withPrompts({name: 'my-element'}) // Mock the prompt answers
.toPromise();
// TODO(#118): Use `polymer install` once it supports installing npm
// packages.
await exec('npm install', {cwd: dir});
await runCommand(binPath, ['install'], {cwd: dir});

// TODO(#130): Add this back in when `polymer lint` has a Polymer 3
// option.
Expand Down