stackpress
Version:
Incept is a content management framework.
68 lines (67 loc) • 2.63 kB
JavaScript
import Exception from '../../Exception.js';
import { toResponse } from '../helpers.js';
import create from './create.js';
import update from './update.js';
export default async function batch(model, engine, rows, seed) {
const actions = rows.map(row => {
const action = model.ids.some(column => row[column.name] === undefined) ? 'create' : 'check';
return { row, action };
});
const check = actions.filter(({ action }) => action === 'check');
const q = engine.dialect.q;
const ids = model.ids.map(column => column.name);
const columns = model.ids.map(column => `${q}${column.snake}${q}`);
const clauses = columns.map(column => `${column} = ?`).join(' AND ');
const where = check.map(() => `(${clauses})`).join(' OR ');
const values = check.map(({ row }) => {
return ids.map(id => row[id]);
}).flat();
const results = [];
try {
let error = false;
await engine.transaction(async () => {
if (where.length > 0 && values.length > 0) {
const exists = await engine
.select(columns)
.from(model.snake)
.where(where, values);
for (const action of actions) {
if (action.action !== 'check')
continue;
action.action = exists.some(exist => ids.every(id => exist[id] === action.row[id])) ? 'update' : 'create';
}
}
for (const { row, action } of actions) {
if (action === 'create') {
const response = await create(model, engine, row, seed);
if (response.code !== 200)
error = true;
results.push(response);
}
else if (action === 'update') {
const filter = Object.fromEntries(ids.map(id => [id, row[id]]));
const response = await update(model, engine, filter, row, seed);
if (response.code !== 200)
error = true;
results.push(response);
}
}
if (error) {
throw Exception.for('Errors found in batch inputs');
}
});
}
catch (e) {
const error = Exception.upgrade(e);
return {
code: 400,
status: 'Bad Request',
error: error.message,
results: results,
total: results.length,
stack: error.trace()
};
}
return toResponse(results);
}
;