Skip to content

Commit

Permalink
feat(graphql): add relay mutation types support (#68)
Browse files Browse the repository at this point in the history
* feat(graphql): delete mutation now return deleted id

Instead of just returning the node that was deleted it also
returns the id so relay can then delete the node from its store.

* feat(graphql): insert mutation returns edge

The insert mutation now also returns the newly created edge. The cursor
is determined either from the orderBy field argument of the edge
or if this is not present it takes the primary key of the table.
  • Loading branch information
ferdinandsalis authored and calebmer committed Jun 15, 2016
1 parent 02b1058 commit f44ab99
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/graphql/createConnectionArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default createConnectionArgs
* @returns {GraphQLEnumType}
*/
// TODO: Some way to eliminate some columns from ordering enum?
const createTableOrderingEnum = memoize(table =>
export const createTableOrderingEnum = memoize(table =>
new GraphQLEnumType({
name: `${table.getTypeName()}Ordering`,
description: `Properties with which ${table.getMarkdownTypeName()} can be ordered.`,
Expand Down
3 changes: 2 additions & 1 deletion src/graphql/createConnectionType.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const createTableConnectionType = memoize(table =>

export default createTableConnectionType

const createTableEdgeType = table =>
export const createTableEdgeType = memoize(table =>
new GraphQLObjectType({
name: `${table.getTypeName()}Edge`,
description: `An edge in the \`${table.getTypeName()}Connection\`.`,
Expand All @@ -61,3 +61,4 @@ const createTableEdgeType = table =>
},
},
})
)
17 changes: 17 additions & 0 deletions src/graphql/mutation/createDeleteMutationField.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {
GraphQLNonNull,
GraphQLObjectType,
GraphQLID,
GraphQLInputObjectType,
} from 'graphql'

import { fromPairs } from 'lodash'
import { $$rowTable } from '../../symbols.js'
import SQLBuilder from '../../SQLBuilder.js'
import getType from '../getType.js'
import { toID } from '../types.js'
import createTableType from '../createTableType.js'
import getPayloadInterface from './getPayloadInterface.js'
import getPayloadFields from './getPayloadFields.js'
Expand Down Expand Up @@ -62,10 +64,25 @@ const createPayloadType = table =>
description: `The deleted ${table.getMarkdownTypeName()}.`,
resolve: source => source.output,
},
[`deleted${table.getTypeName()}Id`]: {
type: GraphQLID,
description: `The deleted ${table.getMarkdownTypeName()} id.`,
resolve: resolveDeletedFieldId(table),
},
...getPayloadFields(table.schema),
},
})

// Resolves the id from the primary keys of the deleted resource
const resolveDeletedFieldId = table => ({ output }) => {
if (!output)
return null

const primaryKeys = table.getPrimaryKeys()
const deletedIds = primaryKeys.map(pkey => output[pkey.name])
return toID(table.name, deletedIds)
}

const resolveDelete = table => {
const primaryKeys = table.getPrimaryKeys()

Expand Down
29 changes: 27 additions & 2 deletions src/graphql/mutation/createInsertMutationField.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { $$rowTable } from '../../symbols.js'
import SQLBuilder from '../../SQLBuilder.js'
import getColumnType from '../getColumnType.js'
import createTableType from '../createTableType.js'
import { createTableEdgeType } from '../createConnectionType.js'
import { createTableOrderingEnum } from '../createConnectionArgs.js'
import getPayloadInterface from './getPayloadInterface.js'
import getPayloadFields from './getPayloadFields.js'
import { inputClientMutationId } from './clientMutationId.js'
Expand Down Expand Up @@ -39,6 +41,7 @@ const createInputType = table =>
new GraphQLInputObjectType({
name: `Insert${table.getTypeName()}Input`,
description: `The ${table.getMarkdownTypeName()} to insert.`,

fields: {
...fromPairs(
table.getColumns().map(column => [column.getFieldName(), {
Expand All @@ -60,8 +63,31 @@ const createPayloadType = table =>
[table.getFieldName()]: {
type: createTableType(table),
description: `The inserted ${table.getMarkdownTypeName()}.`,
resolve: source => source.output,
resolve: ({ output }) => output,
},

[`${table.getFieldName()}Edge`]: {
type: createTableEdgeType(table),
args: {
orderBy: {
type: createTableOrderingEnum(table),
description:
'The value by which the cursor is created so relay knows where to insert ' +
'the edge in the connection.',
defaultValue: (() => {
const column = table.getPrimaryKeys()[0]
if (column) return column.name
return null
})(),
},
},
description: 'An edge to be inserted in a connection with help of the containing cursor.',
resolve: ({ output }, { orderBy }) => ({
cursor: orderBy && output[orderBy],
node: output,
}),
},

...getPayloadFields(table.schema),
},
})
Expand Down Expand Up @@ -96,7 +122,6 @@ const resolveInsert = table => {

const output = row ? (row[$$rowTable] = table, row) : null

// Return the first (and likely only) row.
return {
output,
clientMutationId,
Expand Down
9 changes: 8 additions & 1 deletion tests/integration/fixtures/mutation-delete.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ mutation Delete {
a: deleteThing(input: { rowId: 1 }) { ...payload }
b: deleteThing(input: { rowId: 2 }) { ...payload }
c: deleteThing(input: { rowId: 2 }) { ...payload }
d: deleteRelation(input: { aThingId: 4, bThingId: 3 }) { relation { aThingId, bThingId } }
d: deleteRelation(input: { aThingId: 4, bThingId: 3 }) { ...relationPayload }
e: deleteThing(input: { rowId: 4, clientMutationId: "hello" }) { ...payload }
f: deleteThing(input: { rowId: 6, clientMutationId: "yolo" }) { ...payload }
g: deleteThing(input: { rowId: 2 }) { ...payload }
}

fragment payload on DeleteThingPayload {
clientMutationId
deletedThingId
thing {
rowId
note
}
}

fragment relationPayload on DeleteRelationPayload {
clientMutationId
deletedRelationId
relation { aThingId, bThingId }
}
8 changes: 8 additions & 0 deletions tests/integration/fixtures/mutation-delete.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,52 @@
"data": {
"a": {
"clientMutationId": null,
"deletedThingId": "dGhpbmc6MQ==",
"thing": {
"rowId": 1,
"note": "hello"
}
},
"b": {
"clientMutationId": null,
"deletedThingId": "dGhpbmc6Mg==",
"thing": {
"rowId": 2,
"note": "world"
}
},
"c": {
"clientMutationId": null,
"deletedThingId": null,
"thing": null
},
"d": {
"clientMutationId": null,
"deletedRelationId": "cmVsYXRpb246NCwz",
"relation": {
"aThingId": 4,
"bThingId": 3
}
},
"e": {
"clientMutationId": "hello",
"deletedThingId": "dGhpbmc6NA==",
"thing": {
"rowId": 4,
"note": "bar"
}
},
"f": {
"clientMutationId": "yolo",
"deletedThingId": "dGhpbmc6Ng==",
"thing": {
"rowId": 6,
"note": "bux"
}
},
"g": {
"clientMutationId": null,
"deletedThingId": null,
"thing": null
}
}
Expand Down
33 changes: 33 additions & 0 deletions tests/integration/fixtures/mutation-insert.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ fragment payloadThing on InsertThingPayload {
rowId
note
}
withArg: thingEdge(orderBy: ROW_ID) {
cursor
node {
id
rowId
note
}
}
withoutArg: thingEdge {
cursor
node {
id
rowId
note
}
}
}

fragment payloadRelation on InsertRelationPayload {
Expand All @@ -29,4 +45,21 @@ fragment payloadRelation on InsertRelationPayload {
note
}
}
relationEdge {
cursor
node {
aThingId
bThingId
thingByAThingId {
id
rowId
note
}
thingByBThingId {
id
rowId
note
}
}
}
}
49 changes: 49 additions & 0 deletions tests/integration/fixtures/mutation-insert.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
"id": "dGhpbmc6OA==",
"rowId": 8,
"note": "a"
},
"withArg": {
"cursor": "OA==",
"node": {
"id": "dGhpbmc6OA==",
"note": "a",
"rowId": 8
}
},
"withoutArg": {
"cursor": "OA==",
"node": {
"id": "dGhpbmc6OA==",
"note": "a",
"rowId": 8
}
}
},
"b": {
Expand All @@ -14,6 +30,22 @@
"id": "dGhpbmc6OQ==",
"rowId": 9,
"note": "b"
},
"withArg": {
"cursor": "OQ==",
"node": {
"id": "dGhpbmc6OQ==",
"note": "b",
"rowId": 9
}
},
"withoutArg": {
"cursor": "OQ==",
"node": {
"id": "dGhpbmc6OQ==",
"note": "b",
"rowId": 9
}
}
},
"c": {
Expand All @@ -31,6 +63,23 @@
"rowId": 9,
"note": "b"
}
},
"relationEdge": {
"cursor": "OA==",
"node": {
"aThingId": 8,
"bThingId": 9,
"thingByAThingId": {
"id": "dGhpbmc6OA==",
"note": "a",
"rowId": 8
},
"thingByBThingId": {
"id": "dGhpbmc6OQ==",
"note": "b",
"rowId": 9
}
}
}
}
}
Expand Down

0 comments on commit f44ab99

Please sign in to comment.