Skip to content

Commit bf2b620

Browse files
committed
removed memoize directive since not sure when this would be optional anyway
1 parent 31a7fc6 commit bf2b620

File tree

13 files changed

+130
-177
lines changed

13 files changed

+130
-177
lines changed

Diff for: .gitignore

-3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,3 @@ Thumbs.db
8585
.Spotlight-V100
8686
.Trashes
8787
package-lock.json
88-
89-
examples2
90-
examples3

Diff for: .npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

Diff for: README.md

+10-22
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
Reference implementation around the concept of a partial schema / component similar to that discussed [here](https://medium.com/homeaway-tech-blog/distributed-graphql-schema-development-npm-modules-d734a3cb6f12).
44

5-
This is very similar to the excellent `graphql-modules` project — but closer to our own internal paradigm already in use for over a year and a half and adds some missing features such as `exclude` from `imports`.
5+
This is very similar to the excellent `graphql-modules` project — but a little closer to our own internal paradigm already in use for over a year and a half and adds some features such as `exclude` root types from `imports` and memoize resolvers.
6+
7+
In fact, this module utilizes the `graphql-toolkit` developed by the `graphql-modules` team to merge types and resolvers.
68

79
### The future
810

9-
For now it is alpha and experimental.
11+
Experimental / alpha for now.
1012

1113
### Repository structure
1214

@@ -31,11 +33,11 @@ To intercept resolvers with mocks execute this app with `GRAPHQL_DEBUG=1` enable
3133
# Usage
3234

3335
```javascript
34-
new GraphQLComponent({
36+
new GraphQLComponent({
3537
// A string or array of strings representing typeDefs and rootTypes
3638
types,
3739
// An object containing resolver functions
38-
resolvers,
40+
resolvers,
3941
// An optional object containing resolver dev/test fixtures
4042
mocks,
4143
// An optional array of imported components for the schema to be merged with
@@ -58,7 +60,7 @@ This will create an instance object of a component containing the following func
5860

5961
### Encapsulating state
6062

61-
Typically the best way to make a re-useable component will be to extend `GraphQLComponent`.
63+
Typically the best way to make a re-useable component will be to extend `GraphQLComponent`.
6264

6365
```javascript
6466
const GraphQLComponent = require('graphql-component');
@@ -77,7 +79,7 @@ module.exports = PropertyComponent;
7779

7880
This will allow for configuration (in this example, `useMocks` and `preserveTypeResolvers`) as well as instance data per component (such as data base clients, etc).
7981

80-
### Aggregation
82+
### Aggregation
8183

8284
Example to merge multiple components:
8385

@@ -116,20 +118,6 @@ const { schema, context } = new GraphQLComponent({
116118

117119
This will keep from leaking unintended surface area.
118120

119-
### Resolver memoization
120-
121-
Schemas in graphql components will support the `@memoize` directive. This will allow resolvers to be memoized within the
122-
scope of a particular request context to reduce the number of times a resolver must run for the same data.
123-
124-
Example:
125-
126-
```graphql
127-
type Query {
128-
# Seach for an author by id.
129-
author(id: ID!, version: String) : Author @memoize
130-
}
131-
```
132-
133121
### Adding to context
134122

135123
Example context argument:
@@ -161,6 +149,6 @@ Using `context` now in `apollo-server-hapi` for example, will transform the cont
161149

162150
### Mocks
163151

164-
graphql-component accepts mocks in much the same way that Apollo does but with one difference.
152+
graphql-component accepts mocks in much the same way that Apollo does but with one difference.
165153

166-
Instead of accepting a mocks object, it accepts `(importedMocks) => mocksObject` argument. This allows components to utilize the mocks from other imported components easily.
154+
Instead of accepting a mocks object, it accepts `(importedMocks) => mocksObject` argument. This allows components to utilize the mocks from other imported components easily.

Diff for: lib/index.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,32 @@
33
const GraphQLTools = require('graphql-tools');
44
const GraphQLToolkit = require('graphql-toolkit');
55
const Resolvers = require('./resolvers');
6-
//const { MemoizeDirective } = require('./memoize');
76
const Context = require('./context');
87
const Types = require('./types');
98
const Merge = require('./merge');
9+
1010
const debug = require('debug')('graphql-component:schema');
1111

1212
class GraphQLComponent {
13-
constructor({
14-
types = [],
15-
resolvers = {},
16-
imports = [],
17-
mocks = () => ({}),
18-
directives = {},
19-
context = {},
13+
constructor({
14+
types = [],
15+
resolvers = {},
16+
imports = [],
17+
mocks = () => ({}),
18+
directives = {},
19+
context = {},
2020
useMocks = false,
2121
preserveTypeResolvers = false
2222
} = {}) {
2323
debug(`creating component`);
2424

2525
this._types = Array.isArray(types) ? types : [types];
26-
26+
2727
this._resolvers = Resolvers.wrapResolvers(this, resolvers);
28-
28+
2929
this._imports = [];
30-
31-
this._directives = Object.assign({}, directives/*not doing this as a directive right now, { memoize: MemoizeDirective }*/);
30+
31+
this._directives = directives;
3232

3333
this._context = Context.builder(this, context);
3434

@@ -39,7 +39,7 @@ class GraphQLComponent {
3939
if (GraphQLComponent.isComponent(imp)) {
4040
importedTypes.push(...Types.getImportedTypes(imp));
4141
importedResolvers.push(Resolvers.getImportedResolvers(imp));
42-
this._imports.push(imp);
42+
this._imports.push(imp);
4343
continue;
4444
}
4545

@@ -55,10 +55,10 @@ class GraphQLComponent {
5555
importedTypes.push(...Types.getImportedTypes(imp.component, excludes));
5656
importedResolvers.push(Resolvers.transformResolvers(Resolvers.getImportedResolvers(imp.component), excludes));
5757
}
58-
58+
5959
this._imports.push(imp.component);
6060
}
61-
61+
6262
this._importedTypes = importedTypes;
6363
this._importedResolvers = GraphQLToolkit.mergeResolvers(importedResolvers);
6464

@@ -87,7 +87,7 @@ class GraphQLComponent {
8787

8888
if (this._useMocks) {
8989
debug(`adding mocks, preserveTypeResolvers=${this._preserveTypeResolvers}`);
90-
90+
9191
const mocks = Object.assign({}, this._importedMocks, this._mocks);
9292

9393
GraphQLTools.addMockFunctionsToSchema({ schema, mocks, preserveTypeResolvers: this._preserveTypeResolvers });
@@ -109,4 +109,4 @@ class GraphQLComponent {
109109
}
110110
}
111111

112-
module.exports = GraphQLComponent;
112+
module.exports = GraphQLComponent;

Diff for: lib/memoize.js

-59
This file was deleted.

Diff for: lib/merge.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ const mergeResolvers = function (resolvers = {}, merge = {}) {
1515
return merged;
1616
};
1717

18-
module.exports = { mergeResolvers };
18+
module.exports = { mergeResolvers };

Diff for: lib/resolvers.js

+34-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,40 @@
11
'use strict';
22

33
const Merge = require('./merge');
4-
const { memoize } = require('./memoize');
4+
55
const debug = require('debug')('graphql-component:resolver');
66

7+
const memoize = function (parentType, fieldName, resolve) {
8+
const _cache = new WeakMap();
9+
10+
return function (_, args, context, info ) {
11+
const key = JSON.stringify(args);
12+
13+
debug(`executing ${parentType}.${fieldName}`);
14+
15+
let cached = _cache.get(context);
16+
17+
if (cached && cached[key]) {
18+
debug(`return cached result of memoized ${parentType}.${fieldName}`);
19+
return cached[key];
20+
}
21+
22+
if (!cached) {
23+
cached = {};
24+
}
25+
26+
const result = resolve(_, args, context, info);
27+
28+
cached[key] = result;
29+
30+
_cache.set(context, cached);
31+
32+
debug(`cached ${parentType}.${fieldName}`);
33+
34+
return result;
35+
};
36+
};
37+
738
const transformResolvers = function (resolvers, excludes) {
839
const filteredResolvers = Object.assign({}, resolvers);
940

@@ -36,7 +67,7 @@ const wrapResolvers = function (bind, resolvers = {}) {
3667
}
3768
if (['Query', 'Mutation', 'Subscription'].indexOf(name) > -1) {
3869
debug(`memoized ${name}.${resolverName}`);
39-
wrapped[name][resolverName] = memoize(resolverName, func.bind(bind));
70+
wrapped[name][resolverName] = memoize(name, resolverName, func.bind(bind));
4071
continue;
4172
}
4273
wrapped[name][resolverName] = func.bind(bind);
@@ -64,4 +95,4 @@ const getImportedResolvers = function (imp) {
6495
return importedResolvers;
6596
};
6697

67-
module.exports = { transformResolvers, wrapResolvers, getImportedResolvers };
98+
module.exports = { memoize, transformResolvers, wrapResolvers, getImportedResolvers };

Diff for: lib/types.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const Gql = require('graphql-tag');
4+
45
const debug = require('debug')('graphql-component:types');
56

67
const check = function (operation, fieldName, excludes) {
@@ -43,4 +44,4 @@ const getImportedTypes = function (component, excludes) {
4344
return exclude([...types, ...importedTypes], excludes);
4445
};
4546

46-
module.exports = { exclude, check, getImportedTypes };
47+
module.exports = { exclude, check, getImportedTypes };

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-component",
3-
"version": "0.0.1-alpha.15",
3+
"version": "0.0.1-alpha.16",
44
"description": "",
55
"main": "lib/index.js",
66
"scripts": {

Diff for: test/examples/example-listing/listing-component/index.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class ListingComponent extends GraphQLComponent {
1212
const propertyComponent = new Property();
1313
const reviewsComponent = new Reviews();
1414

15-
super ({
16-
types: Types,
17-
resolvers: Resolvers,
15+
super ({
16+
types: Types,
17+
resolvers: Resolvers,
1818
mocks: Mocks,
1919
imports: [
2020
{
@@ -36,4 +36,4 @@ class ListingComponent extends GraphQLComponent {
3636
}
3737
}
3838

39-
module.exports = ListingComponent;
39+
module.exports = ListingComponent;

Diff for: test/examples/example-listing/listing-component/mocks.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const mocks = (importedMocks) => {
1111
importedMocks.Review()
1212
]
1313
})
14-
}
14+
};
1515
};
1616

1717
module.exports = mocks;

0 commit comments

Comments
 (0)