UNPKG

@avonjs/avonjs

Version:

A fluent Node.js API generator.

199 lines (198 loc) 6.97 kB
"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;