mirror of
https://github.com/Ratstail91/sineQL.git
synced 2025-11-29 02:34:28 +11:00
Wrote some example client code
This commit is contained in:
@@ -1,20 +1,71 @@
|
|||||||
const database = require('./database.js');
|
const database = require('./database.js');
|
||||||
|
|
||||||
|
/* DOCS: The handler module connects the database to simpleQL.
|
||||||
|
* this will be user-implemented, but for now uses a fake database provided in database.js
|
||||||
|
* The 'scalars' will be objects containing a name and the type for each scalar field requested by a query.
|
||||||
|
* This can be used in several ways...
|
||||||
|
*
|
||||||
|
* The handlers should only handle scalar fields - compound fields will be queried separately by simpleQL.
|
||||||
|
*/
|
||||||
|
|
||||||
//the handler routines
|
//the handler routines
|
||||||
const handler = {
|
const handler = {
|
||||||
Book: scalars => {
|
Book: (parent, scalars) => {
|
||||||
|
//takes an object which is the result of the parent query, if there is one { typeName: 'Author', scalars: [scalars], context: parentObject }
|
||||||
|
//takes an array of scalar types as objects: { typeName: 'String', name: 'title' }
|
||||||
|
//must return an array of objects containing the results
|
||||||
|
|
||||||
|
let books = database.books;
|
||||||
|
|
||||||
|
//if this is a sub-query, use the parent to narrow the search
|
||||||
|
if (parent && parent.typeName == 'Author') {
|
||||||
|
//filter based on parent object
|
||||||
|
books = books.filter(b => b.author.name == parent.context.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return all books
|
||||||
|
const fields = scalars.map(s => s.name);
|
||||||
|
return books.map(b => {
|
||||||
|
const ret = {};
|
||||||
|
|
||||||
|
if (fields.includes('title')) {
|
||||||
|
ret.title = b.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.includes('published')) {
|
||||||
|
ret.published = b.published;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
Author: (parent, scalars) => {
|
||||||
|
let authors = database.authors;
|
||||||
|
|
||||||
|
//if this is a sub-query, use the parent to find the author
|
||||||
|
if (parent && parent.typeName == 'Book') {
|
||||||
|
return authors.find(a => a.books.filter(b => b.title == parent.context.title).length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return all authors
|
||||||
|
const fields = scalars.map(s => s.name);
|
||||||
|
return authors.map(a => {
|
||||||
|
const ret = {};
|
||||||
|
|
||||||
|
if (fields.includes('name')) {
|
||||||
|
ret.name = a.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
create: (matches, sets) => {
|
||||||
//TODO
|
//TODO
|
||||||
},
|
},
|
||||||
|
|
||||||
Author: scalars => {
|
update: (matches, sets) => {
|
||||||
//TODO
|
|
||||||
},
|
|
||||||
|
|
||||||
create: (sets, matches) => {
|
|
||||||
//TODO
|
|
||||||
},
|
|
||||||
|
|
||||||
update: (sets, matches) => {
|
|
||||||
//TODO
|
//TODO
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ const main = (schema, handler) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
//check for keywords
|
//check for keywords
|
||||||
switch(tokens[pos++]) {
|
switch(tokens[pos]) {
|
||||||
case 'create':
|
case 'create':
|
||||||
case 'update':
|
case 'update':
|
||||||
case 'delete':
|
case 'delete':
|
||||||
throw 'keyword not implemented';
|
throw 'keyword not implemented: ' + tokens[pos];
|
||||||
//TODO
|
//TODO
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//no leading keyword - regular query
|
//no leading keyword - regular query
|
||||||
default:
|
default:
|
||||||
//TODO: parse the query
|
parseQuery(handler, tokens, pos, typeGraph);
|
||||||
|
|
||||||
return [200, ''];
|
return [200, ''];
|
||||||
|
|
||||||
@@ -110,14 +110,19 @@ const parseCompoundType = (tokens, pos) => {
|
|||||||
type = type.slice(0, type.length - 2);
|
type = type.slice(0, type.length - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//no mangled types or names
|
||||||
|
checkAlphaNumeric(type);
|
||||||
|
checkAlphaNumeric(name);
|
||||||
|
|
||||||
//can't use keywords
|
//can't use keywords
|
||||||
if (['type', 'scalar'].includes(type) || ['type', 'scalar'].includes(name)) {
|
if (['type', 'scalar'].includes(type) || ['type', 'scalar'].includes(name)) {
|
||||||
throw 'Unexpected keyword found as type field or type name';
|
throw 'Unexpected keyword found as type field or type name';
|
||||||
}
|
}
|
||||||
|
|
||||||
//no mangled types or names
|
//check for duplicate fields
|
||||||
checkAlphaNumeric(type);
|
if (Object.keys(compound).includes(name)) {
|
||||||
checkAlphaNumeric(name);
|
throw 'Unexpected duplicate filed name';
|
||||||
|
}
|
||||||
|
|
||||||
//finally, push to the compound definition
|
//finally, push to the compound definition
|
||||||
compound[name] = {
|
compound[name] = {
|
||||||
@@ -130,6 +135,10 @@ const parseCompoundType = (tokens, pos) => {
|
|||||||
return compound;
|
return compound;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const parseQuery = (handler, tokens, pos, typeGraph) => {
|
||||||
|
//TODO
|
||||||
|
};
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
const checkAlphaNumeric = (str) => {
|
const checkAlphaNumeric = (str) => {
|
||||||
if (!/^[a-z0-9]+$/i.test(str)) {
|
if (!/^[a-z0-9]+$/i.test(str)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user