Cloud9 IDEを拡張して、npmのインストーラを作ってみました。npm installとnpm listができるようになりました。
まず、クライアントのViewです。
cloud9/client/ext/npmtools/npmtools.xml
<a:application xmlns:a="http://ajax.org/2005/aml"> <a:window id = "winDatagrid" title = "NPM Packages" icon = "" center = "true" resizable = "true" buttons = "close" modal = "false" skin = "bk-window" width = "660" height = "400" kbclose = "true" draggable = "true"> <a:vbox anchors="0 0 0 0" edge="0 0 0 0"> <a:hbox> <a:textbox id="tbPackage" flex="1"> </a:textbox> <a:button id="btnInstall" caption="Install"> </a:button> </a:hbox> <a:datagrid id="dgList" flex="1"> <a:each match="[packages]"> <a:column caption="Name" value="[@name]" width="50%" /> <a:column caption="Version" value="[@version]" width="50%" /> </a:each> </a:datagrid> </a:vbox> </a:window> </a:application>
クライアントのロジック。
cloud9/client/ext/npmtools/npmtools.js
define(function(require, exports, module) { var ide = require('core/ide'); var ext = require('core/ext'); var panels = require("ext/panels/panels"); var markup = require('text!ext/npmtools/npmtools.xml'); var util = require("core/util"); module.exports = ext.register('ext/npmtools/npmtools', { name : "NPM Tools", dev : "Tomoyuki Inoue", alone : true, type : ext.GENERAL, markup : markup, command : "npmtools", desp : [panels], nodes : [], hook : function(){ var _self = this; this.nodes.push( mnuWindows.insertBefore(new apf.item({ caption : "NPM Tools", onclick : function(){ ext.initExtension(_self); // モデルを作成 var model = new apf.model(); // datagridのmodel属性にmodelを設定 dgList.setModel("model", model); // data要素を作成 var data = winDatagrid.ownerDocument.createElement("data"); // dataをロード model.load(data); // modelを設定 dgList.setModel(model); _self.listPackages(); // ボタンクリック時のイベントハンドラ btnInstall.addEventListener("click", function(e){ if(tbPackage.value.length > 0){ tbPackage.clear(); btnInstall.disable(); _self.installPackage(tbPackage.value); } }); // datagridを表示 winDatagrid.show(); } }) ), mnuWindows.firstChild); // サーバから受信した時の処理を記述。 ide.addEventListener("socketMessage", this.onMessage.bind(this)); }, onMessage: function(e) { var message = e.message; // datagrid_test以外なら何もしない。 if(message.type !== "result" && message.subtype !== "npmtools") return; if(message.body.subcommand === "list"){ this.addPackageToDatagrid(message.body.name, message.body.version); } if(message.body.subcommand === "install"){ m.clear(); this.listPackages(); } }, listPackages: function(){ // npm listの実行結果を取得 ide.send({ command: "npmtools", subcommand: "list" }); }, installPackage: function(packageName){ var data = { command: "npmtools", subcommand: "install", packagename :packageName }; // サーバにデータを送信。 ide.send(data); }, addPackageToDatagrid: function(packageName, version){ // モデルを取得 var m = dgList.getModel(); // packages要素を作成 var member = winDatagrid.ownerDocument.createElement('packages'); // name属性を設定 member.setAttribute('name', packageName); // version属性を設定 member.setAttribute('version', version); // data要素の子要素としてpackages要素を追加 m.data.appendChild(member); btnInstall.enable(); }, init : function(apfNode){}, enable : function(){ if (!this.disabled) return; this.nodes.each(function(item){ item.enable(); }); this.disabled = false; }, disable : function(){ if (this.disabled) return; this.nodes.each(function(item){ item.disable(); }); this.disabled = true; }, destroy : function(){ this.nodes.each(function(item){ item.destroy(true, true); }); this.nodes = []; } }); });
サーバ側のプラグインです。
cloud9/server/cloud9/ext/npmtools/npmtools.js
var Plugin = require("cloud9/plugin"); var sys = require("sys"); var fs = require("fs"); // 初期設定 var DataGridTestPlugin = module.exports = function(ide) { this.ide = ide; // hooksに「command」を追加する this.hooks = ["command"]; // 自分の名前 this.name = "npmtools"; }; // Pluginクラスを継承する。 sys.inherits(DataGridTestPlugin, Plugin); (function() { // command を実装。workspaceから実行される。 this.command = function(user, message, client) { // 自分以外のコマンドは受け付けない。 if(message.command != "npmtools") return false; var _self = this; // サブコマンドがlistの場合、作業フォルダのpackage.jsonを探索。 if(message.subcommand === "list") { this.listPackages(this.ide.workspaceDir, function(err, json){ if(err) throw err; console.log(json.name + "," + json.version); _self.sendResult(0, message.command, { subcommand: message.subcommand, name: json.name, version: json.version }); }); return true; } if(message.subcommand === "install"){ var args = [message.subcommand, message.packagename]; // npm installを実行 this.spawnCommand("npm", args, this.ide.workspaceDir, function(err) {}, function(out) {}, function(code, err, out) { // クライアントに送信 _self.sendResult(0, message.command, { subcommand: message.subcommand, packagename: message.packagename }); } ); return true; } return false; }; // サーバ終了時に起動。 this.dispose = function(callback) { // TODO kill all running processes! callback(); }; // NPMパッケージのリストを取得する this.listPackages = function(path, cb) { // パスの読み込み開始 var path = path + "/node_modules"; fs.readdir(path, function(err, dirs){ if(err) cb(err, null); // dirsには指定したパスのファイル名・ディレクトリ名の一覧が入っている for(var i = 0; i < dirs.length; i++){ var dir = dirs[i]; // 頭文字が.の場合読み込まない if(dir.charAt(0) === '.') continue; // package.jsonのパスを指定 var jsonPath = path + "/" + dir + "/package.json"; // package.jsonを読み込み開始 fs.readFile(jsonPath, function(err, data){ if(err) cb(err, null); // dataには読み込んだBufferが入っている // toString('utf8')で文字列にする var jsonStr = data.toString('utf8'); // JSONをパースしてコールバック cb(null, JSON.parse(jsonStr)); }); } }); }; }).call(DataGridTestPlugin.prototype);
実行結果はこんな感じ。テキストボックスにパッケージ名を入力してInstallボタンで、npmでインストールできます。
0 件のコメント:
コメントを投稿