Adjusted handler API

This commit is contained in:
2020-09-22 11:10:12 +10:00
parent 7f04a656c2
commit 0d245fdeb6
15 changed files with 2137 additions and 28 deletions

View File

@@ -0,0 +1,53 @@
//the authors
let authors = [
{
name: 'J.K. Roaring',
books: [
{ title: 'The Philosepher\'s Kidney Stone' },
{ title: 'The Chamber Pot of Secrets' },
{ title: 'The Prisoner of Aunt Kazban' },
{ title: 'The Goblet of the Fire Cocktail' },
{ title: 'The Order for Kleenex' },
{ title: 'The Half-Priced Pharmacy' },
{ title: 'Yeah, I Got Nothing' },
]
},
{
name: 'Kenneth Grahame',
books: [
{ title: 'The Wind in the Willows', published: '1 April 1908' }
]
},
{
name: 'Kayne Ruse',
books: [
{ title: 'alpha', published: "1" },
{ title: 'beta', published: "2" },
{ title: 'gamma', published: "3" },
{ title: 'delta', published: "4" },
{ title: 'epsilon', published: "5" },
]
},
];
//insert the authors into the books (relationship)
authors = authors.map(a => {
a.books = a.books.map(b => {
b.authors = [a];
return b;
});
return a;
});
//get the books array
let books = [];
authors.forEach(a => books = books.concat(a.books));
//the fake database
module.exports = {
authors,
books,
};

View File

@@ -0,0 +1,180 @@
/* DOCS: parameter types
parent: Type | null
scalars: [{ typeName: String, name: String, filter: any | null }, ...]
matching: Boolean
*/
const database = require('./database.js');
//the handler routines
const handler = {
//type queries
Author: (parent, scalars, matching) => {
console.log("Author", parent ? parent.context : null);
let authors;
//check parentage
if (parent) {
//find the author(s) of the parent Book object
authors = database.authors.filter(author => author.books.some(b => b.title == parent.context.title));
} else {
authors = database.authors;
}
//I am being matched (if true, ALL present scalars will have a filter field)
if (matching) {
//check every scalar to every author - a single false match is a miss on that author
authors = authors.filter(author => {
return scalars.every(scalar => {
//handle each type of scalar
switch (scalar.typeName) {
case 'String':
case 'Integer':
case 'Float':
case 'Boolean':
return author[scalar.name] == scalar.filter; //dumb comparison for now
//custom handling
//NOTE: Only books used the `Date` scalar
default:
throw `Unknown scalar typeName in handler: ${scalar.typeName} (${scalar.name})`;
}
});
});
//if there are no authors left, then the book's filters missed matches
if (authors.length == 0) {
return [];
}
}
//scalars are being matched on their own
if (scalars.some(s => s.filter)) {
//check every scalar to every author - a single match is a hit
authors = authors.filter(author => {
return scalars.some(scalar => {
//handle each type of scalar
switch (scalar.typeName) {
case 'String':
case 'Integer':
case 'Float':
case 'Boolean':
return author[scalar.name] == scalar.filter; //dumb comparison for now
//custom handling
//NOTE: Only books used the `Date` scalar
default:
throw `Unknown scalar typeName in handler: ${scalar.typeName} (${scalar.name})`;
}
});
});
//if there are no authors left, then the book's filters missed matches
if (authors.length == 0) {
return [];
}
}
//process (filter out unwanted fields) and return the array of authors
return authors.map(author => {
let ret = {};
//that's a big O(damn)
scalars.forEach(scalar => {
ret[scalar.name] = author[scalar.name];
});
return ret;
});
},
Book: (parent, scalars, matching) => {
console.log("Book", parent ? parent.context : null);
let books;
//check parentage
if (parent) {
//find the books of the parent author object
books = database.books.filter(book => book.authors.some(a => a.name == parent.context.name));
} else {
books = database.books;
}
//I am being matched (if true, ALL present scalars will have a filter field)
if (matching) {
//check every scalar to every book - a single false match is a miss on that book
books = books.filter(book => {
return scalars.every(scalar => {
//handle each type of scalar
switch (scalar.typeName) {
case 'String':
case 'Integer':
case 'Float':
case 'Boolean':
return book[scalar.name] == scalar.filter; //dumb comparison for now
//custom handling
case 'Date':
return book[scalar.name] == scalar.filter; //could have a more complex comparator function, like date-ranges
default:
throw `Unknown scalar typeName in handler: ${scalar.typeName} (${scalar.name})`;
}
});
});
//if there are no books left, then the authos's filters missed matches
if (books.length == 0) {
return [];
}
}
//scalars are being matched on their own
if (scalars.some(s => s.filter)) {
//check every scalar to every author - a single match is a hit
books = books.filter(author => {
return scalars.some(scalar => {
//handle each type of scalar
switch (scalar.typeName) {
case 'String':
case 'Integer':
case 'Float':
case 'Boolean':
return author[scalar.name] == scalar.filter; //dumb comparison for now
//custom handling
//NOTE: Only books used the `Date` scalar
default:
throw `Unknown scalar typeName in handler: ${scalar.typeName} (${scalar.name})`;
}
});
});
//if there are no authors left, then the book's filters missed matches
if (books.length == 0) {
return [];
}
}
//process (filter out unwanted fields) and return the array of books
return books.map(book => {
let ret = {};
//that's a big O(damn)
scalars.forEach(scalar => {
ret[scalar.name] = book[scalar.name];
});
return ret;
});
},
};
module.exports = handler;

1807
test-server-books/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
{
"name": "test-server",
"version": "0.2.1",
"description": "",
"main": "server.js",
"scripts": {
"start": "pm2 start server.js",
"restart": "pm2 restart server.js",
"stop": "pm2 stop server.js",
"list": "pm2 list",
"node": "node server.js"
},
"author": "Kayne Ruse",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"pm2": "^4.4.1"
}
}

View File

@@ -0,0 +1,14 @@
module.exports = `
scalar Date
type Author {
String name
Book books
}
type Book {
String title
Date published
Author authors
}
`;

View File

@@ -0,0 +1,27 @@
//express for testing
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(bodyParser.text());
//test the library
const schema = require('./schema.js');
const handler = require('./handler.js');
const sineQL = require('../source/index.js');
const sine = sineQL(schema, handler, { debug: false });
//open the end
app.post('/sineql', async (req, res) => {
const [code, result] = await sine(req.body);
res.status(code).send(result);
});
//startup
app.listen(process.env.WEB_PORT || 3100, err => {
console.log(`listening to *:${process.env.WEB_PORT || 3100}`);
});