diff --git a/server/database.js b/server/database.js index 59ff0ce..fd27910 100644 --- a/server/database.js +++ b/server/database.js @@ -30,7 +30,7 @@ authors = authors.map(a => { return a; }); -//get the book array +//get the books array let books = []; authors.forEach(a => books = books.concat(a.books)); diff --git a/server/handler.js b/server/handler.js index 7e767c7..9e25ab3 100644 --- a/server/handler.js +++ b/server/handler.js @@ -7,6 +7,24 @@ const handler = { Book: scalars => { //takes an array of scalar types as objects: { typeName: 'String', name: 'title' } //must return an array of objects containing the results + + return database.books.map(b => { + const ret = {}; + + if (scalars.some(s => s.name == 'title')) { + ret.title = b.title; + } + + if (scalars.some(s => s.name == 'author')) { + ret.author = b.author; + } + + if (scalars.some(s => s.name == 'published')) { + ret.published = b.published; + } + + return ret; + }); }, Author: scalars => { diff --git a/server/server.js b/server/server.js index 5a4a666..22b5f46 100644 --- a/server/server.js +++ b/server/server.js @@ -1,6 +1,8 @@ //express for testing const express = require('express'); +const bodyParser = require('body-parser'); const app = express(); +app.use(bodyParser.text()); //test the library const schema = require('./schema.js'); diff --git a/server/simpleQL/index.js b/server/simpleQL/index.js index e140a1d..6db4b2d 100644 --- a/server/simpleQL/index.js +++ b/server/simpleQL/index.js @@ -6,7 +6,34 @@ const main = (schema, handler) => { //the receiving function - this will be called multiple times return reqBody => { - return [200, '']; + //parse the query + const tokens = reqBody.split(/(\s+)/).filter(s => s.trim().length > 0); + let pos = 0; + + try { + //check for keywords + switch(tokens[pos++]) { + case 'create': + case 'update': + case 'delete': + throw 'keyword not implemented'; + //TODO + break; + + //no leading keyword - regular query + default: + const [result] = parseQuery(handler, tokens, pos, typeGraph[tokens[pos - 1]], typeGraph); + + return [200, result]; + + //TODO + break; + } + } + catch(e) { + console.log('caught', e); + return [400, e.stack || e]; + } }; }; @@ -14,10 +41,10 @@ const main = (schema, handler) => { const buildTypeGraph = schema => { //the default graph let graph = { - String: { scalar: true }, - Integer: { scalar: true }, - Float: { scalar: true }, - Boolean: { scalar: true }, + String: { scalar: true, nullable: true }, + Integer: { scalar: true, nullable: true }, + Float: { scalar: true, nullable: true }, + Boolean: { scalar: true, nullable: true }, }; //parse the schema @@ -92,8 +119,54 @@ const parseCompoundType = (tokens, pos) => { } return compound; -} +}; +const parseQuery = (handler, tokens, pos, typeGraph, superTypeGraph) => { + //cache this for later + const startPos = pos; + + //the opening brace + if (tokens[pos++] != '{') { + throw 'Expected \'{\' in query, found ' + tokens[pos - 1]; + } + + //the fields to pass to the handler + const queryFields = []; + + //while not at the end + while (tokens[pos] != '}') { + //not the end of the query + if (!tokens[pos]) { + throw 'Expected field in query, got end'; + } + + //prevent using keywords + if (['create', 'update', 'delete', 'set', 'match'].includes(tokens[pos])) { + throw 'Unexpected keyword ' + tokens[pos]; + } + + //type is a scalar, and can be queried + if (superTypeGraph[typeGraph[tokens[pos]].typeName].scalar) { + //push the scalar object to the queryFields + queryFields.push({ typeName: typeGraph[tokens[pos]].typeName, name: tokens[pos] }); + + pos++; + } else { + //parse the subquery using the correct sub-typegraph + const [result, increment] = parseQuery(handler, tokens, pos + 1, superTypeGraph[typeGraph[tokens[pos]].typeName], superTypeGraph); + + queryFields.push({ ...typeGraph[tokens[pos]], name: tokens[pos], subquery: handler[typeGraph[tokens[pos]].typeName](result) }); + + pos += increment + 1; + } + } + + console.log(' handler', queryFields); + + return [queryFields, pos - startPos]; +}; + +//utils const checkAlphaNumeric = (str) => { if (!/^[a-z0-9]+$/i.test(str)) { throw 'Unexpected string ' + str;