Skip to content

Commit

Permalink
feat(DataLoader): Added override with DataLoader on .get($findById)
Browse files Browse the repository at this point in the history
  • Loading branch information
st0ffern committed Feb 9, 2017
1 parent 66b3fcf commit 5b91afe
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"env": {
"development": {
"passPerPreset": true,
"presets": [
{ "plugins": [ "transform-runtime" ] },
{
"passPerPreset": false,
"presets": ["es2015"]
}
],
"plugins": [
"syntax-async-functions",
"transform-regenerator",
"transform-class-properties",
"transform-object-rest-spread",
"transform-flow-strip-types"
]
},
"es": {
"presets": [
["es2015", {"modules": false}]
],
"plugins": [
"syntax-async-functions",
["transform-regenerator", {
"async": false
}],
"transform-class-properties",
"transform-object-rest-spread",
"transform-flow-strip-types",
]
}
}
}
33 changes: 33 additions & 0 deletions lib/composeWithDataLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.composeWithDataLoader = composeWithDataLoader;

var _graphqlCompose = require('graphql-compose');

function composeWithDataLoader(typeComposer) {

if (!(typeComposer instanceof _graphqlCompose.TypeComposer)) {
throw new Error('You should provide TypeComposer instance to composeWithDataLoader method');
}

/**
* get resolvers to add DataLoader to
*/
var count = typeComposer.get('$count');
var findById = typeComposer.get('$findById');
var findByIds = typeComposer.get('$findByIds');
var findMany = typeComposer.get('$findMany');
var findOne = typeComposer.get('$findOne');
console.log(typeComposer.getTypeName());

if (!findById) throw new Error('TypeComposer(' + typeComposer.getTypeName() + ') provided to composeWithRelay ' + 'should have findById resolver.');
if (!findById) throw new Error('TypeComposer(' + typeComposer.getTypeName() + ') provided to composeWithRelay ' + 'should have findById resolver.');
if (!findByIds) throw new Error('TypeComposer(' + typeComposer.getTypeName() + ') provided to composeWithRelay ' + 'should have findByIds resolver.');
if (!findMany) throw new Error('TypeComposer(' + typeComposer.getTypeName() + ') provided to composeWithRelay ' + 'should have findMany resolver.');
if (!findOne) throw new Error('TypeComposer(' + typeComposer.getTypeName() + ') provided to composeWithRelay ' + 'should have findOne resolver.');

return typeComposer;
}
11 changes: 11 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.composeWithDataLoader = undefined;

var _composeWithDataLoader = require('./composeWithDataLoader');

exports.default = _composeWithDataLoader.composeWithDataLoader;
exports.composeWithDataLoader = _composeWithDataLoader.composeWithDataLoader;
74 changes: 74 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "graphql-compose-dataloader",
"version": "0.0.1",
"description": "Add DataLoader to graphql-composer resolvers.",
"main": "lib/index.js",
"jsnext:main": "es/index.js",
"scripts": {
"build": "npm run build-cjs && npm run build-es",
"build-cjs": "rimraf lib && babel src --ignore __tests__,__mocks__ -d lib",
"build-es": "rimraf es && BABEL_ENV=es babel src --ignore __tests__,__mocks__ -d es",
"link": "yarn link graphql-compose && yarn link",
"unlink": "yarn unlink graphql-compose && yarn add graphql-compose",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"graphql",
"compose",
"schema",
"dataloader",
"graphql-schema",
"graphql-compose"
],
"repository": {
"type": "git",
"url": "git+https://github.com/stoffern/graphql-compose-dataloader.git"
},
"author": "stoffern",
"license": "MIT",
"bugs": {
"url": "https://github.com/stoffern/graphql-compose-dataloader/issues"
},
"homepage": "https://github.com/stoffern/graphql-compose-dataloader#readme",
"dependencies": {
"dataloader": "^1.3.0",
"string-hash": "^1.1.1"
},
"peerDependencies": {
"graphql": ">=0.9.0",
"graphql-compose": ">=1.4.0"
},
"devDependencies": {
"babel-cli": "^6.22.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.1.1",
"babel-plugin-syntax-async-functions": "6.13.0",
"babel-plugin-transform-class-properties": "^6.22.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.22.0",
"babel-plugin-transform-regenerator": "^6.22.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-es2015": "^6.22.0",
"graphql-compose": "^1.10.0",
"nyc": "^10.1.2",
"rimraf": "2.5.4",
"cz-conventional-changelog": "^1.2.0"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"nyc": {
"exclude": [
"**/__mocks__/**",
"**/__tests__/**",
"resources",
"node_modules"
],
"reporter": [
"lcov",
"text"
]
}
}
33 changes: 33 additions & 0 deletions src/composeWithDataLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { TypeComposer } from 'graphql-compose'
import DataLoader from 'dataloader'
import {
wrapFindById,
wrapFindByIds,
wrapConnection,
wrapFindMany,
} from './resolvers'

import {
dataloaderOptions
} from './definitions'

export function composeWithDataLoader(
typeComposer: TypeComposer,
options: dataloaderOptions = {}
): TypeComposer {


// if (!(typeComposer instanceof TypeComposer)) {
// throw new Error('You should provide TypeComposer instance to composeWithDataLoader method');
// }

/**
* get resolvers to add DataLoader to
*/
typeComposer = wrapFindById(typeComposer, options)
typeComposer = wrapFindByIds(typeComposer, options)
typeComposer = wrapFindMany(typeComposer, options)
typeComposer = wrapConnection(typeComposer, options)

return typeComposer
}
4 changes: 4 additions & 0 deletions src/definitions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type dataloaderOptions = {
cacheExpiration?: number,
debug?: bool,
}
6 changes: 6 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {composeWithDataLoader} from './composeWithDataLoader'

export default composeWithDataLoader
export {
composeWithDataLoader
}
103 changes: 103 additions & 0 deletions src/resolvers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import DataLoader from 'dataloader'
import hash from 'object-hash'
import SingleContinous from './singleContinous'


export const wrapFindById = function (tc, opt){
let resolver = tc.getResolver('findById')
let loader = new DataLoader( (resolveParamsArray) =>
new Promise( (resolve, reject) => {
if (opt.debug) console.log('New db request (findById)')
let params = resolveParamsArray[0]
delete params.projection;
let res = resolver.resolve(params)
resolve([res])
}),
{ cacheKeyFn: key => key.args._id.toString() })

tc.setResolver(
'findById',
resolver.wrapResolve(fn => rp => {
SingleContinous.run(loader, rp, opt)
return loader.load(rp)
})
)
return tc
}

// export const wrapFindByIds = function (tc, opt){
// let resolver = tc.getResolver('findByIds')
// let loader = new DataLoader( (resolveParamsArray) =>
// new Promise( (resolve, reject) => {
// if (opt.debug) console.log('New db request (findByIds)')
// let params = resolveParamsArray[0]
// params.args._ids = resolveParamsArray.map(params => params.args._id)
// delete params.projection;
// let res = resolver.resolve(params)
// resolve([res])
// }),
// { cacheKeyFn: key => key.args._id.toString() })

// tc.setResolver(
// 'findByIds',
// resolver.wrapResolve(fn => rp => {
// SingleContinous.run(loader, rp, opt)
// return loader.load(rp)
// })
// )
// return tc
// }

// export const wrapConnection = function (tc, opt){
// let resolver = tc.getResolver('connection')
// let loader = new DataLoader( (resolveParamsArray) =>
// new Promise( async (resolve, reject) => {
// console.log('resolveParamsArray')
// console.log(resolveParamsArray[0].rawQuery._id)
// if (opt.debug) console.log('New db request (connection)')
// let params = resolveParamsArray[0]
// delete params.projection;
// let res = await resolver.resolve(params)
// console.log(res)
// console.log(res.edges[0].node)
// resolve([res])
// }),
// { cacheKeyFn: key => {
// let hashKey = hash(key.args)
// return hashKey
// } })

// tc.setResolver(
// 'connection',
// resolver.wrapResolve(fn => rp => {
// SingleContinous.run(loader, rp, opt)
// return loader.load(rp)
// })
// )
// return tc
// }

// export const wrapFindMany = function (tc, opt){
// let resolver = tc.getResolver('findMany')
// let loader = new DataLoader( (resolveParamsArray) =>
// new Promise( (resolve, reject) => {
// if (opt.debug) console.log('New db request (findMany)')
// let params = resolveParamsArray[0]
// delete params.projection;
// let res = resolver.resolve(params)
// resolve(res)
// }),
// { cacheKeyFn: key => {
// let hashKey = hash(key.args)
// return hashKey
// } })

// tc.setResolver(
// 'findMany',
// resolver.wrapResolve(fn => rp => {
// SingleContinous.run(loader, rp, opt)
// return loader.load(rp)
// })
// )
// return tc
// }
30 changes: 30 additions & 0 deletions src/singleContinous.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import objectHash from 'object-hash'
import stringHash from 'string-hash'

/**
* This class makes shure functions with params only run once
*/
export default new class SingleContinous{

constructor(props) {
this.store = new Map()
this.counter = 1
}

run(loader, rp, opt){
let hashKey = stringHash(JSON.stringify(loader)+JSON.stringify(rp))

if (!this.store.has(hashKey)){
this.store.set(hashKey, 'running')
setTimeout(() => {
let res = loader.clear(rp)
this.store.delete(hashKey)
},opt.cacheExpiration)
}
}

clearAll(){
this.store.clear()
return true
}
}

0 comments on commit 5b91afe

Please sign in to comment.