@avonjs/avonjs
Version:
A fluent Node.js API generator.
199 lines (198 loc) • 6.97 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = require("node:util/types");
const collect_js_1 = __importStar(require("collect.js"));
const Contracts_1 = require("../Contracts");
const Models_1 = require("../Models");
const Repository_1 = __importDefault(require("./Repository"));
class CollectionRepository extends Repository_1.default {
/**
* Resolve items from the store path.
*/
resolveItems() {
return [];
}
/**
* Prepare given items for collection.
*/
prepareItems(items) {
return items.map((item) => {
return item instanceof Models_1.Fluent ? item : new Models_1.Fluent(item);
});
}
/**
* Search storage for given query string.
*/
async search(search, page = 1, perPage = 15) {
const searched = this.searchCollection(search);
return {
count: searched.count(),
items: searched.slice(perPage * (page - 1), perPage).toArray(),
};
}
/**
* Find all model's for the given conditions.
*/
async all(wheres = []) {
return this.where(wheres).getCollection().toArray();
}
/**
* Search collection for given query string.
*/
searchCollection(search = '') {
const collection = this.getCollection();
return search.length > 0
? collection.filter((item) => this.performSearch(item, search))
: collection;
}
/**
* Get the collection with applied constraints.
*/
getCollection() {
let collection = this.makeCollection().filter((item) => {
return this.wheres.every((where) => this.checkAgainstWhere(item, where));
});
this.orders.forEach((order) => {
collection = collection[order.direction === Contracts_1.Direction.ASC ? 'sortBy' : 'sortByDesc'](order.key);
});
return this.modifiers.reduce((collection, modifier) => {
const modified = modifier(collection);
return modified instanceof collect_js_1.Collection ? modified : collection;
}, collection);
}
/**
* Make collection from entire data.
*/
makeCollection() {
return new collect_js_1.Collection(this.prepareItems(this.resolveItems()));
}
/**
* Apply the where constraint on the collection item.
*/
checkAgainstWhere(item, where) {
const value = item.getAttribute(where.key);
switch (where.operator) {
case Contracts_1.Operator.in:
case Contracts_1.Operator.eq:
return (0, collect_js_1.default)(Array.isArray(where.value) ? where.value : [where.value]).contains((where) => {
// compare numbers
if (Number(where) === value) {
return true;
}
// to handle soft deletes
if (where === null) {
return [where, undefined].includes(value);
}
// compare others
return where === value;
});
case Contracts_1.Operator.lte:
return value <= where.value;
case Contracts_1.Operator.gte:
return value >= where.value;
case Contracts_1.Operator.not:
case Contracts_1.Operator.notIn:
return !this.checkAgainstWhere(item, {
...where,
operator: Contracts_1.Operator.in,
});
case Contracts_1.Operator.lt:
return value < where.value;
case Contracts_1.Operator.gt:
return value > where.value;
case Contracts_1.Operator.like:
return new RegExp(where.value.replace(/%/g, '.*')).test(value ?? '');
default:
return true;
}
}
/**
* Perform searches on the given item.
*/
performSearch(item, search) {
for (const searchable in this.searchableColumns()) {
const searchCallback = this.searchableColumns()[searchable];
if ((0, types_1.isRegExp)(searchCallback) &&
searchCallback.test(item.getAttribute(searchable) ?? '')) {
return true;
}
if (typeof searchCallback === 'function' &&
searchCallback(search, item)) {
return true;
}
}
return false;
}
/**
* Store given model into the storage.
*/
async store(model) {
this.resolveItems().push(model
.setAttribute(model.getKeyName(), model.getKey() ?? this.newId())
.getAttributes());
return model;
}
/**
* Find first model for the given conditions.
*/
async first(wheres = []) {
this.where(wheres);
return this.getCollection().first();
}
/**
* Store given model into the storage.
*/
async update(model) {
const keyName = model.getKeyName();
const index = this.resolveItems().indexOf((item) => item[keyName] === model.getKey());
this.resolveItems()[index] = model.getAttributes();
return model;
}
/**
* Delete model for the given key.
*/
async delete(key) {
const keyName = this.model().getKeyName();
const index = this.resolveItems().indexOf((item) => item[keyName] === key);
this.resolveItems().splice(index, 1);
}
/**
* Create new instance of model.
*/
model() {
return new Models_1.Fluent();
}
/**
* Generate new id for storing item.
*/
newId() {
return Date.now();
}
}
exports.default = CollectionRepository;