diff --git a/examples/kitchen-sink/schema.sql b/examples/kitchen-sink/schema.sql index 5924cddace..d37253bb34 100644 --- a/examples/kitchen-sink/schema.sql +++ b/examples/kitchen-sink/schema.sql @@ -78,6 +78,10 @@ create table a.foreign_key ( foreign key (compound_key_1, compound_key_2) references c.compound_key(person_id_1, person_id_2) ); +create table c.edge_case ( + not_null_has_default boolean not null default false +); + create domain a.an_int as integer; create domain b.another_int as a.an_int; diff --git a/src/graphql/schema/collection/mutations/createCreateCollectionMutationFieldEntry.ts b/src/graphql/schema/collection/mutations/createCreateCollectionMutationFieldEntry.ts index 003a08ceb3..ac672f9c3b 100644 --- a/src/graphql/schema/collection/mutations/createCreateCollectionMutationFieldEntry.ts +++ b/src/graphql/schema/collection/mutations/createCreateCollectionMutationFieldEntry.ts @@ -74,8 +74,10 @@ export default function createCreateCollectionMutationFieldEntry ( execute: (context, input) => { const value = transformGQLInputValue(inputFieldType, input[inputFieldName]) - if (!collection.type.isTypeOf(value)) - throw new Error(`Created object is not of the correct type for collection '${collection.name}'.`) + // TODO: This can’t be the best solution? `isTypeOf` fails though for + // default fields that don’t exist. + if (!(value instanceof Map)) + throw new Error('Value must be a `Map`.') return collection.create!(context, value) }, diff --git a/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationOperations-test.js.snap b/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationOperations-test.js.snap index 5748015dfe..f0df9952e4 100644 --- a/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationOperations-test.js.snap +++ b/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationOperations-test.js.snap @@ -772,6 +772,16 @@ Object { "name": "Best Pal", }, }, + "e": Object { + "edgeCase": Object { + "notNullHasDefault": true, + }, + }, + "f": Object { + "edgeCase": Object { + "notNullHasDefault": false, + }, + }, }, } `; diff --git a/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationSchema-test.js.snap b/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationSchema-test.js.snap index 8c998e502d..eec1ab1f6b 100644 --- a/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationSchema-test.js.snap +++ b/src/postgraphql/__tests__/__snapshots__/postgraphqlIntegrationSchema-test.js.snap @@ -83,6 +83,21 @@ type CreateCompoundKeyPayload { query: Query } +input CreateEdgeCaseInput { + clientMutationId: String + edgeCase: EdgeCaseInput! +} + +type CreateEdgeCasePayload { + clientMutationId: String + edgeCase: EdgeCase + edgeCaseEdge( + # The method to use when ordering \`EdgeCase\`. + orderBy: EdgeCasesOrderBy = NATURAL + ): EdgeCasesEdge + query: Query +} + input CreatePersonInput { clientMutationId: String person: PersonInput! @@ -151,6 +166,45 @@ type DeletePersonPayload { query: Query } +type EdgeCase { + notNullHasDefault: Boolean! +} + +input EdgeCaseInput { + notNullHasDefault: Boolean +} + +# A connection to a list of \`EdgeCase\` values. +type EdgeCasesConnection { + # Information to aid in pagination. + pageInfo: PageInfo! + + # The count of *all* \`EdgeCase\` you could get from the connection. + totalCount: Int + + # A list of edges which contains the \`EdgeCase\` and cursor to aid in pagination. + edges: [EdgeCasesEdge] + + # A list of \`EdgeCase\` objects. + nodes: [EdgeCase!] +} + +# A \`EdgeCase\` edge in the connection. +type EdgeCasesEdge { + # A cursor for use in pagination. + cursor: Cursor + + # The \`EdgeCase\` at the end of the edge. + node: EdgeCase! +} + +# Methods to use when ordering \`EdgeCase\`. +enum EdgeCasesOrderBy { + NATURAL + NOT_NULL_HAS_DEFAULT_ASC + NOT_NULL_HAS_DEFAULT_DESC +} + scalar Email input FloatRangeBoundInput { @@ -221,6 +275,7 @@ type Mutation { updateCompoundKeyByPersonId1AndPersonId2(input: UpdateCompoundKeyByPersonId1AndPersonId2Input!): UpdateCompoundKeyPayload deleteCompoundKey(input: DeleteCompoundKeyInput!): DeleteCompoundKeyPayload deleteCompoundKeyByPersonId1AndPersonId2(input: DeleteCompoundKeyByPersonId1AndPersonId2Input!): DeleteCompoundKeyPayload + createEdgeCase(input: CreateEdgeCaseInput!): CreateEdgeCasePayload createPerson(input: CreatePersonInput!): CreatePersonPayload updatePerson(input: UpdatePersonInput!): UpdatePersonPayload updatePersonByEmail(input: UpdatePersonByEmailInput!): UpdatePersonPayload @@ -528,6 +583,29 @@ type Query implements Node { ): CompoundKey compoundKeyByPersonId1AndPersonId2(personId1: Int!, personId2: Int!): CompoundKey + # Reads and enables paginatation through a set of \`EdgeCase\`. + allEdgeCases( + # The method to use when ordering \`EdgeCase\`. + orderBy: EdgeCasesOrderBy = NATURAL + + # Read all values in the set before (above) this cursor. + before: Cursor + + # Read all values in the set after (below) this cursor. + after: Cursor + + # Only read the first \`n\` values of the set. + first: Int + + # Only read the last \`n\` values of the set. + last: Int + + # Skip the first \`n\` values from our \`after\` cursor, an alternative to cursor + # based pagination. May not be used with \`last\`. + offset: Int + notNullHasDefault: Boolean + ): EdgeCasesConnection + # Reads and enables paginatation through a set of \`Person\`. allPeople( # The method to use when ordering \`Person\`. @@ -1549,6 +1627,21 @@ type CreateCompoundKeyPayload { query: Query } +input CreateEdgeCaseInput { + clientMutationId: String + edgeCase: EdgeCaseInput! +} + +type CreateEdgeCasePayload { + clientMutationId: String + edgeCase: EdgeCase + edgeCaseEdge( + # The method to use when ordering \`EdgeCase\`. + orderBy: EdgeCasesOrderBy = NATURAL + ): EdgeCasesEdge + query: Query +} + input CreateForeignKeyInput { clientMutationId: String foreignKey: ForeignKeyInput! @@ -1748,6 +1841,45 @@ type DeleteTypePayload { query: Query } +type EdgeCase { + notNullHasDefault: Boolean! +} + +input EdgeCaseInput { + notNullHasDefault: Boolean +} + +# A connection to a list of \`EdgeCase\` values. +type EdgeCasesConnection { + # Information to aid in pagination. + pageInfo: PageInfo! + + # The count of *all* \`EdgeCase\` you could get from the connection. + totalCount: Int + + # A list of edges which contains the \`EdgeCase\` and cursor to aid in pagination. + edges: [EdgeCasesEdge] + + # A list of \`EdgeCase\` objects. + nodes: [EdgeCase!] +} + +# A \`EdgeCase\` edge in the connection. +type EdgeCasesEdge { + # A cursor for use in pagination. + cursor: Cursor + + # The \`EdgeCase\` at the end of the edge. + node: EdgeCase! +} + +# Methods to use when ordering \`EdgeCase\`. +enum EdgeCasesOrderBy { + NATURAL + NOT_NULL_HAS_DEFAULT_ASC + NOT_NULL_HAS_DEFAULT_DESC +} + scalar Email # range of numerics @@ -1987,6 +2119,7 @@ type Mutation { updateCompoundKeyByPersonId1AndPersonId2(input: UpdateCompoundKeyByPersonId1AndPersonId2Input!): UpdateCompoundKeyPayload deleteCompoundKey(input: DeleteCompoundKeyInput!): DeleteCompoundKeyPayload deleteCompoundKeyByPersonId1AndPersonId2(input: DeleteCompoundKeyByPersonId1AndPersonId2Input!): DeleteCompoundKeyPayload + createEdgeCase(input: CreateEdgeCaseInput!): CreateEdgeCasePayload createPerson(input: CreatePersonInput!): CreatePersonPayload updatePerson(input: UpdatePersonInput!): UpdatePersonPayload updatePersonByEmail(input: UpdatePersonByEmailInput!): UpdatePersonPayload @@ -2616,6 +2749,29 @@ type Query implements Node { ): CompoundKey compoundKeyByPersonId1AndPersonId2(personId1: Int!, personId2: Int!): CompoundKey + # Reads and enables paginatation through a set of \`EdgeCase\`. + allEdgeCases( + # The method to use when ordering \`EdgeCase\`. + orderBy: EdgeCasesOrderBy = NATURAL + + # Read all values in the set before (above) this cursor. + before: Cursor + + # Read all values in the set after (below) this cursor. + after: Cursor + + # Only read the first \`n\` values of the set. + first: Int + + # Only read the last \`n\` values of the set. + last: Int + + # Skip the first \`n\` values from our \`after\` cursor, an alternative to cursor + # based pagination. May not be used with \`last\`. + offset: Int + notNullHasDefault: Boolean + ): EdgeCasesConnection + # Reads and enables paginatation through a set of \`Person\`. allPeople( # The method to use when ordering \`Person\`. diff --git a/src/postgraphql/__tests__/fixtures/queries/mutation-create.graphql b/src/postgraphql/__tests__/fixtures/queries/mutation-create.graphql index 93eb415f76..f3a2a645f1 100644 --- a/src/postgraphql/__tests__/fixtures/queries/mutation-create.graphql +++ b/src/postgraphql/__tests__/fixtures/queries/mutation-create.graphql @@ -152,6 +152,22 @@ mutation { name } } + e: createEdgeCase(input: { + edgeCase: { + notNullHasDefault: true + } + }) { + edgeCase { + notNullHasDefault + } + } + f: createEdgeCase(input: { + edgeCase: {} + }) { + edgeCase { + notNullHasDefault + } + } } fragment createPersonPayload on CreatePersonPayload { diff --git a/src/postgres/introspection/__tests__/__snapshots__/introspectDatabase-test.js.snap b/src/postgres/introspection/__tests__/__snapshots__/introspectDatabase-test.js.snap index 6c01fb3801..032e9af7bd 100644 --- a/src/postgres/introspection/__tests__/__snapshots__/introspectDatabase-test.js.snap +++ b/src/postgres/introspection/__tests__/__snapshots__/introspectDatabase-test.js.snap @@ -81,6 +81,16 @@ Object { "num": 5, "typeId": "int4", }, + Object { + "classId": "edge_case", + "description": null, + "hasDefault": true, + "isNotNull": true, + "kind": "attribute", + "name": "not_null_has_default", + "num": 1, + "typeId": "bool", + }, Object { "classId": "foreign_key", "description": null, @@ -587,6 +597,18 @@ Object { "namespaceId": "c", "typeId": "compound_type", }, + Object { + "description": null, + "id": "edge_case", + "isDeletable": true, + "isInsertable": true, + "isSelectable": true, + "isUpdatable": true, + "kind": "class", + "name": "edge_case", + "namespaceId": "c", + "typeId": "edge_case", + }, Object { "description": null, "id": "foreign_key", @@ -1468,6 +1490,22 @@ Object { "rangeSubTypeId": null, "type": "c", }, + Object { + "arrayItemTypeId": null, + "category": "C", + "classId": "edge_case", + "description": null, + "domainBaseTypeId": null, + "domainIsNotNull": false, + "enumVariants": null, + "id": "edge_case", + "kind": "type", + "name": "edge_case", + "namespaceId": "c", + "namespaceName": "c", + "rangeSubTypeId": null, + "type": "c", + }, Object { "arrayItemTypeId": null, "category": "S",