objection
Version:
An SQL-friendly ORM for Node.js
115 lines (94 loc) • 2.82 kB
JavaScript
import clone from 'lodash/clone';
import Model from '../../model/Model';
import QueryBuilderOperation from './QueryBuilderOperation';
import {isPromise} from '../../utils/promiseUtils';
import Promise from 'bluebird';
export default class FindOperation extends QueryBuilderOperation {
clone(props) {
props = props || {};
return new this.constructor(this.name, props.opt || clone(this.opt));
}
onAfter(builder, results) {
if (this.opt.dontCallAfterGet) {
return results;
} else {
return callAfterGet(builder.context(), results, !!this.opt.callAfterGetDeeply);
}
}
}
function callAfterGet(ctx, results, deep) {
if (Array.isArray(results)) {
if (results.length === 1) {
return callAfterGetForOne(ctx, results[0], results, deep);
} else {
return callAfterGetArray(ctx, results, deep);
}
} else {
return callAfterGetForOne(ctx, results, results, deep);
}
}
function callAfterGetArray(ctx, results, deep) {
if (results.length === 0 || typeof results[0] !== 'object') {
return results;
}
const mapped = new Array(results.length);
let containsPromise = false;
for (let i = 0, l = results.length; i < l; ++i) {
mapped[i] = callAfterGetForOne(ctx, results[i], results[i], deep);
if (isPromise(mapped[i])) {
containsPromise = true;
}
}
if (containsPromise) {
return Promise.all(mapped);
} else {
return mapped;
}
}
function callAfterGetForOne(ctx, model, result, deep) {
if (!(model instanceof Model)) {
return result;
}
if (deep) {
const results = [];
const containsPromise = callAfterGetForRelations(ctx, model, results);
if (containsPromise) {
return Promise.all(results).then(() => {
return doCallAfterGet(ctx, model, result);
});
} else {
return doCallAfterGet(ctx, model, result);
}
} else {
return doCallAfterGet(ctx, model, result);
}
}
function callAfterGetForRelations(ctx, model, results) {
const relations = model.constructor.getRelationArray();
let containsPromise = false;
for (let i = 0, l = relations.length; i < l; ++i) {
const relName = relations[i].name;
if (model[relName]) {
const maybePromise = callAfterGet(ctx, model[relName], true);
if (isPromise(maybePromise)) {
containsPromise = true;
}
results.push(maybePromise);
}
}
return containsPromise;
}
function doCallAfterGet(ctx, model, result) {
if (model.$afterGet !== Model.prototype.$afterGet) {
const maybePromise = model.$afterGet(ctx);
if (maybePromise instanceof Promise) {
return maybePromise.return(result);
} else if (isPromise(maybePromise)) {
return maybePromise.then(() => result);
} else {
return result;
}
} else {
return result;
}
}