Skip to content

v0.4.2

Latest

Choose a tag to compare

@wrsouza wrsouza released this 11 Jun 00:29

Bug Fixes

Static pagination and iteration methods on Model

The five pagination and iteration methods documented in the API were only reachable through the query builder (e.g. User.where(...).paginate()). Calling them directly on a model subclass — as shown in the documentation — threw a TypeScript error (ts(2339)). They are now available as static methods on every model:

// All of these now work directly on the model class
const page   = await User.paginate(15);        // Paginator<User>
const page   = await User.simplePaginate(20);  // SimplePaginator<User>

await User.chunk(200, async (users) => { /* ... */ });

for await (const user of User.cursor()) { /* ... */ }
for await (const user of User.lazy(500)) { /* ... */ }

All five methods accept the same arguments as their ModelBuilder equivalents and delegate directly to them.


New Features

ModelNotFoundException

findOrFail() and firstOrFail() now throw ModelNotFoundException instead of a generic Error. Import and catch it by type:

import { ModelNotFoundException } from '@wrsouza/orion';

try {
  const user = await User.findOrFail(99);
} catch (e) {
  if (e instanceof ModelNotFoundException) {
    // e.message → "[orion] No query results for model [User] with key 99."
  }
}

MassAssignmentException

When strict mass assignment is enabled (Model.preventSilentlyDiscardingAttributes()), attempting to fill a non-fillable attribute now throws MassAssignmentException instead of a generic Error:

import { Model, MassAssignmentException } from '@wrsouza/orion';

Model.preventSilentlyDiscardingAttributes();

try {
  await User.create({ name: 'Alice', role: 'admin' }); // 'role' not in @fillable
} catch (e) {
  if (e instanceof MassAssignmentException) {
    // e.message → "[orion] Add [role] to fillable on [User] to allow mass assignment."
  }
}

QueryException

All query execution failures (unique constraint violations, foreign key errors, connection drops, etc.) are now wrapped in a QueryException that exposes the SQL, bindings, and original driver error for structured error handling:

import { QueryException } from '@wrsouza/orion';

try {
  await User.create({ email: 'duplicate@example.com' });
} catch (e) {
  if (e instanceof QueryException) {
    console.log(e.sql);           // INSERT INTO "users" ...
    console.log(e.bindings);      // ['duplicate@example.com']
    console.log(e.cause.message); // duplicate key value violates unique constraint ...

    // Detect specific violations via driver error codes
    const isUnique = (e.cause as any).code === '23505'; // PostgreSQL
  }
}

Migration Guide

No breaking changes. All existing code continues to work.

  • If you were catching Error from findOrFail() or firstOrFail(), switch to ModelNotFoundException for a precise match — the generic Error catch will still work but is less specific.
  • QueryException extends Error, so existing generic catch blocks are unaffected.

Documentation

  • New Error Handling page covering all three exception classes with framework-specific examples for Express, Fastify, NestJS, Next.js, and React Router.
  • Fixed paginate(perPage, page) argument order in all integration examples — the arguments were shown in the wrong order in Express, Fastify, NestJS, Next.js, and React Router docs.
  • Added static method examples for paginate, simplePaginate, chunk, cursor, and lazy to the Pagination page.