Skip to content

Commit 7be0269

Browse files
Minor refactoring to support multiple SchemaBuilder options (#3)
* Minor refactoring to support multiple SchemaBuilder options * code format and update Readme file --------- Co-authored-by: Firass Ziedan <firass.ziedan@gmail.com>
1 parent 0f8f8f8 commit 7be0269

File tree

3 files changed

+57
-49
lines changed

3 files changed

+57
-49
lines changed

README.md

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -89,30 +89,30 @@ a `where age <= 100` clause. In addition to the property filters, there are some
8989

9090
```js
9191
const { graphQlSchema } = require('./graphql') // your graphql schema
92-
const graphQlSchemaResult = await graphQlSchema()
93-
const { createHandler } = require('graphql-http/lib/use/express')
94-
95-
app.use('/graphql', (req, res, next) => {
96-
res.set('Content-Security-Policy', 'default-src *; style-src \'self\' http://* \'unsafe-inline\'; script-src \'self\' http://* \'unsafe-inline\' \'unsafe-eval\'')
97-
98-
next()
99-
}, createHandler({
100-
schema: graphQlSchemaResult, context: (req, res, params) => ({ req, res, params })
101-
}))
92+
const graphQlSchemaResult = await graphQlSchema()
93+
const { createHandler } = require('graphql-http/lib/use/express')
94+
95+
app.use('/graphql', (req, res, next) => {
96+
res.set('Content-Security-Policy', 'default-src *; style-src \'self\' http://* \'unsafe-inline\'; script-src \'self\' http://* \'unsafe-inline\' \'unsafe-eval\'')
97+
98+
next()
99+
}, createHandler({
100+
schema: graphQlSchemaResult, context: (req, res, params) => ({ req, res, params })
101+
}))
102102
```
103103

104104
#### [express-graphql](https://www.npmjs.com/package/express-graphql) (deprecated)
105105

106106
```js
107107
const { graphQlSchema } = require('./graphql') // your graphql schema
108-
const graphQlSchemaResult = await graphQlSchema()
109-
const { graphqlHTTP } = require('express-graphql')
110-
111-
app.use('/graphql', (req, res, next) => {
112-
res.set('Content-Security-Policy', 'default-src *; style-src \'self\' http://* \'unsafe-inline\'; script-src \'self\' http://* \'unsafe-inline\' \'unsafe-eval\'')
113-
114-
next()
115-
}, graphqlHTTP({ schema: graphQlSchemaResult }))
108+
const graphQlSchemaResult = await graphQlSchema()
109+
const { graphqlHTTP } = require('express-graphql')
110+
111+
app.use('/graphql', (req, res, next) => {
112+
res.set('Content-Security-Policy', 'default-src *; style-src \'self\' http://* \'unsafe-inline\'; script-src \'self\' http://* \'unsafe-inline\' \'unsafe-eval\'')
113+
114+
next()
115+
}, graphqlHTTP({ schema: graphQlSchemaResult }))
116116
```
117117

118118
# Getting started
@@ -194,11 +194,11 @@ It will use the model's table schema to generate the structure of the jsonSchema
194194

195195
# Extending your schema with mutations
196196

197-
Often you need to provide mutations in your GraphQL schema. At the same time mutations can be quite opinionated with
197+
Often you need to provide mutations in your GraphQL schema. At the same time, mutations can be quite opinionated with
198198
side effects and complex business logic, so plain CUD implementation is not always a good idea.
199199
Therefore, we provide a method `extendWithMutations` which allows you to extend the generated query schema with
200200
mutations. You can provide a root `GraphQLObjectType` or a function as the first argument for this method.
201-
Function in this case plays as a strategy which receives current builder as a first argument and
201+
Function in this case plays as a strategy that receives the current builder as a first argument and
202202
returns `GraphQLObjectType`.
203203

204204
```js
@@ -270,8 +270,8 @@ schema = mainModule
270270
# Extending your schema with subscriptions
271271

272272
When you want to implement a real-time behavior in your app like push notifications, you basically have two options in
273-
graphql: subscriptions and live queries. The first approach is focused on events and granular control over updates,
274-
while the other is based on smart live queries, where most of real-time magic is hidden from the client. We'd like to
273+
GraphQl: subscriptions and live queries. The first approach focuses on events and granular control over updates,
274+
while the other is based on smart live queries, where most real-time magic is hidden from the client. We'd like to
275275
stick with the first approach since there are some decent implementations out there
276276
like [graphql-subscriptions](https://github.com/apollographql/graphql-subscriptions) by Apollo.
277277

@@ -358,8 +358,8 @@ const graphQlSchema = graphQlBuilder()
358358

359359
Now you would have `myProp_lt: value` instead of the default `myPropLt: value`.
360360

361-
By default, the model names are pluralized by adding an `s` to the end of the camelized table name. You can set a custom
362-
plural and singular names for the root fields like so:
361+
By default, the model names are pluralized by adding an `s` to the end of the caramelized table name.
362+
You can set a custom plural and singular names for the root fields like so:
363363

364364
```js
365365
const graphQlSchema = graphQlBuilder()
@@ -411,21 +411,22 @@ Allows you to customize **Objection** query builder behavior. For instance, you
411411
options argument. So, each time the builder is called, it will be called with **skipUndefined** enabled.
412412
This can be useful when you use [graphql-tools](https://github.com/apollographql/graphql-tools) schema stitching.
413413

414-
## Cacheing
414+
## Caching
415415

416-
We add a cache layer to the graphql builder.
416+
We add a cache layer to the GraphQl builder.
417417
This is useful when you have a lot of queries that are similar.
418418
You can enable the cache by passing a cache object to the builder.
419419

420-
Specifying Cache options when building the GraphQL schema is not necessary but it can drastically improve performance
421-
GraphQL Caching options are : `host, port, redisKeyPrefix, timeout`
420+
Specifying Cache options when building the GraphQL schema is not necessary, but it can drastically improve performance
421+
GraphQL Caching options are: `host, port, redisKeyPrefix, timeout`
422422

423423
`host` and `port` specify the host and port of your Redis connection
424424

425-
`redisKeyPrefix` is a prefix for all the cached Redis keys, default value is 'gqlCache'
425+
`redisKeyPrefix` is a prefix for all the cached Redis keys, the default value is 'gqlCache'
426426

427-
`timeout` specifies the age of each cached Redis key in seconds, defaults to 1 hour, you might need to change this value
428-
in case your system often faces data updates
427+
`timeout` specifies the age of each cached Redis key in seconds, and defaults to 1 hour, you might need to change this
428+
value
429+
in case your system often faces data updates.
429430

430431
```js
431432
const graphql = require('graphql').graphql;
@@ -438,11 +439,15 @@ const Review = require('./models/Review');
438439

439440
const graphQlSchema = async() => {
440441
const builder = await graphQlBuilder({
441-
host: 'localhost',
442-
port: 6379,
443-
redisKeyPrefix: 'gqlCache',
444-
timeout: 10
445-
}).allModels([Movie, Person, Review]);
442+
// Builder options, currently only 'redis' is available
443+
redis: {
444+
host: 'localhost',
445+
port: 6379,
446+
redisKeyPrefix: 'gqlCache',
447+
cacheTimeout: 10
448+
}
449+
}
450+
).allModels([Movie, Person, Review]);
446451

447452
return builder.build();
448453
};

lib/SchemaBuilder.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const KIND_VARIABLE = 'Variable'
2626

2727
class SchemaBuilder {
2828
constructor(options) {
29-
this.cache = new Cache(options)
29+
this.cache = new Cache(options?.redis)
3030
this.models = {}
3131
this.typeCache = {}
3232
this.filterIndex = 1
@@ -342,7 +342,7 @@ class SchemaBuilder {
342342
}
343343

344344
const result = await builder.then(toJson)
345-
this.cache ? await this.cache?.cacheResult(request, result) : null
345+
this.cache && result ? await this.cache?.cacheResult(request, result) : null
346346
return result
347347
}
348348
}

lib/cache/caching.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@ const redis = require('redis')
22
const md5 = require('md5')
33

44
class Cache {
5-
constructor(options) {
6-
if (options) {
7-
if (!(typeof options === 'object') || Array.isArray(options)) {
5+
constructor(redisOptions) {
6+
if (redisOptions) {
7+
if (!(typeof redisOptions === 'object') || Array.isArray(redisOptions)) {
88
throw new Error('Caching options must be an object')
99
} else {
1010
const allowedKeys = ['host', 'port', 'cacheTimeout', 'redisKeyPrefix']
11-
Object.keys(options).forEach(key => {
11+
Object.keys(redisOptions).forEach(key => {
1212
if (!allowedKeys.includes(key)) {
1313
throw new Error(`${key} is not a valid option for GraphQL caching`)
1414
}
1515
})
1616
}
1717

18-
this.validate(options)
18+
this.validate(redisOptions)
1919
this.redisClient = redis.createClient({
20-
port: Number(options.port),
21-
host: options.host
20+
port: Number(redisOptions.port),
21+
host: redisOptions.host
2222
})
23-
this.redisKeyPrefix = options.redisKeyPrefix || 'gqlCache'
24-
this.timeout = Number(options.cacheTimeout) || 3600
23+
this.redisKeyPrefix = redisOptions.redisKeyPrefix || 'gqlCache'
24+
this.timeout = Number(redisOptions.cacheTimeout) || 3600
2525
}
2626
}
2727

@@ -34,10 +34,13 @@ class Cache {
3434
throw new Error('Invalid Redis host')
3535
}
3636

37-
if (options.timeout) {
38-
if (!(typeof +options.timeout === 'number')) {
37+
if (options.cacheTimeout) {
38+
if (!(typeof +options.cacheTimeout === 'number') || isNaN(Number(options.cacheTimeout))) {
3939
throw new Error('Invalid Timeout value, timeout is not a number')
4040
}
41+
if (+options.cacheTimeout <= 0) {
42+
throw new Error('Invalid Timeout value, timeout must be larger than zero')
43+
}
4144
}
4245
this.enabled = true
4346
}

0 commit comments

Comments
 (0)