node-kyoto-tycoon
node-kyoto-tycoon
http://github.com/swdyh/node-kyoto-tycoon
KyotoTycoonのNode.js用ライブラリを作りました。まだだいぶ荒削りな状態で、KyotoTycoonのAPIを簡単にラップした感じのものです。APIも変わるかもしれないし、バグもたぶんあると思いますが試してみてください。
Node.jsが新しめでないとHTTPのKeep-Aliveが使えないので、古いNode.jsを使っている場合は、新しいNode.jsを入れて使ってください。(Keep-Aliveが使えなくても動きますが、カーソル関連は使えないと思います)
インストール
npmを使う
% npm install kyoto-tycoon
ソースから
% git clone http://github.com/swdyh/node-kyoto-tycoon.git % cp -r node-kyoto-tycoon ~/.node_libraries/kyoto-tycoon
使い方
var KyotoTycoon = require('kyoto-tycoon').KyotoTycoon var kt = new KyotoTycoon() kt.set('key1', 'val1', function() { kt.get('key1', function(err ,data) { console.log(data) kt.end() }) })
Node.jsらしく非同期なAPIしかなくて、なにをするにもコールバック関数を渡します。
ただこれだと、いくつかの処理を順にやろうとすると、コールバック関数がネストしていってつらいので、JSDeferredを使えるようにしています。ソースの中に入れてあるのでインストールする必要はありません。
var kt3 = new KyotoTycoon({ deferred : true }) kt3.set('key3', 'val3').next(function() { return kt3.get('key3') }).next(function(err, data) { console.log(data) return kt3.remove('key3') }).next(function(err, data) { return kt3.get('key3') }).next(function(err, data) { console.log(err) kt3.end() })
newのときにdeferredオプションを付けておくと、Deferredオブジェクトが返ってくるようになるので、nextで次の処理をつないでいけば順番に処理していけます。
実装の話
KyotoTycoonはhttpでアクセスするで、Node.jsについているhttpのライブラリをそのまま使っていています。データはTSVで返ってくるTSV-RPCという方式らしいので、TSV-RPCを処理するtsv-rpc.jsと、それを使ったkyoto-tycoon.jsのという構成にしています。
KyotoTycoonにははREST APIもあるんだけど、こっとは機能が少ないのと、REST用ライブラリだったら汎用のものがありそうで、KyotoTycoon用のライブラリとして書く意味がないという気がしたので使ってません。
JSDeferredを使えるようにしたところは、Deferred.connectというコールバックを取る関数を渡すと、Deferredを使った関数返をしてくれるという魔法みたいな関数があるので、それを呼びまくって関数を入れ替えています。
テストはVowsというので書いていて、正直あまり分かってないんだけど、非同期な関数のテストを想定してあったり、出力が綺麗だったりするので使ってみました。
AutoPagerizeのFirefox拡張をJetpack SDKで書き直した
Jetpack SDKが0.8になってpage-mod API(content script)がついたので、それを使ってAutPagerizeのFirefox拡張をつくり直しました。
前に作っていたFirefox拡張とは別の拡張になるので(Jetpackの制約のため)、以前のFirefox拡張を使っている場合は、それをアンインストールしてからこちらをインストールしてください。
インストール
https://relucks-org.appspot.com/autopagerize/autopagerize.xpi
ソースコード
http://github.com/swdyh/autopagerize_for_firefox
page-mod APIはけっこういい感じにできていて、JetpackのAPIが使えるmain.jsとcontent scriptの間をpostMessageでやりとりできるようになっていて、ChromeやSafariの拡張と同じような感じで使えます。
ただpage-mod APIは、content scriptを文字列で指定するようになっているのが難点で、これはselfモジュールを使って読み込むようにするといいと思います。
pageMod.add(new pageMod.PageMod({ include: ['http://*', 'https://*'], contentScriptWhen: 'ready', contentScript: self.data.load('autopagerize.user.js'), onAttach: onAttach }))
AutoPagerize for Safari
URLのトラッキング用パラメータを無視するFirefox拡張 Through utm_
URLのトラッキング用パラメータを無視するFirefox拡張(Through utm_) を作りました。インストールすると、utm_から始まるパラメータがついたURLにアクセスしようとした場合に、そのアクセスをキャンセルし、そのパラメータを削除したURLへアクセスします。
Through utm_
https://relucks-org.appspot.com/through_utm_/through_utm_.xpi
Jetpack SDKを使っていて、ソースはいつものようにGithubに置いてあります。
swdyh's Through-utm_ at master - GitHub
http://github.com/swdyh/Through-utm_
Jetpack SDKを使ってちょっと書いてみたという感じのもので、いま思うと他のトラッキング用パラメータ(?ref=rssとか)も対象にしたり、設定で変更できるようにしたり、もうちょっと汎用的にしてもよかったかなあと思ってます。
前からhttpまわりを簡単に触れるとけっこう面白いんじゃないかなあと思っていて、このへんはもうちょっといろいろできそうだなあという感じはあるので、またべつのものを作るかもしれないです。
あと今回は、ファイルをGoogle App Engineに置いています。Jetpack SDKでxpiを作る場合に署名を仕込むのが難しそうだったので、httpsが使えるApp Engineにしました。ファイルを置くだけならyamlを書くだけでいいし、なかなか良さそうです。App Engineでファイルを配布する場合、.xpi用のmime typeが用意されていないので、設定ファイルでmime type(mime_type: application/x-xpinstall)を指定しておくといいと思います。
Jepack SDKがリリースされたので使ってみる
Mozilla Labs » jetpack » Blog Archive » Announcing the Jetpack SDK: First Milestone Release
http://mozillalabs.com/jetpack/2010/03/09/announcing-the-jetpack-sdk/
環境は、MacOS 10.5.8、python2.5(macportsで入れたやつ、もとから入ってるのでもいいと思う)
SDKをダウンロードして解凍
% wget https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-0.1.tar.gz % tar zxvf jetpack-sdk-0.1.tar.gz % cd jetpack-sdk-0.1
SDKの環境をロード
% source bin/activate
ドキュメントの説明通りにパッケージをつくってみる
(jetpack-sdk-0.1)% mkdir packages/my-first-package (jetpack-sdk-0.1)% cd packages/my-first-package (jetpack-sdk-0.1)% vim package.json
{ "description": "This is my first package, it's tiny.", "author": "Me (http://me.org)" }
モジュールをつくる。モジュールはCommonJSスタイル。exportのプロパティに追加しておくと、他のファイルからrequireしたときに呼び出せる。
(jetpack-sdk-0.1)% mkdir lib (jetpack-sdk-0.1)% vim lib/my-module.js
exports.add = function add(a, b) { return a + b; }
モジュールのテストを書く
(jetpack-sdk-0.1)% mkdir tests (jetpack-sdk-0.1)% vim tests/test-my-module.js
var myModule = require('my-module') exports.ensureAdditionWorks = function(test) { test.assertEqual(myModule.add(1, 1), 2, '1 + 1 = 2') }
テストの実行。
(jetpack-sdk-0.1)% cfx test -v info: executing 'test-my-module.ensureAdditionWorks' info: pass: 1 + 1 = 2 Malloc bytes allocated (in use by application): 6436928 Malloc bytes mapped (not necessarily committed): 14262272 Malloc bytes committed (r/w) in default zone: 6446624 Malloc bytes allocated (in use) in default zone: 13213696 Tracked memory objects in testing sandbox: 2 1 of 1 tests passed. OK Total time: 1.215288 seconds Program terminated successfully.
ドキュメントを書く。Markdown形式。
(jetpack-sdk-0.1)% vim README.md
This is my *first* package. It contains: * A tiny module. * A tiny test suite. * Some meager documentation.
モジュールのドキュメントを書く。
(jetpack-sdk-0.1)% mkdir docs (jetpack-sdk-0.1)% vim docs/my-module.md
# my-module documentation!!
ドキュメントを開く
(jetpack-sdk-0.1)% cfx docs
ブラウザにSDKのドキュメントが表示される。左下のへんを見ると、自分のパッケージも追加されていて、ドキュメントも表示される。
起動部分を書く
(jetpack-sdk-0.1)% vim lib/main.js
exports.main = function(options, callbacks) { console.log("Hello World!") callbacks.quit() }
動かしてみる
(jetpack-sdk-0.1)% cfx run info: Hello World! OK Total time: 0.559730 seconds Program terminated successfully.
モジュールを使ってみる
var myModule = require('my-module') exports.main = function(options, callbacks) { console.log("Hello World!") console.log(myModule.add(1,2)) callbacks.quit() }
(jetpack-sdk-0.1)% cfx run info: Hello World! info: 3 OK Total time: 0.562395 seconds Program terminated successfully.
もうちょっと書いてみる
exports.add = function add(a, b) { return a + b; } exports.notify = function notify(options) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService). showAlertNotification(options['icon'], options['title'], options['body']) }
CcやCiは定義されていて使える。(セキュリティ関係で扱い方がかわるかも。)
var myModule = require('my-module') exports.main = function(options, callbacks) { myModule.notify({title: 'Run', body: 'This is my first Jetpack SDK app.'}) callbacks.quit() }
xpiにしてみる
(jetpack-sdk-0.1)% cfx xpi Exporting extension to my-first-package.xpi.
my-first-package.xpiをブラウザにドロップして、再起動。通知が出てきたら、成功
雑感
けっこう良い気がする。APIがそろってくれば、もっと書きやすくなるだろうし、APIが足りない部分はCcとかCi使って、ごりごり書けばなんとかなりそうだし。やっぱりそこが、Chromeの拡張に対するアドバンテージだろうなあ。
Jetpackから入るひとにCcとかCi使え、というのは酷だけど、もとから拡張書いてるひとが、そのへんをラップしたライブラリ書けばいいと思う。
今までだって、そういうラップしたライブラリは書こうと思えば書けたし、書いてるひとももちろんいるんだけど、そのへんが共有されてない感じがあって、結局、再発明したりMDCからコピペしたりとかになっちゃってたから、CPANとかGem的なライブラリを共有する仕組みがあるとJetpackはもう一歩先に進めるんじゃないかと思う。