-
Notifications
You must be signed in to change notification settings - Fork 12k
feat(install): 1. and 3. phase from design docs #294
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
Changes from all commits
b2dbad8
d21635f
ef3334f
33833b8
de3c89b
d00177c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
addon/ng2/blueprints/ng2/files/src/config/system.config.js | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,6 @@ | |
"ts-node": "^0.5.5", | ||
"tslint": "^3.6.0", | ||
"typescript": "^1.8.7", | ||
"typings": "^0.6.6" | ||
"typings": "^0.7.7" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
System.config({ | ||
"packages": { | ||
"app": { | ||
"format": "register", | ||
"defaultExtension": "js" | ||
} | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as Command from 'ember-cli/lib/models/command'; | ||
import * as SlientError from 'silent-error'; | ||
import * as InstallTask from '../tasks/install'; | ||
|
||
module.exports = Command.extend({ | ||
name: 'install', | ||
description: 'Adds 3rd party library to existing project', | ||
works: 'insideProject', | ||
|
||
run: function (commandOptions, rawArgs) { | ||
if (!rawArgs.length) { | ||
const msg = 'The `ng install` command must take an argument with ' + | ||
'a package name.'; | ||
|
||
return Promise.reject(new SilentError(msg)); | ||
} | ||
|
||
const installTask = new InstallTask({ | ||
ui: this.ui, | ||
analytics: this.analytics, | ||
project: this.project | ||
}); | ||
|
||
return installTask.run({ | ||
packages: rawArgs | ||
}); | ||
} | ||
}); | ||
|
||
module.exports.overrideCore = true; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as Command from 'ember-cli/lib/models/command'; | ||
import * as SilentError from 'silent-error'; | ||
import * as UninstallTask from '../tasks/uninstall'; | ||
|
||
module.exports = Command.extend({ | ||
name: 'uninstall', | ||
description: 'Removes 3rd party library from existing project', | ||
works: 'insideProject', | ||
|
||
run: function (commandOptions, rawArgs) { | ||
if (!rawArgs.length) { | ||
const msg = 'The `ng uninstall` command must take an argument with ' + | ||
'a package name.'; | ||
|
||
return Promise.reject(new SilentError(msg)); | ||
} | ||
|
||
const uninstallTask = new UninstallTask({ | ||
ui: this.ui, | ||
analytics: this.analytics, | ||
project: this.project | ||
}); | ||
|
||
return uninstallTask.run({ | ||
packages: rawArgs | ||
}); | ||
} | ||
}); | ||
|
||
module.exports.overrideCore = true; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import * as Task from 'ember-cli/lib/models/task'; | ||
import * as npmTask from 'ember-cli/lib/tasks/npm-task'; | ||
import * as chalk from 'chalk'; | ||
import * as path from 'path'; | ||
import { EventEmitter } from 'events'; | ||
import * as search from 'typings-core/dist/search'; | ||
import * as typings from 'typings-core/dist/install'; | ||
import * as systemJS from '../utilities/systemjs-helper'; | ||
|
||
module.exports = Task.extend({ | ||
completionOKMessage: 'Successfully installed.', | ||
completionErrorMessage: 'Error installing package.', | ||
|
||
run: function(options) { | ||
this.packages = options.packages; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused as to what this does. Could you explain it? Preferably in a comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It gets |
||
|
||
if (this.packages.indexOf('sass') !== -1) { | ||
this.packages[this.packages.indexOf('sass')] = 'node-sass'; | ||
} | ||
|
||
if (this.packages.indexOf('compass') !== -1) { | ||
this.packages[this.packages.indexOf('compass')] = 'compass-importer'; | ||
if (this.packages.indexOf('sass') === -1 || this.packages.indexOf('node-sass')) { | ||
this.packages.push('node-sass'); | ||
} | ||
} | ||
|
||
return this.installProcedure(); | ||
}, | ||
|
||
installProcedure: function() { | ||
const that = this; | ||
|
||
const NpmTask = new npmTask({ | ||
command: 'install', | ||
ui: this.ui, | ||
analytics: this.analytics, | ||
project: this.project, | ||
startProgressMessage: 'Installing packages: ' + this.packages, | ||
completionMessage: 'Packages successfully installed.' | ||
}); | ||
|
||
return NpmTask.run({ | ||
packages: this.packages, | ||
verbose: false | ||
}) | ||
.then(() => this.storeInSystemJSConfig(this.packages)) | ||
.then(() => this.installTypings()); | ||
}, | ||
|
||
installTypings: function() { | ||
this.ui.startProgress(chalk.green('Searching and installing typings'), chalk.green('.')); | ||
this.packages = this.packages.filter(p => !/node-sass|stylus|less|compass-importer/.test(p)); | ||
|
||
let typingsList = []; | ||
|
||
return Promise.all(this.packages.map(p => { | ||
return new Promise(res => { | ||
search.search({ name: p }).then(resp => { | ||
if (resp.results.length) { | ||
let names = resp.results.map(x => { | ||
if (x.source === 'dt') { return x.name; } | ||
}).filter(x => !!x); | ||
typingsList = typingsList.concat(names); | ||
} | ||
res(); | ||
}); | ||
}); | ||
})) | ||
.then(() => { | ||
return Promise.all(typingsList.map(t => { | ||
return new Promise(res => { | ||
let installOpts = { cwd: process.env.PWD, save: true, ambient: true }; | ||
typings.installDependencyRaw(t, installOpts).then(() => { res(); }); | ||
}); | ||
})) | ||
.then(() => { | ||
return this.ui.stopProgress(); | ||
}) | ||
}); | ||
}, | ||
|
||
storeInSystemJSConfig: function(packages) { | ||
const systemPath = path.resolve(process.cwd(), 'src', 'config', 'system.config.js'); | ||
let json = systemJS.loadSystemJson(systemPath); | ||
|
||
packages = packages.filter(p => { | ||
return (!/node-sass|stylus|less|compass-importer/.test(p)); | ||
}); | ||
|
||
let mappings = json.map || {}; | ||
packages.forEach(pkg => { | ||
mappings[pkg] = 'libs/' + pkg + '/' + pkg + '.js'; | ||
}); | ||
json.map = mappings; | ||
systemJS.saveSystemJson(systemPath, json); | ||
|
||
return Promise.resolve(); | ||
} | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import * as Task from 'ember-cli/lib/models/task'; | ||
import * as npmTask from 'ember-cli/lib/tasks/npm-task'; | ||
import * as chalk from 'chalk'; | ||
import * as path from 'path'; | ||
import * as search from 'typings-core/dist/search'; | ||
import * as typings from 'typings-core/dist/uninstall'; | ||
import * as systemJS from '../utilities/systemjs-helper'; | ||
|
||
module.exports = Task.extend({ | ||
run: function(options) { | ||
this.packages = options.packages; | ||
|
||
return this.uninstallProcedure(); | ||
}, | ||
|
||
uninstallProcedure: function() { | ||
const that = this; | ||
|
||
const NpmTask = new npmTask({ | ||
command: 'uninstall', | ||
ui: this.ui, | ||
analytics: this.analytics, | ||
project: this.project, | ||
startProgressMessage: 'Uninstalling packages: ' + this.packages, | ||
completionMessage: 'Packages successfully uninstalled.' | ||
}); | ||
|
||
return NpmTask.run({ | ||
packages: this.packages, | ||
verbose: false | ||
}) | ||
.then(() => this.removeFromSystemJSConfig(this.packages)) | ||
.then(() => this.uninstallTypings()); | ||
}, | ||
|
||
uninstallTypings: function() { | ||
this.ui.startProgress(chalk.green('Uninstalling typings'), chalk.green('.')); | ||
this.packages = this.packages.filter(p => !/node-sass|stylus|less|compass-importer/.test(p)); | ||
let typingsList = []; | ||
|
||
return Promise.all(this.packages.map(p => { | ||
return new Promise(res => { | ||
search.search({ name: p }).then(resp => { | ||
if (resp.results.length) { | ||
let names = resp.results.map(x => { | ||
if (x.source === 'dt') { return x.name; } | ||
}).filter(x => !!x); | ||
typingsList = typingsList.concat(names); | ||
} | ||
res(); | ||
}); | ||
}); | ||
})) | ||
.then(() => { | ||
return Promise.all(typingsList.map(t => { | ||
return new Promise(res => { | ||
let installOpts = { cwd: process.env.PWD, save: true, ambient: true }; | ||
typings.uninstallDependency(t, installOpts).then(() => { res(); }); | ||
}); | ||
})) | ||
.then(() => { | ||
return this.ui.stopProgress(); | ||
}) | ||
}); | ||
}, | ||
|
||
removeFromSystemJSConfig: function(packages) { | ||
const systemPath = path.resolve(process.cwd(), 'src', 'config', 'system.config.js'); | ||
|
||
let json = systemJS.loadSystemJson(systemPath); | ||
let mappings = json.map || {}; | ||
packages.forEach(pkg => { | ||
delete mappings[pkg]; | ||
}); | ||
json.map = mappings; | ||
systemJS.saveSystemJson(systemPath, json); | ||
|
||
return Promise.resolve(); | ||
} | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/// <reference path="../../../typings/main.d.ts" /> | ||
import fs = require('fs'); | ||
|
||
export function loadSystemJson(systemPath: string): { [name: string]: any } { | ||
const systemContents: any = fs.readFileSync(systemPath, 'utf8'); | ||
const jsonContent: any = systemContents.match(/^[^\{]*([\s\S]+)\);.*$/m)[1]; | ||
|
||
return JSON.parse(jsonContent); | ||
} | ||
|
||
export function saveSystemJson(systemPath: string, json: { [name: string]: any }) { | ||
const jsonContent: any = JSON.stringify(json, null, '\t'); | ||
const writeContents: any = 'System.config(' + jsonContent + ');'; | ||
|
||
fs.writeFileSync(systemPath, writeContents, 'utf8'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* jshint node: true, esversion: 6 */ | ||
'use strict'; | ||
|
||
try { | ||
let sass; | ||
let compass; | ||
|
||
if (process.platform === 'win32') { | ||
require.resolve(`${process.env.PWD}/node_modules/node-sass`); | ||
require.resolve(`${process.env.PWD}/node_modules/compass-importer`); | ||
sass = require(`${process.env.PWD}/node_modules/node-sass`); | ||
compass = require(`${process.env.PWD}/node_modules/compass-importer`); | ||
} else { | ||
process.env.NODE_PATH += `:${process.env.PWD}/node_modules`; | ||
require('module').Module._initPaths(); | ||
require.resolve('node-sass'); | ||
require.resolve('compass-importer'); | ||
sass = require('node-sass'); | ||
compass = require('compass-importer'); | ||
} | ||
|
||
const Plugin = require('broccoli-caching-writer'); | ||
const fse = require('fs-extra'); | ||
const path = require('path'); | ||
const Funnel = require('broccoli-funnel'); | ||
|
||
class CompassPlugin extends Plugin { | ||
constructor(inputNodes, options) { | ||
super(inputNodes, {}); | ||
|
||
options = options || {}; | ||
Plugin.call(this, inputNodes, { | ||
cacheInclude: [/(.*?).scss$/, /(.*?).sass$/] | ||
}); | ||
this.options = options; | ||
this.fileRegistry = []; | ||
} | ||
|
||
build() { | ||
let entries = this.listEntries(); | ||
let rootFileNames = entries.map(e => { | ||
return path.resolve(e.basePath, e.relativePath); | ||
}); | ||
|
||
rootFileNames.forEach(fileName => { | ||
this.compile(fileName, this.inputPaths[0], this.outputPath); | ||
}); | ||
} | ||
|
||
compile(fileName, inputPath, outputPath) { | ||
let sassOptions = { | ||
file: path.join(fileName), | ||
includePaths: this.inputPaths, | ||
data: '@import "compass"; .transition { @include transition(all); }', | ||
importer: compass | ||
}; | ||
|
||
let result = sass.renderSync(sassOptions); | ||
let filePath = fileName.replace(inputPath, outputPath) | ||
.replace(/\.scss$/, '.css') | ||
.replace(/\.sass$/, '.css'); | ||
|
||
fse.outputFileSync(filePath, result.css, 'utf8'); | ||
} | ||
} | ||
|
||
exports.makeBroccoliTree = (sourceDir) => { | ||
let compassSrcTree = new Funnel(sourceDir, { | ||
include: ['**/*.scss', '**/*.sass'], | ||
allowEmpty: true | ||
}); | ||
|
||
return new CompassPlugin([compassSrcTree]); | ||
}; | ||
} catch (e) { | ||
exports.makeBroccoliTree = () => { | ||
return null; | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we want to ignore that single file? It seems like it should be linted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the double quotes which are mandatory for
JSON.parse
insystemjs-helper.ts
.