タイトル盛りすぎた。 mizchi/stone-skin です。 npm install stone-skin
で入るんでbrowserifyと一緒に使ってください。
命名は、時間があったらFF14やるんだけどなという気持ちを込めて。(ナイトだけLv50にしてから1年以上触ってない)
この前紹介したArdaと一緒で、本番環境でドッグフーディングしつつ開発したので、使い物になるはず。今さっきドキュメント書いてv0.1.0にしたので紹介。
サンプルコード
非同期APIはPromiseを返すので、この前書いた
JavaScript - Babelのasync/await試してみた(+中の処理をちょっと追ってみた) - Qiita のasync/awaitを使いつつ紹介。
import "babel/polyfill";
import StoneSkin from '../with-tv4';
class ItemStore extends StoneSkin.IndexedDb {
storeName: 'Item';
schema: {
properties: {
title: {
type: 'string'
}
}
}
}
let itemStore = new ItemStore();
(async () => {
await itemStore.ready;
await itemStore.save({title: 'foo', _id: 'xxx'});
let item = await itemStore.find('xxx');
console.log(item);
let items = await itemStore.all();
console.log(items);
})();
_id
だけ予約語。find(), save({..}), all(), select(i => bool) っていうそれっぽいAPIで永続化されたIndexedDbを扱える。
MemoryDbっていうクラスを継承しても全く同じAPIになるが、永続化はされない。扱ってる時はどっちか気にしなくてよい。
save時に渡したインスタンスは、JSONSchemaでバリデーションされる。
TypeScript用の型定義も用意した https://github.com/mizchi/stone-skin/blob/master/stone-skin.d.ts のだけど、TypeScriptの抜け道がいくらでもある型チェックより保存時のインスタンスのバリデーションの方が安心できそうだったので、実行時バリデーションを大事にした。型情報は補完用。
他にも StoneSkin.utils.setupWithMigrate(version)
っていうスキーマバージョンが変わった時のマイグレーションヘルパとかある。というか必要に迫られて作った。
他は mizchi/stone-skin の README や examples を見てください。
作った動機
近年、JavaScriptアプリの多機能化により、ブラウザストレージを適切に扱う必要性が増してきた。うんぬん。
似たようなライブラリとして Dexie.js - Minimalistic IndexedDB Wrapper や mWater/minimongo がある。
弊社某アプリの開発でminimongo使ってたんだけどmongo部分がどんどんいらなくなってきて、結局モンゴクエリでwhereするの面倒くさくなってきた。どうせJSから扱うんだし、カーソル処理+filter関数だけでどうにかできるはず、という直感はあった。ついでに適切にバッチ処理にフォールバック出来るようにするとパフォーマンスあがるはずで、薄いラッパーの上でそういうの作りたかった。作った。
で、最初jensarps/IDBWrapperをみてたんだけど、Promise化ぐらいならいけるやろと思い mizchi/idb-wrapper-promisify を書き(これのテストをPromise用に書き換えて通すのが面倒だった)、その上にActiveRecord風のAPIを被せた。
永続化ストレージ、簡単に扱うよりも固く扱えるようにするのが動機として強いんだけど、とはいえある程度簡単じゃないとモチベーション下がる。素のIndexedDbは妙にローレベルで最適化難しく、StoneSkinはまだパフォーマンス的な最適化は施してないがそれが出来る余地を残してある。
お試しください。