Skip to content

Commit

Permalink
GraphQL v15 config via extensions (#418)
Browse files Browse the repository at this point in the history
* Switch to using GraphQL 15's extensions for join-monster config in a schema

GraphQL 15 doesn't let schema authors attach arbitrary properties to schema objects anymore, so join-monster's config style has to change. There's an `extensions` property that works great for this, let's use that!

* Update docs to reflect new extensions configuration setup

* Bump join-monster version to indicate breaking change

* Update TypeScript types to export strongly typed extension interfaces

After graphql/graphql-js#2465 , we can now use TypeScript declaration merging to augment the graphql-types nice and cleanly. Woop woop!

* Add a changelog entry explaining how to migrate to the new extensions format

* Fix a couple broken TypeScript types for thunking and add TypeScript tests
  • Loading branch information
airhorns committed Aug 10, 2020
1 parent 71c831e commit c755902
Show file tree
Hide file tree
Showing 38 changed files with 2,471 additions and 1,161 deletions.
3 changes: 3 additions & 0 deletions bin/test
Expand Up @@ -104,5 +104,8 @@ if [ $PG = 1 ]; then
STRATEGY=mix MINIFY=1 npm run testpg-paging
fi

echo -e "${YELLOW} testing typescript definitions${NC}"
npm run testtsd

echo -e "${GREEN} PASSED ${NC}"

115 changes: 110 additions & 5 deletions docs/CHANGELOG.md
@@ -1,44 +1,117 @@
### v3.0.0 (unreleased)

**Breaking changes:**

- Update GraphQL requirement to version 15, which supports a new `extensions` property where join-monster config lives. The config keys and values are largely unchanged, but now they must be nested under an `extensions: { joinMonster: ... }}` property on the GraphQLObjectTypes and fields using join-monster. To upgrade, you must move any non-standard keys off of your `GraphQLObjectType`s or field configs into the `extensions` of the same field. So, something like this:

```javascript
const User = new GraphQLObjectType({
name: 'User',
sqlTable: 'users',
uniqueKey: 'id',
fields: () => ({
id: {
type: GraphQLInt
},
email: {
type: GraphQLString,
sqlColumn: 'email_address'
},
})
}
```
becomes this:
```javascript
const User = new GraphQLObjectType({
name: 'User',
extensions: {
joinMonster: {
sqlTable: 'users',
uniqueKey: 'id'
}
},
fields: () => ({
id: {
type: GraphQLInt
},
email: {
type: GraphQLString,
extensions: {
joinMonster: {
sqlColumn: 'email_address'
}
}
}
})
}
```
The resulting code is sadly more verbose, but the only supported way of layering in extra information to a GraphQL schema going forward, and safer in the presence of other GraphQL schema extensions.
**Note**: There are two configuration keys which have changed beyond just becoming nested in the `extensions` property:
- `jmIgnoreAll` has been renamed to `ignoreAll`
- `jmIgnoreTable` has been renamed to `ignoreTable`
The old names for these configuration options will no longer work so please be sure to update.
### v2.1.2 (May 25, 2020)
#### Fixed
#### Fixed
- Connections inside union fragments [#407](https://github.com/join-monster/join-monster/pull/407)
### v2.1.1 (Nov. 21, 2019)
#### Fixed
#### Fixed
- Updated vulnerable version of lodash (`eed0264`)
### v2.1.0 (Aug. 25, 2018)
- Numerous bug fixes
- TypeScript type definitions
- New 'mysql8' dialect which supports some pagination
### v2.0.13 (Sep. 4, 2017)
- Don't write to debug module unless it's actually enabled.
### v2.0.9 (Aug. 23, 2017)
- Properly format instances of Buffer.
### v2.0.8 (Aug. 16, 2017)
- Support duplicate fields without aliases off the query root type.
### v2.0.6 (Aug. 11, 2017)
- Add SQL AST node to sqlJoin callback signature.
### v2.0.5 (Aug. 11, 2017)
- Remove the use of `Proxy` to improve compatibility.
### v2.0.4 (Aug. 8, 2017)
- Add option for custom dialect modules.
- Various bug fixes.
### v2.0.0 (Jun. 25, 2017)
**New features:**
- `LIMIT` functionality, supported on all fields.
- Fetch columns from junction tables.
- For fields with junctions, you can now specify `WHERE` and `ORDER BY` clauses on the junction table or the main table, including paginated fields.
- Ability to dynamically choose pagination implementation per-request.
- Better ability to write `where` functions that depend on args and info from the parent/ancestors.
**Breaking changes:**
- Fields with junctions have a new interface in order to support the new features.
- Any `where`, `orderBy`, and `sortKey` on many-to-many paginated fields used to be applied to the junction table. This has changed, and will be applied to the main table instead in order to be consistent with non-paginated junctions. If the old behavior is desired, you can nest those properties inside the `junction` object, which is part of the new API.
- Change 4th parameter of `where` and `sqlExpr` to the field's SQL AST Node, which is a lot more useful.
Expand Down Expand Up @@ -134,30 +207,36 @@
// created_at: 'DESC',
// id: 'ASC'
//}

// you could also place a `where` at either
}
```
### v1.2.1 (Mar. 28, 2017)
- Add `jmIgnoreAll` and `jmIgnoreTable`.
- Make `sqlTable` a thunk.
- Bug fix with recursively nested union and interface type fragments.
- Bug fix with for batch on a single-type parent.
### v1.2.0 (Mar. 16, 2017)
- Add an API for GraphQLInterfaceType
### v1.1.1 (Mar. 13, 2017)
- Add an API for GraphQLUnionType
### v1.1.0 (Mar. 11, 2017)
- Add Oracle as supported dialect.
### v1.0.1 (Mar. 8, 2017)
- Add `ORDER BY` support for non-paginated fields.
### v1.0.0 (Feb. 28, 2017)
- Batching capabilities added.
- MariaDB can do pagination on batches.
- `sqlExpr` can now be asynchronous.
Expand All @@ -173,94 +252,120 @@
- `joinTable` is deprecated. It was renamed to `junctionTable` to avoid over-use of the word "join".
- `'standard'` dialect is deprecated because nothing really implements the standard. The new default is `'sqlite3'`.


### v0.9.10 (Feb. 16, 2017)
- Bug fixes with recursive fragments and argument parsing.
### v0.9.9 (Feb. 3, 2017)
- Add `context` to the `sqlJoin` parameters.
- Support async in `sqlJoin`.
### v0.9.8 (Feb. 2, 2017)
- Expose parent table aliases to `where` function.
### v0.9.5 (Jan. 24, 2017)
- Fix bug for Postgres where `CONCAT` returns `''` instead of `NULL`.
### v0.9.4 (Jan. 22, 2017)
- Expose GraphQL args to `sqlJoin` function.
### v0.9.3 (Jan. 14, 2017)
- Add support for fragments on interface types.
### v0.9.2 (Jan. 5, 2017)
- Fix bug when composite keys contain timestamps or dates in PG dialect.
- Patch SQL injection risk.
### v0.9.0 (Jan. 4, 2017)
- More automatic fetching using `getNode` implemented.
### v0.8.0 (Dec. 19, 2016)
- Expose the `getSQL` method for getting only the converted SQL.
### v0.7.0 (Dec. 16, 2016)
- Introducing raw SQL expressions for computed columns.
### v0.6.0 (Dec. 2, 2016)
- Support asynchronicity in the `where` function.
### v0.5.8 (Dec. 1, 2016)
- Add null check to node interface handler.
### v0.5.7 (Nov. 29, 2016)
- Fix bug with `WHERE` conditions on paginated fields.
### v0.5.6 (Nov. 14, 2016)
- Fix bug with query variables on the Node interface.
### v0.5.5 (Nov. 13, 2016)
- Add support for dynamic sort keys on paginated fields. Sort keys can now be functions that receive the GraphQL arguments.
### v0.5.4 (Nov. 10, 2016)
- Add support for query variables.
### v0.5.2 (Nov. 6, 2016)
- Relay connection type names are no longer required to end with "Connection".
### v0.5.1 (Nov. 5, 2016)
- Fix problem with introspection queries.
### v0.5.0 (Nov. 4, 2016)
- Add dialect for MySQL/MariaDB.
### v0.4.1 (Oct 21, 2016)
- Fix bug with de-duplication of objects.
### v0.4.0 (Oct 20, 2016)
- Add Postgres dialect option.
- Support SQL pagination based on integer offsets.
- Support SQL pagination based on a sort key(s).
### v0.3.7 (Oct 16, 2016)
- Fix bug with nested fragments.
### v0.3.6 (Oct 13, 2016)
- Option to minify the raw data column names.
### v0.3.5 (Oct 9, 2016)
- Add test coverage tools.
### v0.3.4 (Oct 6, 2016)
- Add helper method for getting data for Relay's Node type.
- Fix bug with Union and Interface types.
### v0.3.2 (Oct 5, 2016)
- Add support for specifying schema names for your SQL tables.
### v0.3.1 (Oct 4, 2016)
- Detect Relay connection type and fetch data for it.
### v0.3.0 (Oct 3, 2016)
- Unique keys required for every table. Necessary for achieving good performance during object shaping/nesting.
- Composite keys supported for the unique key.
21 changes: 15 additions & 6 deletions docs/aggregation.md
Expand Up @@ -13,8 +13,13 @@ const Post = new GraphQLObjectType({
description: 'The number of comments on this post',
type: GraphQLInt,
// use a correlated subquery in a raw SQL expression to do things like aggregation
sqlExpr: postTable => `(SELECT count(*) FROM comments WHERE post_id = ${postTable}.id AND archived = FALSE)`
},
extensions: {
joinMonster: {
sqlExpr: postTable =>
`(SELECT count(*) FROM comments WHERE post_id = ${postTable}.id AND archived = FALSE)`
}
}
}
})
})
```
Expand Down Expand Up @@ -57,8 +62,13 @@ const Post = new GraphQLObjectType({
fields: () => ({
commentsWithoutJoin: {
type: new GraphQLList(SimpleComment),
sqlExpr: postTable => `(SELECT json_agg(comments) FROM comments WHERE comments.post_id = ${postTable}.id AND comments.archived = FALSE)`
},
extensions: {
joinMonster: {
sqlExpr: postTable =>
`(SELECT json_agg(comments) FROM comments WHERE comments.post_id = ${postTable}.id AND comments.archived = FALSE)`
}
}
}
})
})
```
Expand All @@ -76,7 +86,7 @@ This should work without any additional data munging if you're using `knex`, as
commentsWithoutJoin {
id
body
authorId
authorId
}
}
}
Expand All @@ -98,4 +108,3 @@ FROM accounts AS "user"
LEFT JOIN posts AS "posts" ON "user".id = "posts".author_id
WHERE "user".id = 2
```

0 comments on commit c755902

Please sign in to comment.