From 803870efc3ae335c4c4dfffa8595b825471ffe21 Mon Sep 17 00:00:00 2001 From: Richard Keil Date: Thu, 24 Mar 2016 14:23:48 +0100 Subject: [PATCH 1/3] adds input type and string literals --- src/graphql-shorthand.pegjs | 24 +++++++++++++++++- test/input.js | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 test/input.js diff --git a/src/graphql-shorthand.pegjs b/src/graphql-shorthand.pegjs index b1b8bbb..3850889 100644 --- a/src/graphql-shorthand.pegjs +++ b/src/graphql-shorthand.pegjs @@ -1,5 +1,5 @@ start - = WS* definitions:(Enum / Interface / Object)* WS* + = WS* definitions:(Enum / Interface / Object / InputObject)* WS* { return definitions; } Ident = $([a-z]([a-z0-9_]i)*) @@ -18,6 +18,10 @@ Object = description:Comment? "type" SPACE name:TypeIdent interfaces:(COLON list:TypeList { return list; })? BEGIN_BODY fields:FieldList CLOSE_BODY { return { type: "TYPE", name, ...(description && { description }), fields, ...(interfaces && { interfaces }) }; } +InputObject + = description:Comment? "input" SPACE name:TypeIdent interfaces:(COLON list:TypeList { return list; })? BEGIN_BODY fields:InputFieldList CLOSE_BODY + { return { type: "INPUT", name, ...(description && { description }), fields, ...(interfaces && { interfaces }) }; } + ReturnType = type:TypeIdent required:"!"? { return { type, ...(required && { required: !!required }) }; } @@ -36,6 +40,14 @@ FieldList = head:Field tail:(EOL_SEP field:Field { return field; })* { return [head, ...tail].reduce((result, field) => ({ ...result, ...field }), {}); } +InputField + = description:Comment? name:Ident args:(BEGIN_ARGS fields:FieldList CLOSE_ARGS { return fields; })? COLON type:ReturnType defaultValue:(EQUAL value:Literal { return value; })? + { return { [name]: { ...type, ...(args && { args }), ...(description && { description }), ...(defaultValue && { defaultValue }) } }; } + +InputFieldList + = head:InputField tail:(EOL_SEP field:InputField { return field; })* + { return [head, ...tail].reduce((result, field) => ({ ...result, ...field }), {}); } + EnumIdentList = head:EnumIdent tail:(EOL_SEP value:EnumIdent { return value; })* { return [head, ...tail]; } @@ -46,6 +58,15 @@ Comment / "/*" comment:(!"*/" char:CHAR { return char; })* "*/" EOL_SEP { return comment.join("").replace(/\n\s*[*]?\s*/g, " ").replace(/\s+/, " ").trim(); } +Literal + = StringLiteral + +StringLiteral + = '"' chars:DoubleStringCharacter* '"' { return chars.join(""); } + +DoubleStringCharacter + = !('"' / "\\" / EOL) . { return text(); } + LINE_COMMENT = "#" / "//" BEGIN_BODY = WS* "{" WS* @@ -59,6 +80,7 @@ CHAR = . WS = (SPACE / EOL)+ COLON = WS* ":" WS* +EQUAL = WS* "=" WS* COMMA_SEP = WS* "," WS* EOL_SEP = SPACE* EOL SPACE* diff --git a/test/input.js b/test/input.js new file mode 100644 index 0000000..c5238ee --- /dev/null +++ b/test/input.js @@ -0,0 +1,50 @@ +import test from "ava"; +import { parse } from ".."; + +test("input definition", t => { + const [actual] = parse(` + // A Person + input Person { + id: String! + name: String + } + `); + + const expected = { + type: "INPUT", + name: "Person", + description: "A Person", + fields: { + id: { type: "String", required: true }, + name: { type: "String" } + } + }; + + return t.same(actual, expected); +}); + + +test("input with default values", t => { + const [actual] = parse(` + // A Person + input Person { + id: String! + firstname: String = "Hans" + lastname: String = "Wurst" + } + `); + + const expected = { + type: "INPUT", + name: "Person", + description: "A Person", + fields: { + id: { type: "String", required: true }, + firstname: { type: "String", defaultValue: "Hans" }, + lastname: { type: "String", defaultValue: "Wurst" } + } + }; + + return t.same(actual, expected); +}); + From 215919114d9aa0f37fa0524b53b17cef6b66e43c Mon Sep 17 00:00:00 2001 From: Richard Keil Date: Thu, 24 Mar 2016 15:28:22 +0100 Subject: [PATCH 2/3] add Boolean and Numeric literals --- src/graphql-shorthand.pegjs | 10 ++++++- test/input.js | 57 ++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/graphql-shorthand.pegjs b/src/graphql-shorthand.pegjs index 3850889..48eef36 100644 --- a/src/graphql-shorthand.pegjs +++ b/src/graphql-shorthand.pegjs @@ -5,6 +5,7 @@ start Ident = $([a-z]([a-z0-9_]i)*) TypeIdent = $([A-Z]([a-z0-9_]i)*) EnumIdent = $([A-Z][A-Z0-9_]*) +NumberIdent = $([.+-]?[0-9]+([.][0-9]+)?) Enum = description:Comment? "enum" SPACE name:TypeIdent BEGIN_BODY values:EnumIdentList CLOSE_BODY @@ -59,7 +60,7 @@ Comment { return comment.join("").replace(/\n\s*[*]?\s*/g, " ").replace(/\s+/, " ").trim(); } Literal - = StringLiteral + = StringLiteral / BooleanLiteral / NumericLiteral StringLiteral = '"' chars:DoubleStringCharacter* '"' { return chars.join(""); } @@ -67,6 +68,13 @@ StringLiteral DoubleStringCharacter = !('"' / "\\" / EOL) . { return text(); } +BooleanLiteral + = "true" { return true } + / "false" { return false } + +NumericLiteral + = value:NumberIdent { return Number(value.replace(/^[.]/, '0.')); } + LINE_COMMENT = "#" / "//" BEGIN_BODY = WS* "{" WS* diff --git a/test/input.js b/test/input.js index c5238ee..3e2c850 100644 --- a/test/input.js +++ b/test/input.js @@ -23,8 +23,26 @@ test("input definition", t => { return t.same(actual, expected); }); +test("input with boolean defaultValue", t => { + const [actual] = parse(` + input Person { + alive: Boolean = true + } + `); + + const expected = { + type: "INPUT", + name: "Person", + fields: { + alive: { type: "Boolean", defaultValue: true }, + } + }; -test("input with default values", t => { + return t.same(actual, expected); +}); + + +test("input with string default values", t => { const [actual] = parse(` // A Person input Person { @@ -48,3 +66,40 @@ test("input with default values", t => { return t.same(actual, expected); }); +test("input with integer defaultValue", t => { + const [actual] = parse(` + input Person { + age: Int = 32 + } + `); + + const expected = { + type: "INPUT", + name: "Person", + fields: { + age: { type: "Int", defaultValue: 32 }, + } + }; + + return t.same(actual, expected); +}); + +test("input with float defaultValue", t => { + const [actual] = parse(` + input Person { + height: Float = 1.82 + iq: Float = .5 + } + `); + + const expected = { + type: "INPUT", + name: "Person", + fields: { + height: { type: "Float", defaultValue: 1.82 }, + iq: { type: "Float", defaultValue: 0.5 }, + } + }; + + return t.same(actual, expected); +}); From 1b8b1ca5edd7206569d7514041aacd4d333ea2dd Mon Sep 17 00:00:00 2001 From: Richard Keil Date: Thu, 24 Mar 2016 15:42:15 +0100 Subject: [PATCH 3/3] test description on input field --- test/input.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/input.js b/test/input.js index 3e2c850..4c3d2e3 100644 --- a/test/input.js +++ b/test/input.js @@ -6,6 +6,7 @@ test("input definition", t => { // A Person input Person { id: String! + // The full name name: String } `); @@ -16,7 +17,7 @@ test("input definition", t => { description: "A Person", fields: { id: { type: "String", required: true }, - name: { type: "String" } + name: { type: "String", description: "The full name" } } };