Skip to content

Instantly share code, notes, and snippets.

@Quramy
Last active July 6, 2016 02:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Quramy/55ccb99e4e3a475d94fb941fe9f27e3d to your computer and use it in GitHub Desktop.
Save Quramy/55ccb99e4e3a475d94fb941fe9f27e3d to your computer and use it in GitHub Desktop.
falcor-fire
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;
}
}
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