slim-ef
Version:
An implementation of basic entity framework functionnalities in typescript
226 lines • 8.46 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DbSet = exports.UnderlyingType = void 0;
const base_specification_1 = require("../specification/base.specification");
const specification_interface_1 = require("../specification/specification.interface");
const utilis_1 = require("./utilis");
const repository_decorator_1 = require("./repository.decorator");
const exception_1 = require("./exception");
exports.UnderlyingType = Symbol('__UnderlyingType');
class DbSet {
constructor(context) {
this.context = context;
this._queryTypeToExecute = specification_interface_1.QueryType.ALL;
this._baseSpec = new base_specification_1.BaseSpecification();
}
get [exports.UnderlyingType]() {
if (!this._underlyingType) {
this._underlyingType = repository_decorator_1.getEntitySchema(this);
}
return this._underlyingType;
}
set [exports.UnderlyingType](value) {
if (value) {
this._underlyingType = value;
}
}
add(...entities) {
return this.context.add(...utilis_1.patchM(this[exports.UnderlyingType])(...entities));
}
update(...entities) {
return this.context.update(...utilis_1.patchM(this[exports.UnderlyingType])(...entities));
}
unTrack(...entities) {
return this.context.unTrack(...utilis_1.patchM(this[exports.UnderlyingType])(...entities));
}
remove(...entities) {
return this.context.remove(...utilis_1.patchM(this[exports.UnderlyingType])(...entities));
}
async find(id) {
return await this.context.find(this[exports.UnderlyingType], id);
}
async exists(id) {
return !!(await this.find(id));
}
loadRelatedData(entity) {
return this.context.loadRelatedData(this._underlyingType, entity);
}
async firstOrDefault(predicate, context) {
this._baseSpec.applyPaging(0, 1);
this.where(predicate, context);
return await this.execute(specification_interface_1.QueryType.ONE);
}
async first(func, context) {
const elt = await this.firstOrDefault(func, context);
if (!elt)
throw new exception_1.EmptySetException();
return elt;
}
include(navigationPropertyPath) {
this._lastInclude = navigationPropertyPath;
this._baseSpec.addInclude(navigationPropertyPath);
return this;
}
thenInclude(navigationPropertyPath) {
this._baseSpec.addChainedInclude(this._lastInclude, navigationPropertyPath);
return this;
}
where(predicate, context) {
this._baseSpec.addCriteria(predicate, context);
return this;
}
take(count) {
this._baseSpec.applyPaging(this._currentSkip, count);
this._currentTake = count;
return this;
}
skip(count) {
this._baseSpec.applyPaging(count, this._currentTake);
this._currentSkip = count;
return this;
}
select(selector) {
const thisType = this[exports.UnderlyingType];
const includePaths = this._getIncludePaths();
this._onGoingPromise = this.context
.getMetadata(thisType, includePaths)
.then(proxyInstance => {
const res = selector(proxyInstance);
const fieldsToSelect = this._extractKeyFields(res);
const s = {
builder: selector,
fieldsToSelect
};
this._baseSpec.applySelector(s);
return true;
})
.catch(rej => {
if (rej.message &&
rej.message.includes('Cannot read property') &&
rej.message.includes('of undefined')) {
throw new Error('Select proxy cannot be build. You may have forget to include some properties using `.include` or `.thenInclude` or may be the selected property is not part of the entity schema. Internal Error: ' +
rej.message);
}
else {
throw new Error(rej);
}
});
return this;
}
_getIncludePaths() {
const spec = this.asSpecification();
return spec.getIncludePaths();
}
_extractKeyFields(res) {
const fieldsToSelect = [];
for (const k in res) {
if (k !== '$$propertyName' &&
Object.prototype.hasOwnProperty.call(res, k)) {
const element = res[k];
if (!element)
continue;
if (!Array.isArray(element)) {
const canGrind = !(element instanceof String) &&
!(element instanceof Number) &&
!(element instanceof Boolean) &&
element instanceof Object;
if (canGrind) {
fieldsToSelect.push(...this._extractKeyFields(element).map(e => ({
field: `${e.field}`
})));
}
else if (element.$$propertyName) {
fieldsToSelect.push({
field: element.$$propertyName
});
}
}
else {
const arrElt = element[0];
fieldsToSelect.push(...this._extractKeyFields(arrElt).map(e => ({
field: `${e.field}`
})));
}
}
}
return fieldsToSelect;
}
async count(predicate) {
this._baseSpec.addCriteria(predicate);
this._baseSpec.applyFunction('COUNT', null);
return Number.parseFloat((await this.execute(specification_interface_1.QueryType.RAW_ONE)).COUNT);
}
async sum(selector) {
this._baseSpec.applyFunction('SUM', selector);
return Number.parseFloat((await this.execute(specification_interface_1.QueryType.RAW_ONE)).SUM);
}
async average(selector) {
this._baseSpec.applyFunction('AVG', selector);
return Number.parseFloat((await this.execute(specification_interface_1.QueryType.RAW_ONE)).AVG);
}
async max(selector) {
this._baseSpec.applyFunction('MAX', selector);
return (await this.execute(specification_interface_1.QueryType.RAW_ONE)).MAX;
}
async min(selector) {
this._baseSpec.applyFunction('MIN', selector);
return (await this.execute(specification_interface_1.QueryType.RAW_ONE)).MIN;
}
orderBy(keySelector) {
this._baseSpec.applyOrderBy(keySelector);
return this;
}
thenOrderBy(keySelector) {
this._baseSpec.applyThenOrderBy(keySelector);
return this;
}
groupBy(keySelector) {
this._baseSpec.applyGroupBy(keySelector);
return this;
}
thenGroupBy(keySelector) {
this._baseSpec.applyThenGroupBy(keySelector);
return this;
}
orderByDescending(keySelector) {
this._baseSpec.applyOrderByDescending(keySelector);
return this;
}
asSpecification() {
return this._baseSpec;
}
ignoreQueryFilters() {
this._ignoreFilters = true;
return this;
}
distinct() {
this._baseSpec.applyDistinct();
return this;
}
fromSpecification(spec) {
this._baseSpec.extend(spec);
this._baseSpec.applySelector(spec.getSelector());
this._baseSpec.applyOrderBy(spec.getOrderBy());
this._baseSpec.applyOrderByDescending(spec.getOrderByDescending());
return this;
}
toList() {
return this.execute(this._queryTypeToExecute);
}
async execute(type) {
try {
if (!this._onGoingPromise || (await this._onGoingPromise)) {
const res = await this.context.execute(this, type, this._ignoreFilters);
this._baseSpec.clearSpecs();
return res;
}
}
catch (err) {
// wrapping this in finally, to clear specs on failure or success
this._baseSpec.clearSpecs();
throw err;
}
}
}
exports.DbSet = DbSet;
//# sourceMappingURL=db-set.js.map