Skip to content

Commit

Permalink
Get the example running
Browse files Browse the repository at this point in the history
  • Loading branch information
ForbesLindesay committed Aug 3, 2017
1 parent c2d7ecb commit 1c70566
Show file tree
Hide file tree
Showing 65 changed files with 169 additions and 9,563 deletions.
4 changes: 4 additions & 0 deletions .babelrc
@@ -0,0 +1,4 @@
{
"presets": ["react-app"],
"plugins": ["transform-es2015-modules-commonjs"]
}
7 changes: 0 additions & 7 deletions .gitignore
Expand Up @@ -15,10 +15,3 @@ node_modules
/dev
.DS_Store
/coverage

# generated modules (do not edit anything after this line manually)

/client.js
/server.js
/sessions
/utils
10 changes: 9 additions & 1 deletion HISTORY.md
Expand Up @@ -2,11 +2,19 @@

## v3.0.0: 2017-08-03

- Convert to typescript
Convert to typescript

### Breaking:

- Scalars `validate` method now has to return a boolean indicating whether the value is valid, and requires a "baseType".
- Scalars can no longer have `parse` and `validate`.
- The cache format, used by optimistic updaters, is now `{[typeName: string]: {[id: string]: Node}}` where it used to be `{[typeName + ':' + id]: Node}`. This is to allow for strongly typed bicycle caches.
- Void and Null are now treated as different, distinct values.
- The empty object is no longer cast to undefined for mutation arguments
- `createServerRenderer` now expects a `getContext` argument and then takes `Request` instead of `Context`

### Features:

- You can optionally add an `auth` property to each mutation/field. It is called with the same arguments as `resolve` and returns `true`, `false` (or a Promise for `true` or `false`) to idicate whether the current context is authorized to perform that action.
- Args do not have to be objects, you an direclty use e.g. `number` now.

Expand Down
46 changes: 27 additions & 19 deletions example/client/todo-model.js
@@ -1,4 +1,4 @@
import BicycleClient from '../../src/client'; // in a real app, the path should be 'bicycle/client'
import BicycleClient, {createNodeID} from '../../lib/client'; // in a real app, the path should be 'bicycle/client'

export default function TodoModel() {
this.errors = [];
Expand Down Expand Up @@ -33,16 +33,20 @@ TodoModel.prototype.inform = function () {

TodoModel.prototype.addTodo = function (title) {
this._client.update('Todo.addTodo', {title, completed: false}, (mutation, cache, optimistic) => {
if (cache.root.todos) {
if (cache.Root.root.todos) {
const id = optimistic('id');
return {
['Todo:' + id]: {
id,
title: mutation.args.title,
completed: mutation.args.completed,
Todo: {
[id]: {
id,
title: mutation.args.title,
completed: mutation.args.completed,
},
},
root: {
todos: ['Todo:' + id].concat(cache.root.todos),
Root: {
root: {
todos: [createNodeID('Todo', id)].concat(cache.Root.root.todos),
},
},
};
}
Expand All @@ -52,9 +56,9 @@ TodoModel.prototype.addTodo = function (title) {

TodoModel.prototype.toggleAll = function (checked) {
this._client.update('Todo.toggleAll', {checked}, (mutation, cache) => {
if (cache.root.todos) {
if (cache.Root.root.todos) {
const result = {};
cache.root.todos.forEach(key => {
cache.Root.root.todos.forEach(key => {
result[key] = {completed: checked};
});
return result;
Expand All @@ -65,16 +69,18 @@ TodoModel.prototype.toggleAll = function (checked) {

TodoModel.prototype.toggle = function (todoToToggle) {
this._client.update('Todo.toggle', {id: todoToToggle.id, checked: !todoToToggle.completed}, (mutation, cache) => {
return {['Todo:' + mutation.args.id]: {completed: mutation.args.checked}};
return {Todo: {[mutation.args.id]: {completed: mutation.args.checked}}};
});
};

TodoModel.prototype.destroy = function (todo) {
this._client.update('Todo.destroy', {id: todo.id}, (mutation, cache) => {
if (cache.root.todos) {
if (cache.Root.root.todos) {
return {
root: {
todos: cache.root.todos.filter(id => id !== 'Todo:' + mutation.args.id),
Root: {
root: {
todos: cache.Root.root.todos.filter(id => id.i !== mutation.args.id),
},
},
};
}
Expand All @@ -85,17 +91,19 @@ TodoModel.prototype.destroy = function (todo) {
TodoModel.prototype.save = function (todoToSave, text) {
this._client.update('Todo.save', {id: todoToSave.id, title: text}, (mutation, cache) => {
return {
['Todo:' + mutation.args.id]: {title: mutation.args.title},
Todo: {[mutation.args.id]: {title: mutation.args.title}},
};
});
};

TodoModel.prototype.clearCompleted = function () {
this._client.update('Todo.clearCompleted', {}, (mutation, cache) => {
if (cache.root.todos) {
this._client.update('Todo.clearCompleted', undefined, (mutation, cache) => {
if (cache.Root.root.todos) {
return {
root: {
todos: cache.root.todos.filter(id => !cache[id].completed),
Root: {
root: {
todos: cache.Root.root.todos.filter(id => !cache.Todo[id.i].completed),
},
},
};
}
Expand Down
4 changes: 2 additions & 2 deletions example/data.js
Expand Up @@ -52,9 +52,9 @@ export function clearCompleted() {
}

export function getTodos() {
return Promise.resolve(JSON.parse(JSON.stringify(todos)));
return new Promise((resolve) => { setTimeout(() => resolve(JSON.parse(JSON.stringify(todos))), LATENCY); });
}

export function getTodo(id) {
return Promise.resolve(JSON.parse(JSON.stringify(todos.filter(t => t.id === id)[0] || null)));
return new Promise((resolve) => { setTimeout(() => resolve(JSON.parse(JSON.stringify(todos.filter(t => t.id === id)[0] || null))), LATENCY); });
}
5 changes: 2 additions & 3 deletions example/schema/scalars/id.js
@@ -1,9 +1,8 @@
export default {
name: 'id',
baseType: 'string',
validate(value) {
// validate that it matches the format of the values returned by uuid()
if (!/^[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}$/.test(value)) {
throw new Error('Invalid id');
}
return /^[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}$/.test(value);
},
};
3 changes: 2 additions & 1 deletion example/schema/scalars/json-object.js
@@ -1,6 +1,7 @@
export default {
name: 'JsonObject',
baseType: 'any',
validate(value) {
// no-op
return value && typeof value === 'object';
},
};
7 changes: 4 additions & 3 deletions example/server.js
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs';
import express from 'express';
import browserify from 'browserify-middleware';
import babelify from 'babelify';
import BicycleServer from '../src/server';
import BicycleServer from '../lib/server';

const bicycle = new BicycleServer(__dirname + '/schema');

Expand All @@ -24,10 +24,11 @@ app.get('/client.js', browserify(__dirname + '/client/index.js', {transform: [ba
app.use('/bicycle', bicycle.createMiddleware(req => ({user: req.user})));

// TODO: use this capability to actually do server side rendering
const serverRenderer = bicycle.createServerRenderer((client, ...args) => {
const serverRenderer = bicycle.createServerRenderer(req => ({user: 'my user'}), (client, req, ...args) => {
return client.queryCache({todos: {id: true, title: true, completed: true}}).result;
});
serverRenderer({user: 'my user'}).done(result => {
const fakeRequest = {};
serverRenderer(fakeRequest).then(result => {
console.log('server renderer result');
console.dir(result, {depth: 10, colors: true});
});
Expand Down
104 changes: 0 additions & 104 deletions flow-definitions.js

This file was deleted.

0 comments on commit 1c70566

Please sign in to comment.