mirror of
https://github.com/Ratstail91/sineQL.git
synced 2025-11-29 02:34:28 +11:00
145 lines
4.5 KiB
JavaScript
145 lines
4.5 KiB
JavaScript
const { Op } = require('sequelize');
|
|
const { books, authors } = require('../database/models');
|
|
|
|
//TODO: 'unique' may be a useful modifier, but not at this stage of development
|
|
|
|
//The create handlers are supposed to handle inserting new data into a database
|
|
//You don't have to create all associated books at the same time as the authors - you can use update later to join them
|
|
|
|
//You can use the '[' and ']' symbols to create mutliple elements of data at once
|
|
|
|
//'create' also counts as a modifier, indicating that a specific value is new to the database, and returning an error if it exists already OR
|
|
//'match' is used when an existing value must already exist in the database, and returning an error if it does not OR
|
|
//if no modifiers are specified, 'set' is used as a fallback (query for compounds, create if not found)
|
|
|
|
/* possible create requests include:
|
|
|
|
create Author {
|
|
name "Sydney Sheldon"
|
|
create books [
|
|
{
|
|
title "The Naked Face"
|
|
published 1970
|
|
}
|
|
{
|
|
title "A Stranger in the Mirror"
|
|
published 1976
|
|
}
|
|
]
|
|
}
|
|
|
|
create Author {
|
|
name "Sydney Sheldon"
|
|
create books {
|
|
title "Bloodline"
|
|
published 1977
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
/* all create arguments look like this:
|
|
|
|
//Author array
|
|
[{
|
|
typeName: 'Author',
|
|
name: { typeName: 'String', scalar: true, create: 'Sydney Sheldon' }
|
|
books: [{
|
|
typeName: 'Book',
|
|
create: true,
|
|
title: { typeName: 'String', scalar: true, create: 'Bloodline' }
|
|
published: { typeName: 'Date', scalar: true, set: 1977 }
|
|
}, ...]
|
|
},
|
|
...]
|
|
|
|
*/
|
|
|
|
//higher level elements need to pass their IDs to sub-elements
|
|
const createHandlers = {
|
|
//complex compound
|
|
Author: async (create, graph) => {
|
|
//apply the following to an array of authors
|
|
const promises = create.map(async author => {
|
|
//get the fields alone
|
|
const { typeName, create, match, set, ...fields } = author;
|
|
|
|
//if we are creating a new element (default with Author as a top-level only type)
|
|
if (create) {
|
|
//check the created scalar fields (value must not exist in the database yet)
|
|
const createdOrs = Object.keys(fields).filter(field => fields[field].scalar && fields[field].create).map(field => { return { [field]: fields[field].create }; });
|
|
|
|
const createdFound = await authors.findOne({
|
|
where: {
|
|
[Op.or]: createdOrs
|
|
},
|
|
});
|
|
|
|
if (createdFound) {
|
|
//enter error state
|
|
Object.keys(fields).forEach(field => {
|
|
if (fields[field].create == createdFound[field]) {
|
|
throw `Cannot create Author ${field} with value ${fields[field].create} (value already exists)`;
|
|
}
|
|
});
|
|
|
|
//no error field found, continue?
|
|
}
|
|
|
|
//create the element
|
|
const args = {};
|
|
Object.keys(fields).filter(field => fields[field].scalar).forEach(field => args[field] = fields[field].create || fields[field].set);
|
|
const createdAuthor = await authors.create(args);
|
|
|
|
//pass on to the books
|
|
Object.keys(fields).filter(field => !fields[field].scalar).forEach(nonScalar => fields[nonScalar].forEach(element => element.authorId = createdAuthor.id));
|
|
Object.keys(fields).filter(field => !fields[field].scalar).forEach(nonScalar => {
|
|
//delegation
|
|
createHandlers[graph[typeName][nonScalar].typeName](fields[nonScalar], graph);
|
|
});
|
|
}
|
|
|
|
//if we are matching an existing element
|
|
else if (match) {
|
|
//check the matched scalar fields (value must exist in the database)
|
|
const matchedAnds = Object.keys(fields).filter(field => fields[field].scalar && fields[field].match).map(field => { return { [field]: fields[field].match }; });
|
|
|
|
//these only match one
|
|
const matchedFound = await authors.findOne({
|
|
where: {
|
|
[Op.and]: matchedAnds
|
|
}
|
|
});
|
|
|
|
if (!matchedFound) {
|
|
throw `Cannot match Author (no match exists)`;
|
|
}
|
|
|
|
//pass on to the books
|
|
Object.keys(fields).filter(field => !fields[field].scalar).forEach(nonScalar => fields[nonScalar].forEach(element => element.authorId = matchedAuthor.id));
|
|
Object.keys(fields).filter(field => !fields[field].scalar).forEach(nonScalar => {
|
|
//delegation
|
|
createHandlers[graph[typeName][nonScalar].typeName](fields[nonScalar], graph);
|
|
});
|
|
}
|
|
|
|
//get the remaining scalar fields without create or match ('set' by default), not used - just an error
|
|
else if (set) {
|
|
throw 'Set not implemented for create Author';
|
|
}
|
|
});
|
|
|
|
//handle promises
|
|
await Promise.all(promises).catch(e => console.error(e));
|
|
|
|
return null;
|
|
},
|
|
|
|
//simple compound
|
|
Book: async (create, graph) => {
|
|
//TODO: incomplete
|
|
console.log('-----', create)
|
|
}
|
|
};
|
|
|
|
module.exports = createHandlers; |