From 4d67fd682c7b01e88a22bf2d9d255664953bd2a3 Mon Sep 17 00:00:00 2001 From: jangko Date: Fri, 16 Apr 2021 22:21:36 +0700 Subject: [PATCH] add parseVars API --- docs/api.md | 2 ++ graphql/api.nim | 35 ++++++++++++++++++++++++++++++++++- graphql/server_common.nim | 6 +++++- playground/swapi.nim | 2 +- tests/test_execution.nim | 4 ++-- tests/test_introspection.nim | 4 ++-- tests/test_schemaintros.nim | 6 +++--- tests/test_validation.nim | 8 ++++---- 8 files changed, 53 insertions(+), 14 deletions(-) diff --git a/docs/api.md b/docs/api.md index e4a6ba4..ea1e8ea 100644 --- a/docs/api.md +++ b/docs/api.md @@ -28,6 +28,8 @@ If you find anything not listed or not exported in this list, please submit an i - `addVar(ctx: GraphqlRef, name: string)`. Add a `null` variable. - `parseVar(ctx: GraphqlRef, name: string, value: string | openArray[byte]): ParseResult`. Add new variable to the system by parsing a text string. + - `parseVars(ctx: GraphqlRef, value: string | openArray[byte]): ParseResult`. + Add new variables to the system by parsing map. Top level keys will become variables name. - `addResolvers(ctx: GraphqlRef, ud: RootRef, typeName: Name, resolvers: openArray[(string, ResolverProc)])`. Add a list of resolvers to the system. - `addResolvers(ctx: GraphqlRef, ud: RootRef, typeName: string, resolvers: openArray[(string, ResolverProc)])` - `createName(ctx: GraphqlRef, name: string): Name`. `respMap` will need a name from the system using this proc. diff --git a/graphql/api.nim b/graphql/api.nim index ab087b7..4e3f5ef 100644 --- a/graphql/api.nim +++ b/graphql/api.nim @@ -86,6 +86,7 @@ proc parseVariable(q: var Parser): Node = nextToken if currToken == tokEof: return + rgReset(rgValueLiteral) # recursion guard q.valueLiteral(isConst = true, result) proc parseVariable(ctx: GraphqlRef, name: string, input: InputStream): GraphqlResult = @@ -109,6 +110,33 @@ proc parseVar*(ctx: GraphqlRef, name: string, var stream = unsafeMemoryInput(value) ctx.parseVariable(name, stream) +proc parseVars(ctx: GraphqlRef, input: InputStream): GraphqlResult = + var parser = Parser.init(input, ctx.names) + parser.lex.next() + if parser.lex.tok == tokEof: + return ok() + + var values: Node + parser.rgReset(rgValueLiteral) # recursion guard + parser.valueLiteral(isConst = true, values) + if parser.error != errNone: + return err(@[parser.err]) + + for n in values: + ctx.varTable[n[0].name] = n[1] + + ok() + +proc parseVars*(ctx: GraphqlRef, input: string): GraphqlResult {.gcsafe.} = + {.gcsafe.}: + var stream = unsafeMemoryInput(input) + ctx.parseVars(stream) + +proc parseVars*(ctx: GraphqlRef, input: openArray[byte]): GraphqlResult {.gcsafe.} = + {.gcsafe.}: + var stream = unsafeMemoryInput(input) + ctx.parseVars(stream) + proc addResolvers*(ctx: GraphqlRef, ud: RootRef, typeName: Name, resolvers: openArray[tuple[name: string, resolver: ResolverProc]]) = var res = ctx.resolver.getOrDefault(typeName) @@ -193,7 +221,8 @@ proc purgeQueries*(ctx: GraphqlRef, includeVariables: bool) = if includeVariables: ctx.varTable.clear() -proc purgeSchema*(ctx: GraphqlRef, includeScalars, includeResolvers: bool) = +proc purgeSchema*(ctx: GraphqlRef, includeScalars, + includeResolvers, includeCoercion: bool) = var names = initHashSet[Name]() for n, v in ctx.typeTable: if sfBuiltin notin v.flags: @@ -214,6 +243,10 @@ proc purgeSchema*(ctx: GraphqlRef, includeScalars, includeResolvers: bool) = for n in names: ctx.resolver.del(n) + if includeCoercion: + for n in names: + ctx.coerceTable.del(n) + proc getNameCounter*(ctx: GraphqlRef): NameCounter = ctx.names.getCounter() diff --git a/graphql/server_common.nim b/graphql/server_common.nim index e6e8399..28dffe0 100644 --- a/graphql/server_common.nim +++ b/graphql/server_common.nim @@ -86,6 +86,8 @@ proc jsonOkResp*(data: openArray[byte]): string = resp.getString() proc addVariables*(ctx: GraphqlRef, vars: Node) = + if vars.kind != nkInput: + return for n in vars: if n.len != 2: continue # support both json/graphql object key @@ -102,8 +104,10 @@ proc parseLiteral(ctx: GraphqlRef, input: InputStream): ParseResult = # we want to parse a json object parser.flags.incl pfJsonCompatibility parser.lex.next() + if parser.lex.tok == tokEof: + return ok(ctx.emptyNode) parser.rgReset(rgValueLiteral) # recursion guard - parser.valueLiteral(true, values) + parser.valueLiteral(isConst = true, values) if parser.error != errNone: return err(@[parser.err]) ok(values) diff --git a/playground/swapi.nim b/playground/swapi.nim index 8fbecf3..88e9e58 100644 --- a/playground/swapi.nim +++ b/playground/swapi.nim @@ -482,7 +482,7 @@ proc coerceEnum(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsa if node.kind == nkString: ok(Node(kind: nkEnum, name: ctx.createName(node.stringVal), pos: node.pos)) else: - err("cannot coerce '$1' to $2" % [$node.kind, $typeNode.sym.name]) + err("cannot coerce '$1' to $2" % [$node.kind, $typeNode]) {.pop.} diff --git a/tests/test_execution.nim b/tests/test_execution.nim index b906725..a7b2665 100644 --- a/tests/test_execution.nim +++ b/tests/test_execution.nim @@ -93,7 +93,7 @@ proc runSuite(ctx: GraphqlRef, savePoint: NameCounter, fileName: string, counter else: ctx.runExecutor(unit, testStatusIMPL) ctx.purgeQueries(false) - ctx.purgeSchema(false, false) + ctx.purgeSchema(false, false, false) ctx.purgeNames(savePoint) if testStatusIMPL == OK: inc counter.ok @@ -133,7 +133,7 @@ when isMainModule: test unit.name: ctx.runExecutor(unit, testStatusIMPL) ctx.purgeQueries(true) - ctx.purgeSchema(true, true) + ctx.purgeSchema(true, true, false) ctx.purgeNames(savePoint) var message: string diff --git a/tests/test_introspection.nim b/tests/test_introspection.nim index fbda8f4..08260cd 100644 --- a/tests/test_introspection.nim +++ b/tests/test_introspection.nim @@ -133,7 +133,7 @@ proc runSuite(ctx: GraphqlRef, savePoint: NameCounter, fileName: string, counter else: ctx.runExecutor(unit, testStatusIMPL) ctx.purgeQueries(false) - ctx.purgeSchema(false, false) + ctx.purgeSchema(false, false, false) ctx.purgeNames(savePoint) if testStatusIMPL == OK: inc counter.ok @@ -175,7 +175,7 @@ when isMainModule: test unit.name: ctx.runExecutor(unit, testStatusIMPL) ctx.purgeQueries(true) - ctx.purgeSchema(true, true) + ctx.purgeSchema(true, true, true) ctx.purgeNames(savePoint) var message: string diff --git a/tests/test_schemaintros.nim b/tests/test_schemaintros.nim index bd6d391..49a7f81 100644 --- a/tests/test_schemaintros.nim +++ b/tests/test_schemaintros.nim @@ -15,7 +15,7 @@ const schemaFolder = "tests" / "schemas" introsFolder = "tests" / "introspection" -proc runValidator(ctx: GraphqlRef, fileName: string, testStatusIMPL: var TestStatus) = +proc runValidator(ctx: GraphqlRef, fileName: string, testStatusIMPL: var TestStatus) = var res = ctx.parseSchemaFromFile(fileName) check res.isOk if res.isErr: @@ -45,7 +45,7 @@ proc runValidator(ctx: GraphqlRef, fileName: string, testStatusIMPL: var TestSta check ($jsonRes).len != 0 except: check false - + proc main() = suite "schema introspection validation": var ctx = new(GraphqlRef) @@ -57,7 +57,7 @@ proc main() = let parts = splitFile(fileName) test parts.name: ctx.runValidator(fileName, testStatusIMPL) - ctx.purgeSchema(true, true) + ctx.purgeSchema(true, true, true) ctx.purgeQueries(true) ctx.purgeNames(savePoint) diff --git a/tests/test_validation.nim b/tests/test_validation.nim index 301e010..18e15cd 100644 --- a/tests/test_validation.nim +++ b/tests/test_validation.nim @@ -101,7 +101,7 @@ proc runConverter(ctx: GraphqlRef, savePoint: NameCounter, path, output: string) for unit in mitems(cases.units): ctx.runConverter(unit) ctx.purgeQueries(false) - ctx.purgeSchema(false, false) + ctx.purgeSchema(false, false, false) ctx.purgeNames(savePoint) writeUnit(f, unit) @@ -141,7 +141,7 @@ proc runSuite(ctx: GraphqlRef, savePoint: NameCounter, fileName: string, counter else: ctx.runValidator(unit, testStatusIMPL) ctx.purgeQueries(false) - ctx.purgeSchema(false, false) + ctx.purgeSchema(false, false, false) ctx.purgeNames(savePoint) if testStatusIMPL == OK: inc counter.ok @@ -183,7 +183,7 @@ proc validateSchemas() = test fileName: ctx.runValidator(fileName, testStatusIMPL) ctx.purgeQueries(true) - ctx.purgeSchema(true, true) + ctx.purgeSchema(true, true, true) ctx.purgeNames(savePoint) when isMainModule: @@ -217,7 +217,7 @@ when isMainModule: test unit.name: ctx.runValidator(unit, testStatusIMPL) ctx.purgeQueries(true) - ctx.purgeSchema(true, true) + ctx.purgeSchema(true, true, true) ctx.purgeNames(savePoint) var message: string