mevn-orm
Version:
simple ORM for express js
99 lines (98 loc) • 2.92 kB
JavaScript
/**
* Lazy relation query wrapper backed by Knex.
*
* Relation instances are {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise | Promise-like}:
* `await farmer.profile()` auto-executes the query. Chain `where()` before awaiting
* to refine the query, or call `first()` / `get()` explicitly.
*/
class Relation {
Related;
query;
constructor(Related, query) {
this.Related = Related;
this.query = query;
}
/**
* Appends a `where` constraint to the underlying Knex query.
*
* @param args - Knex `where` arguments (object or column/value pairs).
* @returns This relation instance for chaining.
*/
where(...args) {
this.query?.where(...args);
return this;
}
/**
* Executes the relation query and returns the first matching related model.
*
* @param columns - Columns to select (default `'*'`).
* @returns Related model instance, or `null` when no row matches.
*/
async first(columns = '*') {
if (!this.query) {
return null;
}
const row = await this.query.first(columns);
if (!row) {
return null;
}
const related = new this.Related(row);
return related.stripColumns(related);
}
/**
* Executes the relation query and returns all matching related models.
*
* @param columns - Columns to select (default `'*'`).
* @returns Array of related model instances (empty when no rows match).
*/
async get(columns = '*') {
if (!this.query) {
return [];
}
const rows = await this.query.select(columns);
return rows.map((row) => {
const related = new this.Related(row);
return related.stripColumns(related);
});
}
/**
* Allows `await relation` without calling `first()` or `get()` explicitly.
*
* @param onFulfilled - Success callback.
* @param onRejected - Error callback.
*/
then(onFulfilled, onRejected) {
return this.resolve().then(onFulfilled, onRejected);
}
}
/**
* One-to-one relation. Awaiting resolves to a single related model or `null`.
*
* @typeParam T - Related model instance type.
*/
class HasOneRelation extends Relation {
resolve() {
return this.first();
}
}
/**
* One-to-many relation. Awaiting resolves to an array of related models.
*
* @typeParam T - Related model instance type.
*/
class HasManyRelation extends Relation {
resolve() {
return this.get();
}
}
/**
* Inverse belongs-to relation. Awaiting resolves to the parent model or `null`.
*
* @typeParam T - Related model instance type.
*/
class BelongsToRelation extends Relation {
resolve() {
return this.first();
}
}
export { Relation, HasOneRelation, HasManyRelation, BelongsToRelation, };