Last active
July 6, 2016 02:15
-
-
Save Quramy/55ccb99e4e3a475d94fb941fe9f27e3d to your computer and use it in GitHub Desktop.
falcor-fire
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from "lodash"; | |
import Router from "falcor-router"; | |
const routingDefinitions = [ | |
{ | |
// "users.u001.name" のようなpathに反応する | |
route: "[{keys:collections}][{keys:ids}][{keys:props}]", | |
get: function(pathset) { | |
const collectionName = pathset.collections[0]; | |
const paths = pathset.ids.map(id => ({ refPath: `/${collectionName}/${id}`, fPath: [collectionName, id] })); | |
return Promise.all(paths.map(p => { | |
return this._db.ref(p.refPath).once("value").then(snapshot => { | |
const node = snapshot.val(); | |
if (!node) { | |
return [{ | |
path: p.fPath, | |
value: {$type: "error", value: "not found"}, | |
}]; | |
} | |
const decoded = this.decodeRef(node); | |
return pathset.props.map(prop => { | |
if (!decoded[prop]) { | |
return { path: [...p.fPath, prop], value: {$type: "error", value: "not found"} }; | |
} | |
return { path: [...p.fPath, prop], value: decoded[prop] }; | |
}); | |
}); | |
})).then(results => _.flatten(results)); | |
}, | |
set: function(jsonGraph) { | |
const collectionName = Object.keys(jsonGraph)[0]; | |
const updates = {}; | |
Object.keys(jsonGraph[collectionName]).forEach(id => { | |
const patch = this.encodeRef(jsonGraph[collectionName][id]); | |
Object.keys(patch).forEach(prop => { | |
const refPath = `/${collectionName}/${id}/${prop}`; | |
updates[refPath] = patch[prop]; | |
}); | |
}); | |
return this._db.ref().update(updates).then(() => ({jsonGraph})); | |
} | |
}, { | |
route: "[{keys:collections}].push", | |
call: function(callpath, args) { | |
const collectionName = callpath.collections[0]; | |
const payload = args[0]; | |
if (!payload) { | |
return [{ | |
path: [collectionName, "push"], | |
value: { $type: "error", value: "This call function requires an argument" }, | |
}]; | |
} | |
const newItemRef = this._db.ref(`/${collectionName}`).push(); | |
const body = this.encodeRef(payload); | |
body.id = newItemRef.key; | |
return newItemRef.set(body).then(() => { | |
return [...Object.keys(body).map(prop => { | |
return { | |
path: [collectionName, newItemRef.key, prop], | |
value: body[prop], | |
}; | |
}), { | |
path: [collectionName, "lastCreated"], | |
value: { $type: "ref", value: [collectionName, newItemRef.key] } | |
}]; | |
}); | |
} | |
} | |
]; | |
export class FireRouter extends Router.createClass(routingDefinitions) { | |
constructor(db) { | |
super(); | |
this._db = db; | |
} | |
/** | |
* Falcor JSON GraphのreferenceをFirebase Databaseに保存できる形式にシリアライズする | |
**/ | |
encodeRef(payload) { | |
const encoded = {}; | |
Object.keys(payload).forEach(prop => { | |
if (payload[prop].$type && payload[prop].$type === "ref") { | |
let path = payload[prop].value; | |
if (!path) return; | |
if (typeof path === "string") { | |
} else if (Array.isArray(path)) { | |
path = _.flatten(path).join('.'); | |
} else { | |
return; | |
} | |
encoded[prop] = {_type: "ref", value: path}; | |
} else { | |
encoded[prop] = payload[prop]; | |
} | |
}); | |
return encoded; | |
} | |
/** | |
* Firebase Databaseから取得したデータから、Falcor JSON Graphのreferenceを復元する | |
**/ | |
decodeRef(node) { | |
const decoded = {}; | |
Object.keys(node).forEach(prop => { | |
if (node[prop]._type === "ref" && node[prop].value) { | |
decoded[prop] = { $type: "ref", value: node[prop].value.split('.') }; | |
} else { | |
decoded[prop] = { $type: "atom", value: node[prop] }; | |
} | |
}); | |
return decoded; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import firebase from "firebase"; | |
import { config } from "./config"; | |
import * as Falcor from "falcor"; | |
import { FireRouter } from "./fire-router"; | |
export default async function main() { | |
// 0-a. Firebase Databaseの初期化 | |
firebase.initializeApp(config); | |
const database = firebase.database(); | |
// 0-b. Firebase DatabaseからFalcorのModelを作成する(実体はFalcor Router) | |
const model = new Falcor.Model({ source: new FireRouter(database) }).batch(); | |
let jsonEnvelope; | |
// 1. ユーザーの作成 | |
jsonEnvelope = await model.call("users.push", [{name: "Quramy"}], ["id"]); | |
const createdUser = jsonEnvelope.json.users.lastCreated; | |
// 2. 投稿の作成 | |
jsonEnvelope = await model.call( | |
"blogs.push", | |
[ | |
{ | |
title: "falcor and firebase", | |
body: "It's awesome", | |
starred: 0, | |
author: {$type: "ref", value: ["users", createdUser.id]} // JSON Graph形式で参照を保存 | |
} | |
], | |
["id"] | |
); | |
const createdPost = jsonEnvelope.json.blogs.lastCreated; | |
// 3. 作成した投稿の更新 | |
jsonEnvelope = await model.set({path: ["blogs", jsonEnvelope.json.blogs.lastCreated.id, "starred"], value: 10}); | |
// 4. 投稿の確認 | |
jsonEnvelope = await model.get( | |
"blogs.lastCreated.title", | |
"blogs.lastCreated.body", | |
"blogs.lastCreated.starred", | |
"blogs.lastCreated.author.id", | |
"blogs.lastCreated.author.name" | |
); | |
console.log(JSON.stringify(jsonEnvelope.json, null, 2)); | |
// 下記のようなJSONが取得できる. | |
// { | |
// "blogs": { | |
// "lastCreated": { | |
// "title": "falcor and firebase", | |
// "body": "It's awesome", | |
// "starred": 10, | |
// "author": { | |
// "id": "-KLwWPjOuMAE9SJKr41m", | |
// "name": "Quramy" | |
// } | |
// } | |
// } | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment