Skip to content

Commit

Permalink
Cut of FB API
Browse files Browse the repository at this point in the history
  • Loading branch information
clayallsopp committed Mar 30, 2016
1 parent 519555f commit 1af4799
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 2 deletions.
1 change: 1 addition & 0 deletions graphqlhub-schemas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"author": "Clay Allsopp <[email protected]>",
"license": "MIT",
"dependencies": {
"fb": "1.1.0-alpha1",
"giphy-api": "1.1.14",
"github-api": "https://github.com/clayallsopp/github/tarball/fork",
"graphql-relay": "0.3.6",
Expand Down
24 changes: 24 additions & 0 deletions graphqlhub-schemas/src/apis/facebook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Facebook, FacebookApiException} from 'fb';

const createClient = () => {
const client = new Facebook();
client.apiAsync = (...args) => {
let promise = new Promise((resolve, reject) => {
return client.api(...args, (res) => {
if(!res || res.error) {
reject(res && res.error);
return;
}
resolve(res);
});
});
return promise;
};
return client;
}

export const getId = (id, token) => {
const client = createClient();
client.setAccessToken(token);
return client.apiAsync(id, { metadata: '1' });
};
160 changes: 160 additions & 0 deletions graphqlhub-schemas/src/facebook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// https://developers.facebook.com/tools/explorer

import {
getId as getNode
} from './apis/facebook';

import {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLNonNull,
GraphQLInt,
GraphQLEnumType,
GraphQLBoolean,
GraphQLList,
GraphQLInterfaceType,
GraphQLID
} from 'graphql';

import {
nodeDefinitions,
fromGlobalId,

connectionDefinitions,
connectionArgs,
connectionFromArray,
} from 'graphql-relay';

const getTokenFromAST = (ast) => {
return ast.variableValues.facebookToken;
};

const getTypeFromFBGraphType = (node) => {
return {
user: userType,
page: pageType,
}[node.metadata.type];
}

const {nodeInterface, nodeField} = nodeDefinitions(
(globalId, ast) => {
//const { id } = fromGlobalId(globalId);
return getNode(globalId, getTokenFromAST(ast));
},
(obj) => {
return getTypeFromFBGraphType(obj);
//return obj.ships ? factionType : shipType;
}
);

const profileFields = () => {
return {
id : {
type : new GraphQLNonNull(GraphQLID),
},
metadataType : {
type : new GraphQLNonNull(GraphQLString),
resolve(profile) {
return profile.metadata.type;
}
}
};
};

const profileInterface = new GraphQLInterfaceType({
name: 'FacebookProfile',
resolveType: getTypeFromFBGraphType,
fields: {
...profileFields()
}
});

const pageType = new GraphQLObjectType({
name: 'FacebookPage',
interfaces: [nodeInterface, profileInterface],
fields: () => {
return {
...profileFields(),
likes: {
type : GraphQLInt
}
};
}
});

const CURSOR_NOT_SUPPORTED = 'NOT SUPPORTED';

const userType = new GraphQLObjectType({
name: 'FacebookUser',
interfaces: [nodeInterface, profileInterface],
fields: () => {
return {
...profileFields(),
name : {
type : GraphQLString,
resolve(user, args, ast) {
return getNode(user.id, getTokenFromAST(ast)).then((res) => {
return res.name;
})
}
},
likes : {
type : likesConnectionDefinitions.connectionType,
args : connectionArgs,
resolve(user, args, ast) {
return getNode(user.id + `/likes`, getTokenFromAST(ast)).then((response) => {

const { data, paging, summary} = response;
const pages = data;

console.log(response)

const edges = pages.map((page) => {
return {
cursor : CURSOR_NOT_SUPPORTED,
node : page
};
});
const pageInfo = {
startCursor : paging.cursors.before,
endCursor : paging.cursors.after,
hasPreviousPage : (!!paging.previous),
hasNextPage : (!!paging.next)
};

return {
edges,
pageInfo
};
});
}
}
}
}
});

const likesConnectionDefinitions = connectionDefinitions({ nodeType : pageType });


const fbType = new GraphQLObjectType({
name : 'FacebookAPI',
fields : {
viewer : {
type : userType,
resolve(root, args, ast) {
return getNode('me', getTokenFromAST(ast));
}
},
node: nodeField
}
})

export const QueryObjectType = fbType;

export const QueryArgsType = {
token : {
type : new GraphQLNonNull(GraphQLString)
}
};
3 changes: 3 additions & 0 deletions graphqlhub-schemas/src/graphqlhub.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as KEYVALUE from './keyvalue';
import * as GITHUB from './github';
import * as TWITTER from './twitter';
import * as GIPHY from './giphy';
import * as FACEBOOK from './facebook';

let schemas = {
hn : HN,
Expand All @@ -19,6 +20,7 @@ let schemas = {
github : GITHUB,
twitter: TWITTER,
giphy: GIPHY,
facebook: FACEBOOK,
};

let FIELDS = {
Expand All @@ -43,6 +45,7 @@ Object.keys(schemas).forEach((schemaName) => {
}
FIELDS[schemaName] = {
type : schemas[schemaName].QueryObjectType,
args : schemas[schemaName].QueryArgsType,
resolve() {
return {};
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"cors": "2.7.1",
"dotenv": "1.2.0",
"express": "4.13.3",
"express-graphql": "0.3.0",
"express-graphql": "0.4.13",
"github-api": "https://github.com/clayallsopp/github/tarball/fork",
"graphiql": "0.2.0",
"graphql": "0.4.17",
Expand Down
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
<h1 class='gqh-Subheadline'>Explore</h1>
<p class='gqh-Paragraph'>Query popular APIs using GraphQL in your browser:</p>
<ul>
<li class='gph-Bullet'><a href="/playground/facebook">Facebook</a></li>
<li class='gph-Bullet'><a href="/playground/hn">Hacker News</a></li>
<li class='gph-Bullet'><a href="/playground/reddit">Reddit</a></li>
<li class='gph-Bullet'><a href="/playground/github">GitHub</a></li>
Expand Down
12 changes: 11 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,16 @@ app.get('/playground', renderHTML('PLAYGROUND'));
app.get('/', renderHTML('INDEX'));
app.use(express.static(path.join(__dirname, '..', 'public')));
app.use('/graphql', cors(), instrumentationMiddleware(Schema, timingCallback, { addToResponse : false }), graphqlHTTP((req, res) => {
return { schema: Schema, rootValue : req.rootValue }
return {
schema: Schema,
rootValue : req.rootValue,
formatError: (error) => {
return {
message: error.message,
details: error.stack
}
}
}
}));

let SHORTCUTS = {
Expand All @@ -89,6 +98,7 @@ let SHORTCUTS = {
,
giphy : '/playground?query=%23%20Hit%20the%20Play%20button%20above!%0A%23%20Hit%20"Docs"%20on%20the%20right%20to%20explore%20the%20API%0A%0A%7B%0A%20%20graphQLHub%0A%20%20giphy%20%7B%0A%09%09random(tag%3A"javascript")%20%7B%0A%20%20%20%20%09id%0A%20%20%20%20%20%20url%0A%20%20%20%20%20%20images%20%7B%0A%20%20%20%20%20%20%20%20original%20%7B%0A%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%09%7D%0A%20%20%7D%0A%7D'
,
facebook : '/playground?query=%23%20Hit%20the%20Play%20button%20above!%0A%23%20Hit%20"Docs"%20on%20the%20right%20to%20explore%20the%20API%0A%0Aquery%20(%24facebookToken%3A%20String!)%7B%0A%20%20graphQLHub%0A%09facebook(token%3A%20%24facebookToken)%20%7B%0A%09%09node(id%3A%20"4")%20%7B%0A%09%09%09id%0A%20%20%20%20%20%20...%20on%20FacebookUser%20%7B%0A%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20%0A%7D&variables=%7B%0A%20%20"facebookToken"%3A"Get%20an%20API%20token%2C%20i.e.%20from%20https%3A%2F%2Fdevelopers.facebook.com%2Ftools%2Fexplorer"%0A%7D'
};
Object.keys(SHORTCUTS).forEach((shortcut) => {
app.get(`/playground/${shortcut}`, (req, res) => {
Expand Down

0 comments on commit 1af4799

Please sign in to comment.