Momic.DB :: Mongoシェル風のAPIでブラウザのストレージを扱う
前々から欲しかったブラウザの永続ストレージのラッパーを作りました。
mizchi/momic https://github.com/mizchi/momic
momicは"mongo mimic"の略で、mongo風にしたかったけどJavaScriptやストレージの制約を考えると完全な互換にする必要ないんだけど、やっぱそれっぽくしたいが… 作った結果やっぱ擬態でしかない(ミミック)という感じのニュアンスです。
動機
仕事と趣味両方でmongodbをバックエンドにしたシングルページアプリケーション作ってることが多いんですが、クライアントサイドでサーバーサイドのmongo shellと似たようなAPI欲しいなーと前々から思ってました。
パフォーマンスはあんまり気にしていません。ストレスなくそれっぽいAPIを作ることを志しました。気になる人は、詳細は後述しますが、autoSave: false で save()を自前で呼ぶことで最低限の処理だけ走るようになります。
meteorのminimongoをmeteorなしで使いたくて、ydn-db試してみて使い物にならなかったのが作り始めた直接の動機です。
インストール
bowerでインストールできます
bower install momic --save-dev
依存
- localforage
- es6-promises
今のchrome34ならPromiseが入ってるのでes6-promisesは不要ですが、残念ながら世の中そんなに便利ではない。
localforageはmozilla製で localStorage, WebSQ, indexedDb を抽象化してくれます。
使い方
Collection#count(), Collection#saved() 以外のすべての関数はpromsiseオブジェクトを返します
new Momic.DB
db = new Momic.DB name: 'app' # name is used for namespace prefix collections: foo: hasInstance: true # 実体のインスタンスを抱える。あると速いがメモリを使う hasPersistence: true # ストレージに保存する autoSave: true # insert, update時に自動保存 plugins: [] # プラグインあとで解説
DB#init()
collectionを初期化する
db.init().done => db.foo.find().then => # 準備ok
Collection#insert(obj_or_array)
コレクションに挿入します
db.foo.insert({foo: 1})
insetしたときにidプロパティが存在しない場合、自動でidプロパティを生やします。
Collection#update(obj_or_array)
obj.id と同一のidを持つコレクションを更新します。
col.insert(id:1, text: 'a', foo: 3).then => col.update(id:1, text: 'foo') #=> update to {id: 1, text: 'foo', foo: 3}
Collection#find(null_or_func_or_obj)
条件に見合ったものを探す。
col.find() # fetch all items col.find((i)->i.num > 5) # fetch items that num > 5 items col.find({text: 'aaa'}) # fetch items that text is 'aaa' col.find({text: {content: 'aaa'}}) # nested object is ok!
$gteとかのクエリ式は実装しておりません。残念だったな。ここらへんのやる気がある人はPull Requestください。
Collection#remove(func_or_obj)
findと同じ条件でヒットしたものを削除します。
Collection#save()
現在の状態を保存。autoSave: true のときは呼ぶ必要はありません。
プラグイン機構
各所にフック処理をつけられます。バリデーション書きたい人はここで頑張ってください。
MyPlugin = { initialize: (collection) -> # called with collection instance preInsertHook: (item) -> # called by each items to modify preUpdateHook: (item) -> # called by each items to modify preSaveHook: (items) -> # called once before save postSaveHook: (items) -> # called once after save console.log 'collection saved!' } window.db = new Momic.DB name: 'app' collections: items: plugins: [MyPlugin]
注意
今現在chrome34とlocalforageのIndexedDb両方に問題があり、バックエンドとして使うと異常な挙動になります。 ワークアラウンドとして localforage.setDriver('localStorageWrapper')
して使ってください。(おそらくIndexedDbの方が速くはなります)
僕が快適に使えるように作っただけなので、安全弁がついてない感じですが、要望がある方は https://github.com/mizchi/momic/issues までどうぞ。