-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jeffrey Young
committed
Oct 17, 2017
0 parents
commit c25e1c8
Showing
8 changed files
with
1,179 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
Binary file not shown.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const db = require('sqlite'); | ||
const _ = require('lodash'); | ||
const faker = require('faker'); | ||
const {getAllUsers, batchGetUsers, batchGetFollowers} = require('./queries'); | ||
const setup = require('./setup'); | ||
|
||
module.exports = { | ||
initialize: setup, | ||
batchGetUsers: batchGetUsers, | ||
batchGetFollowers: batchGetFollowers, | ||
getAllUsers: getAllUsers | ||
}; | ||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const db = require('sqlite'); | ||
const _ = require('lodash'); | ||
const faker = require('faker'); | ||
let dbQueries = 0; | ||
function logQuery(type) { | ||
console.log('query', type, ++dbQueries); | ||
} | ||
|
||
async function batchGetFollowers(user_ids) { | ||
logQuery('batchGetFollowers'); | ||
const rows = await db.all(`SELECT Persons.firstName, Persons.lastName, Persons.id, FollowerEdges.user_id as following_id | ||
FROM Persons | ||
INNER JOIN FollowerEdges WHERE FollowerEdges.follower_id = Persons.id | ||
AND FollowerEdges.user_id in (${user_ids.join(', ')})`) | ||
const rowsGroupedByUserID = _.groupBy(rows, 'following_id'); | ||
return user_ids.map(id => rowsGroupedByUserID[id]); | ||
} | ||
|
||
async function batchGetUsers(user_ids) { | ||
logQuery('batchGetUsers'); | ||
const rows = await db.all(`SELECT * from Persons WHERE id in (${user_ids.join(', ')})`); | ||
const keyedRows = _.keyBy(rows, 'id'); | ||
return user_ids.map(id => keyedRows[id]); | ||
} | ||
|
||
async function getAllUsers() { | ||
logQuery('getAllUsers'); | ||
return db.all(`SELECT * FROM Persons`); | ||
} | ||
|
||
|
||
|
||
module.exports = { | ||
batchGetUsers: batchGetUsers, | ||
batchGetFollowers: batchGetFollowers, | ||
getAllUsers: getAllUsers | ||
}; | ||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const db = require('sqlite'); | ||
const _ = require('lodash'); | ||
const faker = require('faker'); | ||
let dbQueries = 0; | ||
async function createTables(db) { | ||
await db.run(` | ||
CREATE TABLE Persons ( | ||
id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
firstName TEXT, | ||
lastName TEXT | ||
); | ||
`); | ||
|
||
await db.run(` | ||
CREATE TABLE FollowerEdges ( | ||
user_id NOT_NULL INTEGER, | ||
follower_id NOT_NULL INTEGER, | ||
FOREIGN KEY(user_id) REFERENCES Persons(id) | ||
FOREIGN KEY(follower_id) REFERENCES Persons(id) | ||
PRIMARY KEY(user_id,follower_id) | ||
); | ||
`) | ||
|
||
return true; | ||
} | ||
|
||
async function mockData(db) { | ||
let statement = await db.prepare(`INSERT INTO Persons (firstName, lastName) VALUES (?, ?)`); | ||
_.range(9).forEach(i => statement.run(faker.name.firstName(), faker.name.lastName())); | ||
await statement.finalize(); | ||
const rows = await db.all(`SELECT * FROM Persons`); | ||
let edgesStatement = await db.prepare('INSERT INTO FollowerEdges (user_id, follower_id) VALUES (?, ?)'); | ||
rows.forEach(person => { | ||
rows.filter(r => r.id !== person.id).forEach(personToFollow => { | ||
edgesStatement.run(personToFollow.id, person.id); | ||
}) | ||
}); | ||
await edgesStatement.finalize(); | ||
|
||
} | ||
|
||
async function setupDB() { | ||
await db.open(':memory:') | ||
await createTables(db); | ||
await mockData(db); | ||
return Promise.resolve(true); | ||
//let followers = await batchGetFollowers(db, [1, 2]); | ||
//let users = await batchGetUsers(db, [1,2]); | ||
} | ||
|
||
module.exports = setupDB; | ||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
const express = require('express'); | ||
const graphqlHTTP = require('express-graphql'); | ||
const { buildSchema } = require('graphql'); | ||
const db = require('./db') | ||
const DataLoader = require('dataloader'); | ||
|
||
const userLoader = new DataLoader(async (keys) => { | ||
const rows = await db.batchGetUsers(keys); | ||
return rows.map(r => new User(r)); | ||
}); | ||
const followersLoader = new DataLoader(async (keys) => { | ||
const rows = await db.batchGetFollowers(keys); | ||
return rows.map(r => r.map(c =>new User(c))); | ||
}); | ||
// Construct a schema, using GraphQL schema language | ||
var schema = buildSchema(` | ||
type User { | ||
firstName: String! | ||
lastName: String! | ||
followers: [User] | ||
} | ||
type Query { | ||
users: [User] | ||
} | ||
`); | ||
|
||
// This class implements the RandomDie GraphQL type | ||
class User { | ||
constructor(data) { | ||
this.id = data.id; | ||
this.firstName = data.firstName; | ||
this.lastName = data.lastName; | ||
} | ||
|
||
async followers(a, b, c) { | ||
return followersLoader.load(this.id); | ||
return followers; | ||
} | ||
} | ||
|
||
// The root provides the top-level API endpoints | ||
var root = { | ||
users: async function () { | ||
const rows = await db.getAllUsers(); | ||
let result = rows.map(data => new User(data)); | ||
return result; | ||
} | ||
} | ||
|
||
var app = express(); | ||
app.use('/graphql', graphqlHTTP({ | ||
schema: schema, | ||
rootValue: root, | ||
graphiql: true, | ||
})); | ||
|
||
db.initialize().then(() => { | ||
app.listen(4000); | ||
console.log('Running a GraphQL API server at localhost:4000/graphql'); | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "graphql-dataloader-sqlite", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"start": "node index" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"dataloader": "^1.3.0", | ||
"express": "^4.16.2", | ||
"express-graphql": "^0.6.11", | ||
"faker": "^4.1.0", | ||
"graphql": "^0.11.7", | ||
"lodash": "^4.17.4", | ||
"sqlite": "^2.8.0", | ||
"sqlite3": "^3.1.13" | ||
} | ||
} |
Oops, something went wrong.