-
Notifications
You must be signed in to change notification settings - Fork 1
backend Overview
This package provides the database abstraction layer for Quatrain Core. It adds persistence capabilities to the in-memory objects from @quatrain/core.
-
Abstract Adapter:
AbstractBackendAdapterdefines a consistent interface for all database adapters. - Query Builder: A powerful query system with support for filtering, sorting, and pagination.
-
Dynamic Relational Collections:
CollectionPropertyrepresenting one-to-many and many-to-many parent-child associations. -
Server-Side Aggregations: Compute
sum,average,distinct,min,max, andcountaggregates natively in the database without loading entities into memory. -
Asynchronous Bulk Processing: Apply batch calculations and async transformations across collection elements using
.apply(). - Repositories: Implements the repository pattern for a clean data access layer.
- Middleware Support: Hooks for data transformation and validation before database operations.
npm install @quatrain/backendWhen performing calculations over huge datasets (like thousands of invoice lines), loading everything into application memory is extremely slow. @quatrain/backend allows you to execute these calculations natively in the database engine:
import { Invoice } from './models/Invoice'
import { CollectionProperty } from '@quatrain/backend'
// Load the invoice parent model
const invoice = await Invoice.fromBackend<Invoice>('invoice-uuid')
const lines = invoice.dataObject.get('lines') as CollectionProperty
// Calculate aggregate metrics directly in the database (Zero hydration overhead!)
const totalHT = await lines.sum('amount')
const averageLinePrice = await lines.average('amount')
const uniqueCategories = await lines.distinct('category')
const lineCount = await lines.count()
console.log(`Total HT: ${totalHT} €, Average: ${averageLinePrice} €, Items: ${lineCount}`)For complex business domain calculations where you need to run specific object lifecycle hooks, validation constraints, and database save triggers on each collection element, use .apply(fn):
// Apply a discount and persist all items using their own domain model logic
const updatedPrices = await lines.apply(async (line) => {
const newAmount = line.val('amount') * 0.9 // 10% discount
line.set('amount', newAmount)
// Save individually to trigger encryption/validation middlewares
await line.save()
return line.val('amount')
})For extensive production-grade examples, complete model setups, and step-by-step guides for Invoice/Billing Management (Facturation) and Groups/People Management, check out the:
AGPL-3.0-only