diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ade14b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +npm-debug.log +node_modules diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..f7e9394 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1 @@ +## 0.1.0 - First Release diff --git a/README.md b/README.md index 78c91f4..7ea446f 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# atom-npm-run \ No newline at end of file +# atom-npm + +NPM integration for Atom. diff --git a/lib/atom-npm.coffee b/lib/atom-npm.coffee new file mode 100644 index 0000000..9f41679 --- /dev/null +++ b/lib/atom-npm.coffee @@ -0,0 +1,28 @@ +{CompositeDisposable} = require 'atom' + +ScriptsListView = require './views/scripts-list-view' +OutdatedView = require './views/outdated-view' +InstallView = require './views/install-view' +UpdateView = require './views/update-view' +npm = require './npm' + +module.exports = + subscriptions: null + + activate: (state) -> + # Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable + @subscriptions = new CompositeDisposable() + + # Register command that toggles this view + @subscriptions.add atom.commands.add 'atom-workspace', 'atom-npm:run': () -> + npm.getPackage().then (pkg) -> + (new ScriptsListView(pkg)).show() + @subscriptions.add atom.commands.add 'atom-workspace', 'atom-npm:outdated': () -> new OutdatedView() + @subscriptions.add atom.commands.add 'atom-workspace', 'atom-npm:install': () -> new InstallView() + @subscriptions.add atom.commands.add 'atom-workspace', 'atom-npm:update': () -> new UpdateView() + + return + + deactivate: () -> + @subscriptions.dispose() + return diff --git a/lib/npm.coffee b/lib/npm.coffee new file mode 100644 index 0000000..04a4648 --- /dev/null +++ b/lib/npm.coffee @@ -0,0 +1,51 @@ +path = require 'path' +{execSync} = require 'child_process' + +npm = require 'npm/lib/npm' +npmconf = require 'npm/lib/config/core' +{makeEnv} = require 'npm/lib/utils/lifecycle' +Promise = require 'promise' +readJson = require 'read-package-json' +nopt = require 'nopt' + +configDefs = npmconf.defs +shorthands = configDefs.shorthands +types = configDefs.types +conf = nopt types, shorthands + +getNpm = () -> + new Promise (resolve, reject) -> + npm.load conf, (err) -> + if err then reject err + npm.localPrefix = atom.project.getDirectories()[0].path + resolve npm + return + +getPackage = (npm) -> + pkgdir = npm.localPrefix + + new Promise (resolve, reject) -> + readJson path.resolve(pkgdir, 'package.json'), (err, pkg) -> + if err then reject err + resolve pkg + return + +exec = (wd, pkg, script) -> + env = makeEnv pkg + + conf = cwd: wd, env: env + + if process.platform is 'win32' then conf.windowsVerbatimArguments = true + + out = execSync "npm #{script}", conf + +module.exports = + getPackage: () -> getNpm().then (npm) -> getPackage npm + + run: (wd, pkg, script) -> exec wd, pkg, "run #{script}" + + outdated: (wd, pkg) -> exec wd, pkg, 'outdated' + + install: (wd, pkg) -> exec wd, pkg, 'install' + + update: (wd, pkg) -> exec wd, pkg, 'update' diff --git a/lib/views/install-view.coffee b/lib/views/install-view.coffee new file mode 100644 index 0000000..31913dd --- /dev/null +++ b/lib/views/install-view.coffee @@ -0,0 +1,13 @@ +npm = require '../npm' + +module.exports = class InstallView + constructor: () -> + atom.notifications.addInfo 'Run "npm install"' + npm.getPackage().done (pkg) => + out = npm.install atom.project.getDirectories()[0].path, pkg + @show out.toString() + return + + show: (txt) -> + atom.notifications.addSuccess "npm install", detail: txt, dismissable: yes + return diff --git a/lib/views/outdated-view.coffee b/lib/views/outdated-view.coffee new file mode 100644 index 0000000..a0ba02f --- /dev/null +++ b/lib/views/outdated-view.coffee @@ -0,0 +1,13 @@ +npm = require '../npm' + +module.exports = class OutdatedView + constructor: () -> + atom.notifications.addInfo 'Run "npm outdated"' + npm.getPackage().done (pkg) => + out = npm.outdated atom.project.getDirectories()[0].path, pkg + @show out.toString() + return + + show: (txt) -> + atom.notifications.addSuccess "npm outdated", detail: txt, dismissable: yes + return diff --git a/lib/views/scripts-list-view.coffee b/lib/views/scripts-list-view.coffee new file mode 100644 index 0000000..c185c4b --- /dev/null +++ b/lib/views/scripts-list-view.coffee @@ -0,0 +1,39 @@ +{$$, SelectListView} = require 'atom-space-pen-views' +keys = require 'lodash/keys' +{makeEnv} = require 'npm/lib/utils/lifecycle' +{execSync} = require 'child_process' +npm = require '../npm' + +module.exports = + class ScriptsListView extends SelectListView + initialize: (@pkg) -> + super + @data = pkg.scripts or {} + @setItems @parseData @data + @focusFilterEditor() + + parseData: (scripts) -> keys(scripts).map (script, content) -> + label: "Run #{script}" + script: script + + getFilterKey: () -> 'name' + + show: () -> + @panel ?= atom.workspace.addModalPanel(item: this) + @panel.show() + @focusFilterEditor() + + cancelled: () -> @hide() + + hide: () -> @panel?.destroy() + + viewForItem: ({label}) -> + $$ -> + @li => + @span label + + confirmed: ({script}) -> + @cancel() + out = npm.run atom.project.getDirectories()[0].path, @pkg, script + + atom.notifications.addSuccess "npm run #{script}", detail: out.toString(), dismissable: yes diff --git a/lib/views/update-view.coffee b/lib/views/update-view.coffee new file mode 100644 index 0000000..5700ee2 --- /dev/null +++ b/lib/views/update-view.coffee @@ -0,0 +1,13 @@ +npm = require '../npm' + +module.exports = class UpdateView + constructor: () -> + atom.notifications.addInfo 'Run "npm update"' + npm.getPackage().done (pkg) => + out = npm.update atom.project.getDirectories()[0].path, pkg + @show out.toString() + return + + show: (txt) -> + atom.notifications.addSuccess "npm update", detail: txt, dismissable: yes + return diff --git a/menus/atom-npm.cson b/menus/atom-npm.cson new file mode 100644 index 0000000..57f2c58 --- /dev/null +++ b/menus/atom-npm.cson @@ -0,0 +1,19 @@ +"menu": [ + "label": "Packages" + "submenu": [ + "label": "Atom NPM" + "submenu": [ + "label": "Run" + "command": "atom-npm:run" + , + "label": "Outdated" + "command": "atom-npm:outdated" + , + "label": "Install" + "command": "atom-npm:install" + , + "label": "Update" + "command": "atom-npm:update" + ] + ] +] diff --git a/package.json b/package.json new file mode 100644 index 0000000..0c47d75 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "atom-npm", + "main": "./lib/atom-npm", + "version": "0.1.0", + "description": "NPM integration for Atom", + "keywords": [ + "atom", + "npm" + ], + "scripts": { + "q": "echo \"Test\" && echo \"Line 2\"" + }, + "activationCommands": { + "atom-workspace": [ + "atom-npm:run", + "atom-npm:outdated", + "atom-npm:install", + "atom-npm:update" + ] + }, + "repository": "https://github.com/atom/atom-npm", + "license": "MIT", + "engines": { + "atom": ">=1.0.0 <2.0.0" + }, + "dependencies": { + "atom-space-pen-views": "^2.2.0", + "graceful-fs": "^4.1.6", + "lodash": "^4.15.0", + "nopt": "^3.0.6", + "npm": "^3.10.7", + "promise": "^7.1.1", + "read-package-json": "^2.0.4" + } +} diff --git a/styles/atom-npm.less b/styles/atom-npm.less new file mode 100644 index 0000000..11b86e6 --- /dev/null +++ b/styles/atom-npm.less @@ -0,0 +1,8 @@ +// The ui-variables file is provided by base themes provided by Atom. +// +// See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less +// for a full listing of what's available. +@import "ui-variables"; + +.atom-npm { +}