From 20a084fb07e360ac33b1452951d63e05d22ad4c1 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Tue, 27 Feb 2018 20:31:15 +0000 Subject: [PATCH] feat(compat): enable lower case Json/Uuid like v3 (#184) --- packages/graphile-build-pg/package.json | 1 - packages/graphile-build-pg/src/GraphQLJSON.js | 82 +++++++++++++++++++ .../src/plugins/PgTypesPlugin.js | 17 ++-- .../__snapshots__/schema.test.js.snap | 32 ++++---- .../__tests__/integration/schema.test.js | 3 +- packages/postgraphile-core/src/index.js | 3 + yarn.lock | 4 - 7 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 packages/graphile-build-pg/src/GraphQLJSON.js diff --git a/packages/graphile-build-pg/package.json b/packages/graphile-build-pg/package.json index 5f0219f27..a66582f3f 100644 --- a/packages/graphile-build-pg/package.json +++ b/packages/graphile-build-pg/package.json @@ -39,7 +39,6 @@ "debug": ">=2 <3", "graphile-build": "4.0.0-alpha.1", "graphql-iso-date": "^3.2.0", - "graphql-type-json": "^0.1.4", "jsonwebtoken": "^8.1.1", "lodash": ">=4 <5", "lru-cache": "4.1.1", diff --git a/packages/graphile-build-pg/src/GraphQLJSON.js b/packages/graphile-build-pg/src/GraphQLJSON.js new file mode 100644 index 000000000..469f9e565 --- /dev/null +++ b/packages/graphile-build-pg/src/GraphQLJSON.js @@ -0,0 +1,82 @@ +// This file is based on +// https://github.com/taion/graphql-type-json/blob/6e45ae4ee0a60f8f3565c8c980a82c7d9b98d3f5/src/index.js +// +// It only exists here (rather than using `graphql-type-json` directly) because +// we need to export Json along with JSON. +// +/* +The MIT License (MIT) + +Copyright (c) 2016 Jimmy Jia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +import { GraphQLScalarType } from "graphql"; +import { Kind } from "graphql/language"; + +function identity(value) { + return value; +} + +function parseLiteral(ast) { + switch (ast.kind) { + case Kind.STRING: + case Kind.BOOLEAN: + return ast.value; + case Kind.INT: + case Kind.FLOAT: + return parseFloat(ast.value); + case Kind.OBJECT: { + const value = Object.create(null); + ast.fields.forEach(field => { + value[field.name.value] = parseLiteral(field.value); + }); + + return value; + } + case Kind.LIST: + return ast.values.map(parseLiteral); + case Kind.NULL: + return null; + default: + return undefined; + } +} + +export const GraphQLJSON = new GraphQLScalarType({ + name: "JSON", + description: + "The `JSON` scalar type represents JSON values as specified by " + + "[ECMA-404](http://www.ecma-international.org/" + + "publications/files/ECMA-ST/ECMA-404.pdf).", + serialize: identity, + parseValue: identity, + parseLiteral, +}); + +export const GraphQLJson = new GraphQLScalarType({ + name: "Json", + description: + "The `Json` scalar type represents JSON values as specified by " + + "[ECMA-404](http://www.ecma-international.org/" + + "publications/files/ECMA-ST/ECMA-404.pdf).", + serialize: identity, + parseValue: identity, + parseLiteral, +}); diff --git a/packages/graphile-build-pg/src/plugins/PgTypesPlugin.js b/packages/graphile-build-pg/src/plugins/PgTypesPlugin.js index 461b3a299..d41ae3b65 100644 --- a/packages/graphile-build-pg/src/plugins/PgTypesPlugin.js +++ b/packages/graphile-build-pg/src/plugins/PgTypesPlugin.js @@ -17,7 +17,10 @@ import { import { Kind } from "graphql/language"; import { types as pgTypes } from "pg"; -import GraphQLJSON from "graphql-type-json"; +import { GraphQLJSON, GraphQLJson } from "../GraphQLJSON"; + +import rawParseInterval from "postgres-interval"; +import LRU from "lru-cache"; function indent(str) { return " " + str.replace(/\n/g, "\n "); @@ -36,8 +39,6 @@ const stringType = (name, description) => return ast.value; }, }); -import rawParseInterval from "postgres-interval"; -import LRU from "lru-cache"; /* const { GraphQLDate, @@ -97,7 +98,7 @@ const pgRangeParser = { export default (function PgTypesPlugin( builder, - { pgExtendedTypes = true, pgInflection: inflection } + { pgExtendedTypes = true, pgInflection: inflection, pgLegacyJsonUuid = false } ) { // XXX: most of this should be in an "init" hook, not a "build" hook builder.hook("build", build => { @@ -325,16 +326,18 @@ export default (function PgTypesPlugin( "The exact time of day, does not include the date. May or may not have a timezone offset." ); const SimpleJSON = stringType( - "JSON", + pgLegacyJsonUuid ? "Json" : "JSON", "A JavaScript object encoded in the JSON format as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)." ); const SimpleUUID = stringType( - "UUID", + pgLegacyJsonUuid ? "Uuid" : "UUID", "A universally unique identifier as defined by [RFC 4122](https://tools.ietf.org/html/rfc4122)." ); // pgExtendedTypes might change what types we use for things - const JSONType = pgExtendedTypes ? GraphQLJSON : SimpleJSON; + const JSONType = pgExtendedTypes + ? pgLegacyJsonUuid ? GraphQLJson : GraphQLJSON + : SimpleJSON; const UUIDType = SimpleUUID; // GraphQLUUID const DateType = SimpleDate; // GraphQLDate const DateTimeType = SimpleDatetime; // GraphQLDateTime diff --git a/packages/postgraphile-core/__tests__/integration/__snapshots__/schema.test.js.snap b/packages/postgraphile-core/__tests__/integration/__snapshots__/schema.test.js.snap index 808e1df28..2f9264553 100644 --- a/packages/postgraphile-core/__tests__/integration/__snapshots__/schema.test.js.snap +++ b/packages/postgraphile-core/__tests__/integration/__snapshots__/schema.test.js.snap @@ -12294,7 +12294,7 @@ input WrappedUrlInput { " `; -exports[`prints a schema without legacy relations 1`] = ` +exports[`prints a schema without new relations and with legacy type names 1`] = ` "enum AnEnum { _ASTERISK_BAR_ _ASTERISK_BAZ_ASTERISK_ @@ -12422,7 +12422,7 @@ type CompoundType { b: String c: Color computedField: Int - d: UUID + d: Uuid e: EnumCaps f: EnumWithEmptyString fooBar: Int @@ -13035,7 +13035,7 @@ type IntSetQueryEdge { \\"\\"\\" A JavaScript object encoded in the JSON format as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). \\"\\"\\" -scalar JSON +scalar Json \\"\\"\\"All input for the \`jsonbIdentityMutation\` mutation.\\"\\"\\" input JsonbIdentityMutationInput { @@ -13044,7 +13044,7 @@ input JsonbIdentityMutationInput { payload verbatim. May be used to track mutations by the client. \\"\\"\\" clientMutationId: String - json: JSON + json: Json } \\"\\"\\"The output of our \`jsonbIdentityMutation\` mutation.\\"\\"\\" @@ -13054,7 +13054,7 @@ type JsonbIdentityMutationPayload { unchanged and unused. May be used by a client to track mutations. \\"\\"\\" clientMutationId: String - json: JSON + json: Json \\"\\"\\" Our root query field type. Allows us to run any query from our mutation payload. @@ -13064,7 +13064,7 @@ type JsonbIdentityMutationPayload { \\"\\"\\"All input for the \`jsonbIdentityMutationPlpgsql\` mutation.\\"\\"\\" input JsonbIdentityMutationPlpgsqlInput { - _theJson: JSON! + _theJson: Json! \\"\\"\\" An arbitrary string value with no semantic meaning. Will be included in the @@ -13080,7 +13080,7 @@ type JsonbIdentityMutationPlpgsqlPayload { unchanged and unused. May be used by a client to track mutations. \\"\\"\\" clientMutationId: String - json: JSON + json: Json \\"\\"\\" Our root query field type. Allows us to run any query from our mutation payload. @@ -13090,7 +13090,7 @@ type JsonbIdentityMutationPlpgsqlPayload { \\"\\"\\"All input for the \`jsonbIdentityMutationPlpgsqlWithDefault\` mutation.\\"\\"\\" input JsonbIdentityMutationPlpgsqlWithDefaultInput { - _theJson: JSON + _theJson: Json \\"\\"\\" An arbitrary string value with no semantic meaning. Will be included in the @@ -13106,7 +13106,7 @@ type JsonbIdentityMutationPlpgsqlWithDefaultPayload { unchanged and unused. May be used by a client to track mutations. \\"\\"\\" clientMutationId: String - json: JSON + json: Json \\"\\"\\" Our root query field type. Allows us to run any query from our mutation payload. @@ -13121,7 +13121,7 @@ input JsonIdentityMutationInput { payload verbatim. May be used to track mutations by the client. \\"\\"\\" clientMutationId: String - json: JSON + json: Json } \\"\\"\\"The output of our \`jsonIdentityMutation\` mutation.\\"\\"\\" @@ -13131,7 +13131,7 @@ type JsonIdentityMutationPayload { unchanged and unused. May be used by a client to track mutations. \\"\\"\\" clientMutationId: String - json: JSON + json: Json \\"\\"\\" Our root query field type. Allows us to run any query from our mutation payload. @@ -14112,8 +14112,8 @@ type Query implements Node { y: Int z: Int ): IntSetQueryConnection! - jsonIdentity(json: JSON): JSON - jsonbIdentity(json: JSON): JSON + jsonIdentity(json: Json): Json + jsonbIdentity(json: Json): Json \\"\\"\\"Reads a single \`LeftArm\` using its globally unique \`ID\`.\\"\\"\\" leftArm( @@ -14179,7 +14179,7 @@ type Query implements Node { \\"\\"\\" offset: Int ): PeopleConnection! - typesQuery(a: BigInt!, b: Boolean!, c: String!, d: [Int]!, e: JSON!, f: FloatRangeInput!): Boolean + typesQuery(a: BigInt!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean } \\"\\"\\"All input for the \`tableMutation\` mutation.\\"\\"\\" @@ -14249,7 +14249,7 @@ input TypesMutationInput { \\"\\"\\" clientMutationId: String d: [Int]! - e: JSON! + e: Json! f: FloatRangeInput! } @@ -14547,7 +14547,7 @@ type UpdatePersonSecretPayload { \\"\\"\\" A universally unique identifier as defined by [RFC 4122](https://tools.ietf.org/html/rfc4122). \\"\\"\\" -scalar UUID +scalar Uuid type WrappedUrl { url: NotNullUrl! diff --git a/packages/postgraphile-core/__tests__/integration/schema.test.js b/packages/postgraphile-core/__tests__/integration/schema.test.js index 7ffe0a869..904a14e84 100644 --- a/packages/postgraphile-core/__tests__/integration/schema.test.js +++ b/packages/postgraphile-core/__tests__/integration/schema.test.js @@ -50,11 +50,12 @@ const testFixtures = [ }), }, { - name: "prints a schema without legacy relations", // will be default in v5 + name: "prints a schema without new relations and with legacy type names", createSchema: client => createPostGraphQLSchema(client, "c", { legacyRelations: "only", enableTags: false, + legacyJsonUuid: true, }), }, ]; diff --git a/packages/postgraphile-core/src/index.js b/packages/postgraphile-core/src/index.js index 59d96c9f0..24aaa9085 100644 --- a/packages/postgraphile-core/src/index.js +++ b/packages/postgraphile-core/src/index.js @@ -46,6 +46,7 @@ type PostGraphQLOptions = { setWriteCacheCallback?: (fn: () => Promise) => void, legacyRelations?: "only" | "deprecated", badlyBehavedFunctions?: boolean, + legacyJsonUuid?: boolean, }; type PgConfig = Client | Pool | string; @@ -108,6 +109,7 @@ const getPostGraphQLBuilder = async ( setWriteCacheCallback, legacyRelations = "deprecated", // TODO: Change to 'omit' in v5 badlyBehavedFunctions = false, + legacyJsonUuid = false, } = options; if ( @@ -218,6 +220,7 @@ const getPostGraphQLBuilder = async ( pgViewUniqueKey: viewUniqueKey, pgEnableTags: enableTags, pgLegacyRelations: legacyRelations, + pgLegacyJsonUuid: legacyJsonUuid, persistentMemoizeWithKey, pgForbidSetofFunctionsToReturnNull: !badlyBehavedFunctions, }, diff --git a/yarn.lock b/yarn.lock index d9c3fcbe0..e01038921 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2311,10 +2311,6 @@ graphql-iso-date@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/graphql-iso-date/-/graphql-iso-date-3.5.0.tgz#55a1be0efa8d28c1453afd2eb5ce1d052189a513" -graphql-type-json@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/graphql-type-json/-/graphql-type-json-0.1.4.tgz#89f13f5d32ce08c9a76c79fdf9c1968384d81a4e" - "graphql@>=0.9 <0.14": version "0.13.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.1.tgz#9b3db3d8e40d1827e4172404bfdd2e4e17a58b55"