Skip to content

Interface: ResourcefulModel

Enhanced Lucid model interface providing resourceful CRUD functionality.

This interface extends the base LucidModel with metadata-driven CRUD operations, field-level access control, query scoping, OpenAPI schema generation, and event handling capabilities. Models implementing this interface gain static methods for handling HTTP requests with built-in validation, pagination, filtering, and comprehensive security features.

The interface defines both metadata storage properties and operational methods that work together to provide a complete resourceful API layer on top of AdonisJS Lucid ORM models.

Example

typescript
import { BaseModel, column } from "@ioc:Adonis/Lucid/Orm";
import { withResourceful, resourceful } from "lucid-resourceful";

class User extends withResourceful()(BaseModel) implements ResourcefulModel {
  @column({ isPrimary: true })
  @resourceful({ type: "number", nullable: false })
  public id: number;

  @column()
  @resourceful({ type: "string", nullable: false })
  public name: string;

  // Automatically gains all ResourcefulModel methods
  // User.$onResourcefulIndex, User.$onResourcefulRead, etc.
}

Extends

Constructors

Constructor

ts
new ResourcefulModel(): LucidRow;

Returns

LucidRow

Inherited from

LucidModel.constructor

Properties

PropertyModifierTypeDescriptionInherited from
$adapterpublicAdapterContractAdapter to work as a bridge between query builder and the modelLucidModel.$adapter
$columnsDefinitionspublicMap<string, ModelColumnOptions>A map of defined columnsLucidModel.$columnsDefinitions
$computedDefinitionspublicMap<string, ComputedOptions>A map of computed propertiesLucidModel.$computedDefinitions
$hookspublicHooks<any>Reference to hooksLucidModel.$hooks
$keyspublic{ attributesToColumns: ModelKeysContract; attributesToSerialized: ModelKeysContract; columnsToAttributes: ModelKeysContract; columnsToSerialized: ModelKeysContract; serializedToAttributes: ModelKeysContract; serializedToColumns: ModelKeysContract; }A copy of internal keys mapping. One should be able to resolve between all key versionsLucidModel.$keys
$keys.attributesToColumnspublicModelKeysContract--
$keys.attributesToSerializedpublicModelKeysContract--
$keys.columnsToAttributespublicModelKeysContract--
$keys.columnsToSerializedpublicModelKeysContract--
$keys.serializedToAttributespublicModelKeysContract--
$keys.serializedToColumnspublicModelKeysContract--
$relationsDefinitionspublicMap<string, RelationshipsContract>A map of defined relationshipsLucidModel.$relationsDefinitions
$resourcefulAccessControlFilterspublic{ create: ResourcefulGeneralAccessControlFilter[]; delete: ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]; list: ResourcefulGeneralAccessControlFilter[]; read: ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]; update: ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]; }Access control filter functions organized by CRUD operation type-
$resourcefulAccessControlFilters.createpublicResourcefulGeneralAccessControlFilter[]--
$resourcefulAccessControlFilters.deletepublicResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]--
$resourcefulAccessControlFilters.listpublicResourcefulGeneralAccessControlFilter[]--
$resourcefulAccessControlFilters.readpublicResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]--
$resourcefulAccessControlFilters.updatepublicResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[]--
$resourcefulColumnspublicMap<string, ResourcefulColumnDefinition<ResourcefulPropertySchema>>Map of column property names to their resourceful metadata definitions-
$resourcefulComputedAccessorspublicMap<string, ResourcefulComputedAccessorDefinition<ResourcefulPropertySchema>>Map of computed accessor property names to their resourceful metadata definitions-
$resourcefulEnforcedPreloadspublicSet<string>Set of enforced preloads for the model-
$resourcefulMetaDescription?publicstringOptional description for OpenAPI schema documentation-
$resourcefulMetaExample?publicstringOptional example value for OpenAPI schema documentation-
$resourcefulMetaExternalDocs?publicExternalDocumentationObjectOptional external documentation reference for OpenAPI schema-
$resourcefulNamepublicstringThe display name for this model used in API documentation and error messages-
$resourcefulOnACLErrorpublic"bubble" | "pass" | "fail"Error handling strategy when ACL evaluation fails-
$resourcefulPayloadValidationSchemaBuilderspublic{ create: ResourcefulPayloadValidatorGetter[]; update: ResourcefulPayloadValidatorGetter[]; }Payload validation schema builder functions for create and update operations-
$resourcefulPayloadValidationSchemaBuilders.createpublicResourcefulPayloadValidatorGetter[]--
$resourcefulPayloadValidationSchemaBuilders.updatepublicResourcefulPayloadValidatorGetter[]--
$resourcefulQueryScopeCallbackspublic{ access: ResourcefulQueryScopeCallback[]; list: ResourcefulQueryScopeCallback[]; }Query scope callback functions for constraining database queries-
$resourcefulQueryScopeCallbacks.accesspublicResourcefulQueryScopeCallback[]--
$resourcefulQueryScopeCallbacks.listpublicResourcefulQueryScopeCallback[]--
$resourcefulRelationshipspublicMap<string, ResourcefulRelationshipDefinition<LucidModel>>Map of relationship property names to their resourceful metadata definitions-
$resourcefulTitleColumn?publicstringThe column used as the title of the model instance when displayed in a list-
bootedreadonlybooleanWhether or not model has been booted. After this model configurations are ignoredLucidModel.booted
connection?publicstringCustom database connection to useLucidModel.connection
namingStrategypublicNamingStrategyContractNaming strategy to useLucidModel.namingStrategy
primaryKeypublicstringThe primary key for finding unique referencing to a modelLucidModel.primaryKey
selfAssignPrimaryKeypublicbooleanSelf assign the primary instead of relying on the database to return it backLucidModel.selfAssignPrimaryKey
tablepublicstringDatabase table to useLucidModel.table
transactionpublicTransactionFnReturns transaction client from the model. It is same as calling "db.transaction"LucidModel.transaction

Methods

$addColumn()

ts
$addColumn(name: string, options: Partial<ColumnOptions>): ColumnOptions;

Managing columns

Parameters

ParameterType
namestring
optionsPartial<ColumnOptions>

Returns

ColumnOptions

Inherited from

LucidModel.$addColumn


$addComputed()

ts
$addComputed(name: string, options: Partial<ComputedOptions>): ComputedOptions;

Managing computed columns

Parameters

ParameterType
namestring
optionsPartial<ComputedOptions>

Returns

ComputedOptions

Inherited from

LucidModel.$addComputed


$addRelation()

ts
$addRelation(
   name: string,
   type: "hasOne" | "hasMany" | "belongsTo" | "manyToMany" | "hasManyThrough",
   relatedModel: () => LucidModel,
   options: ModelRelationOptions): void;

Managing relationships

Parameters

ParameterType
namestring
type"hasOne" | "hasMany" | "belongsTo" | "manyToMany" | "hasManyThrough"
relatedModel() => LucidModel
optionsModelRelationOptions

Returns

void

Inherited from

LucidModel.$addRelation


$asOpenApiSchemaObject()

ts
$asOpenApiSchemaObject(
   ctx: HttpContext,
   app: ApplicationService,
   operation?: "read" | "write",
methodOptions?: GenerateModelSchemaOptions): Promise<ResourcefulModelOpenApiSchema>;

Generates an OpenAPI schema object for this model with context-aware field filtering.

This method creates a complete OpenAPI v3 schema representation of the model by evaluating field-level access control permissions for the given request context. Only fields that pass ACL checks are included in the generated schema, ensuring that API documentation accurately reflects what data is accessible to the current user.

The method processes all resourceful properties (columns, computed accessors, and relationships) and converts them to their OpenAPI schema equivalents while respecting access control constraints and applying proper type mappings.

Parameters

ParameterTypeDescription
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
operation?"read" | "write"The type of operation. To honor field-level ACL
methodOptions?GenerateModelSchemaOptions-

Returns

Promise<ResourcefulModelOpenApiSchema>

Promise resolving to a complete OpenAPI schema object with:

  • type: Always 'object' for model schemas
  • title: The model's resourceful name
  • description: Optional model description from metadata
  • properties: Object containing schema definitions for accessible fields
  • required: Array of required field names (non-nullable fields)
  • externalDocs: Optional external documentation reference
  • example: Optional example value for the schema

Example

typescript
// Generate OpenAPI schema for current user context
const schema = await User.$asOpenApiSchemaObject(ctx, app, 'read');

// Result structure:
{
  type: 'object',
  title: 'User',
  properties: {
    id: { type: 'number', readOnly: true },
    name: { type: 'string' },
    email: { type: 'string', format: 'email' }
  },
  required: ['id', 'name', 'email']
}

See

ResourcefulModelOpenApiSchema for the complete schema structure


$createFromAdapterResult()

ts
$createFromAdapterResult<T>(
   this: T,
   result?: ModelObject,
   sideloadAttributes?: ModelObject,
   options?: ModelAdapterOptions):
  | InstanceType<T>
  | null;

Creating model from adapter results

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
result?ModelObject
sideloadAttributes?ModelObject
options?ModelAdapterOptions

Returns

| InstanceType<T> | null

Inherited from

LucidModel.$createFromAdapterResult


$createFromHttpContext()

ts
$createFromHttpContext(ctx: HttpContext): Promise<LucidRow>;

Creates a new model instance from HTTP context data.

Parameters

ParameterTypeDescription
ctxHttpContextThe HTTP context containing the request data

Returns

Promise<LucidRow>

A Promise that resolves to a new model instance


$createMultipleFromAdapterResult()

ts
$createMultipleFromAdapterResult<T>(
   this: T,
   results: ModelObject[],
   sideloadAttributes?: ModelObject,
   options?: ModelAdapterOptions): InstanceType<T>[];

Creating multiple model instances from an array of adapter result

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
resultsModelObject[]
sideloadAttributes?ModelObject
options?ModelAdapterOptions

Returns

InstanceType<T>[]

Inherited from

LucidModel.$createMultipleFromAdapterResult


$defineProperty()

ts
$defineProperty<Model, Prop>(
   this: Model,
   propertyName: Prop,
   defaultValue: Model[Prop],
   strategy: "inherit" | "define" | (value: Model[Prop]) => Model[Prop]): void;

Define a static property on the model using the inherit or define strategy.

Inherit strategy will clone the property from the parent model and will set it on the current model

Type Parameters

Type Parameter
Model extends LucidModel
Prop extends string | number | symbol

Parameters

ParameterType
thisModel
propertyNameProp
defaultValueModel[Prop]
strategy"inherit" | "define" | (value: Model[Prop]) => Model[Prop]

Returns

void

Inherited from

LucidModel.$defineProperty


$getAsResourcefulForContext()

ts
$getAsResourcefulForContext(ctx: HttpContext, app: ApplicationService): Promise<ResourcefulModelMetaSchema>;

Parameters

ParameterType
ctxHttpContext
appApplicationService

Returns

Promise<ResourcefulModelMetaSchema>


$getColumn()

ts
$getColumn(name: string):
  | ModelColumnOptions
  | undefined;

Parameters

ParameterType
namestring

Returns

| ModelColumnOptions | undefined

Inherited from

LucidModel.$getColumn


$getComputed()

ts
$getComputed(name: string): ComputedOptions | undefined;

Parameters

ParameterType
namestring

Returns

ComputedOptions | undefined

Inherited from

LucidModel.$getComputed


$getRelation()

Call Signature

ts
$getRelation<Model, Name>(this: Model, name: Name): NonNullable<InstanceType<Model>[Name]> extends ModelRelations<LucidModel, LucidModel> ? NonNullable<NonNullable<InstanceType<Model>[Name]>>["client"]["relation"] : RelationshipsContract;

Get relationship declaration

Type Parameters
Type Parameter
Model extends LucidModel
Name extends string | number | symbol
Parameters
ParameterType
thisModel
nameName
Returns

NonNullable<InstanceType<Model>[Name]> extends ModelRelations<LucidModel, LucidModel> ? NonNullable<NonNullable<InstanceType<Model>[Name]>>["client"]["relation"] : RelationshipsContract

Inherited from

LucidModel.$getRelation

Call Signature

ts
$getRelation<Model>(this: Model, name: string): RelationshipsContract;
Type Parameters
Type Parameter
Model extends LucidModel
Parameters
ParameterType
thisModel
namestring
Returns

RelationshipsContract

Inherited from

LucidModel.$getRelation


$getResourcefulWriteValidationSchema()

ts
$getResourcefulWriteValidationSchema(
   ctx: HttpContext,
   app: ApplicationService,
   forUpdate?: boolean): Promise<{
  schema: ResourcefulModelOpenApiSchema;
  validator: ObjectSchema<any>;
}>;

Parameters

ParameterType
ctxHttpContext
appApplicationService
forUpdate?boolean

Returns

Promise<{ schema: ResourcefulModelOpenApiSchema; validator: ObjectSchema<any>; }>


$hasColumn()

ts
$hasColumn(name: string): boolean;

Parameters

ParameterType
namestring

Returns

boolean

Inherited from

LucidModel.$hasColumn


$hasComputed()

ts
$hasComputed(name: string): boolean;

Parameters

ParameterType
namestring

Returns

boolean

Inherited from

LucidModel.$hasComputed


$hasRelation()

ts
$hasRelation(name: string): boolean;

Find if a relationship exists

Parameters

ParameterType
namestring

Returns

boolean

Inherited from

LucidModel.$hasRelation


$offResourcefulEvent()

ts
$offResourcefulEvent<K>(event: Key<K, ResourcefulMixinEventMap<Model, ModelInstance>>, listener?: Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>>): this;

Removes an event listener for resourceful model events.

Unregisters a previously registered event listener. If no listener is provided, all listeners for the specified event are removed.

Type Parameters

Type ParameterDescription
KThe event key type from the resourceful event map

Parameters

ParameterTypeDescription
eventKey<K, ResourcefulMixinEventMap<Model, ModelInstance>>The name of the event to stop listening for
listener?Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>>Optional specific listener function to remove

Returns

this

The model class for method chaining

Example

typescript
// Remove specific listener
User.$offResourcefulEvent("acl:error", myErrorHandler);

// Remove all listeners for an event
User.$offResourcefulEvent("acl:error");

$onceResourcefulEvent()

ts
$onceResourcefulEvent<K>(event: Key<K, ResourcefulMixinEventMap<Model, ModelInstance>>, listener: Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>>): this;

Registers a one-time event listener for resourceful model events.

Similar to $onResourcefulEvent but the listener is automatically removed after being called once. Useful for handling events that should only trigger a single response.

Type Parameters

Type ParameterDescription
KThe event key type from the resourceful event map

Parameters

ParameterTypeDescription
eventKey<K, ResourcefulMixinEventMap<Model, ModelInstance>>The name of the event to listen for
listenerListener<K, ResourcefulMixinEventMap<Model, ModelInstance>>Function to call when the event is emitted

Returns

this

The model class for method chaining

Example

typescript
User.$onceResourcefulEvent(
  "validation:scope:error",
  (error, ctx, app, key, datatype) => {
    console.warn("Validation scope error (one-time):", error);
  },
);

$onResourcefulBulkUpdate()

ts
$onResourcefulBulkUpdate(
   filter: string | null | undefined,
   payload: any,
   ctx: HttpContext,
   app: ApplicationService,
   hooks?: Partial<ResourcefulHooks>): Promise<
  | Error
  | {
[key: string]: any;
}>;

Parameters

ParameterType
filterstring | null | undefined
payloadany
ctxHttpContext
appApplicationService
hooks?Partial<ResourcefulHooks>

Returns

Promise< | Error | { [key: string]: any; }>


$onResourcefulBulkUpdateByUid()

ts
$onResourcefulBulkUpdateByUid(
   uids: (string | number)[],
   payload: any,
   ctx: HttpContext,
   app: ApplicationService,
   hooks?: Partial<ResourcefulHooks>): Promise<{
[key: string]: any;
}>;

Parameters

ParameterType
uids(string | number)[]
payloadany
ctxHttpContext
appApplicationService
hooks?Partial<ResourcefulHooks>

Returns

Promise<{ [key: string]: any; }>


$onResourcefulCreate()

ts
$onResourcefulCreate(
   payload: any,
   ctx: HttpContext,
   app: ApplicationService,
hooks?: ResourcefulValidationHooks): Promise<any>;

Creates a new model record with payload validation and access control.

This method handles secure record creation by validating the request payload against both model-level and request-specific validation schemas, checking field-level write permissions, and returning the created record with appropriate field filtering applied.

Parameters

ParameterTypeDescription
payloadanyThe data object containing field values for the new record
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
hooks?ResourcefulValidationHooksOptional array of validation schema getters for additional payload validation

Returns

Promise<any>

Promise resolving to the created record with only accessible fields

Throws

When the model has no identifiable primary key

Throws

When core model validation fails

Throws

When request-specific validation fails

Throws

When access is denied by model-level or field-level ACL filters

Example

typescript
// Create a new user
const user = await User.$onResourcefulCreate(
  {
    name: "John Doe",
    email: "john@example.com",
  },
  ctx,
  app,
);

// With additional validation
const user = await User.$onResourcefulCreate(payload, ctx, app, [
  (ctx, app) => joi.object({ email: joi.string().domain("company.com") }),
]);

$onResourcefulDelete()

ts
$onResourcefulDelete(
   uid: number,
   ctx: HttpContext,
   app: ApplicationService,
hooks?: ResourcefulScopeHooks): Promise<void>;

Deletes an existing model record with access control.

This method implements secure record deletion by applying query scope callbacks to verify the record exists within the user's access scope, checking delete permissions via ACL filters, and then removing the record from the database.

Parameters

ParameterTypeDescription
uidnumberThe unique identifier of the record to delete
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
hooks?ResourcefulScopeHooksOptional array of query scope callbacks to apply additional filtering constraints

Returns

Promise<void>

Promise that resolves when the record has been successfully deleted

Throws

When the model has no identifiable primary key

Throws

When no record exists with the given ID or user lacks access

Throws

When access is denied by model-level ACL filters

Example

typescript
// Delete a user
await User.$onResourcefulDelete(123, ctx, app);

// With additional query scoping
await User.$onResourcefulDelete(123, ctx, app, [
  (ctx, app, query) => query.where("tenant_id", ctx.auth.user.tenantId),
]);

$onResourcefulEvent()

ts
$onResourcefulEvent<K>(event: Key<K, ResourcefulMixinEventMap<Model, ModelInstance>>, listener: Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>>): this;

Registers an event listener for resourceful model events.

This method provides a way to listen for events emitted during resourceful operations such as ACL errors or validation scope errors. Useful for logging, monitoring, or implementing custom error handling logic.

Type Parameters

Type ParameterDescription
KThe event key type from the resourceful event map

Parameters

ParameterTypeDescription
eventKey<K, ResourcefulMixinEventMap<Model, ModelInstance>>The name of the event to listen for ('acl:error', 'validation:scope:error')
listenerListener<K, ResourcefulMixinEventMap<Model, ModelInstance>>Function to call when the event is emitted

Returns

this

The model class for method chaining

Example

typescript
User.$onResourcefulEvent("acl:error", (error, ctx, app, instance) => {
  console.error("ACL error occurred:", error);
});

$onResourcefulIndex()

ts
$onResourcefulIndex(
   filter: string | null | undefined,
   page: number,
   perPage: number,
   fields: string | string[] | null | undefined,
   sort: [string, "asc" | "desc"][] | null | undefined,
   ctx: HttpContext,
   app: ApplicationService,
   hooks?: ResourcefulScopeHooks,
   aggregations?: ResourcefulIndexAggregateOptions): Promise<ResourcefulIndexResult<{
[key: string]: any;
}>>;

Performs paginated listing and searching of model records with comprehensive filtering and aggregations.

This method provides the core implementation for resourceful index/list operations, supporting pagination, field selection, access control, aggregations, and Lucene query syntax for filtering. It validates all inputs, applies ACL filters, executes the query with proper field mapping between serialized names and database columns, and returns structured results with query metadata and computed aggregations.

Parameters

ParameterTypeDescription
filterstring | null | undefinedLucene-style query string for filtering records (e.g., "name:john AND email:*.com"). If null or undefined, defaults to empty string (no filtering).
pagenumberThe page number for pagination (must be ≥ 1). Used with perPage to calculate offset.
perPagenumberNumber of records per page (must be ≥ 1 and ≤ 100 by default).
fieldsstring | string[] | null | undefinedArray of field names to include in the response. If null, undefined, or empty, defaults to just the primary key field. Field names should use serialized names (as they appear in API responses), not database column names.
sort[string, "asc" | "desc"][] | null | undefinedArray of sort specifications as [fieldName, direction] tuples. Field names must be marked as sortable in their column definitions.
ctxHttpContextHTTP context containing request information, authentication, and other request-scoped data.
appApplicationServiceApplication service instance providing access to application-level services and configuration.
hooks?ResourcefulScopeHooksOptional array of query scope callbacks to apply additional filtering constraints.
aggregations?ResourcefulIndexAggregateOptionsOptional object specifying aggregations to compute. Maps field names to arrays of aggregation methods. Only fields marked as aggregatable can be aggregated.

Returns

Promise<ResourcefulIndexResult<{ [key: string]: any; }>>

Promise resolving to ResourcefulIndexResult containing:

  • records: Array of partial record objects with only the requested fields
  • total: Total number of records matching the filter (before pagination)
  • page: The requested page number (echoed back)
  • perPage: The requested per-page limit (echoed back)
  • aggregations: Computed aggregation results organized by field and method
  • countQuery: SQL query string used for counting total records
  • recordsQuery: SQL query string used for fetching the actual records

Throws

When the model has no identifiable primary key

Throws

When access is denied by model-level or field-level ACL filters

Throws

When no fields are available for access after ACL filtering

Throws

When input validation fails

Throws

When attempting to aggregate on non-aggregatable fields

Throws

When using invalid aggregation methods

Example

typescript
// Basic usage with pagination
const result = await User.$onResourcefulIndex(
  "name:john",
  1,
  10,
  ["id", "name", "email"],
  null,
  ctx,
  app,
);

// Complex filtering with date ranges and aggregations
const result = await User.$onResourcefulIndex(
  "status:active AND createdAt:[2021-01-01T00:00:00Z TO 2021-12-31T23:59:59Z]",
  2,
  25,
  ["id", "name", "totalSales"],
  [["createdAt", "desc"]],
  ctx,
  app,
  [],
  {
    totalSales: ["sum", "avg", "max"],
    orderCount: ["sum"],
    customerId: ["countDistinct"],
  },
);

$onResourcefulRead()

ts
$onResourcefulRead(
   uid: number,
   ctx: HttpContext,
   app: ApplicationService,
hooks?: ResourcefulScopeHooks): Promise<any>;

Retrieves a single model record by its unique identifier with access control.

This method implements secure record retrieval by first applying query scope callbacks to verify the record exists within the user's access scope, then fetching the full model instance for field-level ACL evaluation. Only fields that pass ACL checks are included in the response.

Parameters

ParameterTypeDescription
uidnumberThe unique identifier of the record to retrieve
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
hooks?ResourcefulScopeHooksOptional array of query scope callbacks to apply additional filtering constraints

Returns

Promise<any>

Promise resolving to the record object with only accessible fields

Throws

When the model has no identifiable primary key

Throws

When no record exists with the given ID or user lacks access

Throws

When access is denied by model-level or field-level ACL filters

Example

typescript
// Retrieve a user by ID
const user = await User.$onResourcefulRead(123, ctx, app);

// With additional query scoping
const user = await User.$onResourcefulRead(123, ctx, app, [
  (ctx, app, query) => query.where("tenant_id", ctx.auth.user.tenantId),
]);

$onResourcefulReadRelationship()

ts
$onResourcefulReadRelationship(
   uid: any,
   relationshipKey: string,
   filter: string | null | undefined,
   page: number,
   perPage: number,
   fields: string | string[] | null | undefined,
   sort: [string, "asc" | "desc"][] | null | undefined,
   ctx: HttpContext,
   app: ApplicationService,
   hooks?: ResourcefulScopeHooks,
   aggregations?: ResourcefulIndexAggregateOptions): Promise<ResourcefulIndexResult<{
[key: string]: any;
}>>;

Loads a specific relationship for a model record with pagination, filtering, and access control.

This method provides paginated relationship loading by leveraging the related model's $onResourcefulIndex method with automatically generated relationship constraints. It supports full filtering, sorting, and pagination capabilities while maintaining proper access control and scoping.

Parameters

ParameterTypeDescription
uidanyThe unique identifier of the parent record
relationshipKeystringThe name of the relationship property to load
filterstring | null | undefinedLucene-style query string for filtering related records
pagenumberThe page number for pagination (must be ≥ 1)
perPagenumberNumber of records per page (must be ≥ 1 and ≤ 100)
fieldsstring | string[] | null | undefinedArray of field names to include in the response from the related model
sort[string, "asc" | "desc"][] | null | undefinedArray of sort criteria as [field, direction] tuples
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
hooks?ResourcefulScopeHooksOptional array of additional query scope callbacks
aggregations?ResourcefulIndexAggregateOptions-

Returns

Promise<ResourcefulIndexResult<{ [key: string]: any; }>>

Promise resolving to paginated relationship results

Throws

When the model has no identifiable primary key

Throws

When the specified relationship doesn't exist

Throws

When access is denied by model-level or field-level ACL filters

Throws

When input validation fails

Example

typescript
// Load user's posts with filtering and pagination
const userPosts = await Post.$onResourcefulReadRelationship(
  123, // user ID
  "posts", // relationship name
  "status:published", // filter
  1, // page
  10, // perPage
  ["id", "title"], // fields
  [["createdAt", "desc"]], // sort
  ctx,
  app,
);

// Load user's skills (many-to-many)
const userSkills = await Skill.$onResourcefulReadRelationship(
  123,
  "skills",
  null, // no filter
  1,
  50,
  null, // all fields
  null, // default sort
  ctx,
  app,
);

$onResourcefulUpdate()

ts
$onResourcefulUpdate(
   uid: number,
   payload: any,
   ctx: HttpContext,
   app: ApplicationService,
hooks?: Partial<ResourcefulHooks>): Promise<any>;

Updates an existing model record with payload validation and access control.

This method implements secure record updates by first verifying the record exists and is accessible via the read operation, validating the update payload, checking field-level write permissions, and returning the updated record with appropriate field filtering applied.

Parameters

ParameterTypeDescription
uidnumberThe unique identifier of the record to update
payloadanyThe data object containing field values to update
ctxHttpContextHTTP context containing request information and authentication
appApplicationServiceApplication service instance for accessing app-level services
hooks?Partial<ResourcefulHooks>Optional object containing query scope callbacks and validation schema getters

Returns

Promise<any>

Promise resolving to the updated record with only accessible fields

Throws

When the model has no identifiable primary key

Throws

When no record exists with the given ID or user lacks access

Throws

When core model validation fails

Throws

When request-specific validation fails

Throws

When access is denied by model-level or field-level ACL filters

Example

typescript
// Update a user
const user = await User.$onResourcefulUpdate(
  123,
  {
    name: "Jane Doe",
  },
  ctx,
  app,
);

// With additional scoping and validation
const user = await User.$onResourcefulUpdate(123, payload, ctx, app, {
  queryScopeCallbacks: [(ctx, app, query) => query.where("active", true)],
  payloadValidationSchemas: [(ctx, app) => customValidationSchema],
});

after()

Call Signature

ts
after<Model>(
   this: Model,
   event: "fetch",
   handler: HooksHandler<InstanceType<Model>[], "fetch">): void;

Register an after hook

Type Parameters
Type Parameter
Model extends LucidModel
Parameters
ParameterType
thisModel
event"fetch"
handlerHooksHandler<InstanceType<Model>[], "fetch">
Returns

void

Inherited from

LucidModel.after

Call Signature

ts
after<Model>(
   this: Model,
   event: "paginate",
   handler: HooksHandler<ModelPaginatorContract<InstanceType<Model>>, "paginate">): void;
Type Parameters
Type Parameter
Model extends LucidModel
Parameters
ParameterType
thisModel
event"paginate"
handlerHooksHandler<ModelPaginatorContract<InstanceType<Model>>, "paginate">
Returns

void

Inherited from

LucidModel.after

Call Signature

ts
after<Model, Event>(
   this: Model,
   event: Event,
   handler: HooksHandler<InstanceType<Model>, Event>): void;
Type Parameters
Type Parameter
Model extends LucidModel
Event extends EventsList
Parameters
ParameterType
thisModel
eventEvent
handlerHooksHandler<InstanceType<Model>, Event>
Returns

void

Inherited from

LucidModel.after


all()

ts
all<T>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>[]>;

Fetch all rows

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
options?ModelAdapterOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.all


before()

Call Signature

ts
before<Model, Event>(
   this: Model,
   event: Event,
   handler: HooksHandler<ModelQueryBuilderContract<Model, InstanceType<Model>>, Event>): void;

Register a before hook

Type Parameters
Type Parameter
Model extends LucidModel
Event extends "find" | "fetch"
Parameters
ParameterType
thisModel
eventEvent
handlerHooksHandler<ModelQueryBuilderContract<Model, InstanceType<Model>>, Event>
Returns

void

Inherited from

LucidModel.before

Call Signature

ts
before<Model>(
   this: Model,
   event: "paginate",
   handler: HooksHandler<[ModelQueryBuilderContract<Model, InstanceType<Model>>, ModelQueryBuilderContract<Model, InstanceType<Model>>], "paginate">): void;
Type Parameters
Type Parameter
Model extends LucidModel
Parameters
ParameterType
thisModel
event"paginate"
handlerHooksHandler<[ModelQueryBuilderContract<Model, InstanceType<Model>>, ModelQueryBuilderContract<Model, InstanceType<Model>>], "paginate">
Returns

void

Inherited from

LucidModel.before

Call Signature

ts
before<Model, Event>(
   this: Model,
   event: Event,
   handler: HooksHandler<InstanceType<Model>, Event>): void;
Type Parameters
Type Parameter
Model extends LucidModel
Event extends EventsList
Parameters
ParameterType
thisModel
eventEvent
handlerHooksHandler<InstanceType<Model>, Event>
Returns

void

Inherited from

LucidModel.before


boot()

ts
boot(): void;

Boot model

Returns

void

Inherited from

LucidModel.boot


create()

ts
create<T>(
   this: T,
   values: Partial<ModelAttributes<InstanceType<T>>>,
options?: ModelAssignOptions): Promise<InstanceType<T>>;

Create model and return its instance back

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valuesPartial<ModelAttributes<InstanceType<T>>>
options?ModelAssignOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.create


createMany()

ts
createMany<T>(
   this: T,
   values: Partial<ModelAttributes<InstanceType<T>>>[],
options?: ModelAssignOptions): Promise<InstanceType<T>[]>;

Create many of model instances

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valuesPartial<ModelAttributes<InstanceType<T>>>[]
options?ModelAssignOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.createMany


createManyQuietly()

ts
createManyQuietly<T>(
   this: T,
   values: Partial<ModelAttributes<InstanceType<T>>>[],
options?: ModelAssignOptions): Promise<InstanceType<T>[]>;

Same as [[BaseModel.createMany]] but without invoking hooks

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valuesPartial<ModelAttributes<InstanceType<T>>>[]
options?ModelAssignOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.createManyQuietly


createQuietly()

ts
createQuietly<T>(
   this: T,
   values: Partial<ModelAttributes<InstanceType<T>>>,
options?: ModelAssignOptions): Promise<InstanceType<T>>;

Same as [[BaseModel.create]] but without invoking hooks

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valuesPartial<ModelAttributes<InstanceType<T>>>
options?ModelAssignOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.createQuietly


fetchOrCreateMany()

ts
fetchOrCreateMany<T>(
   this: T,
   predicate:
  | keyof ModelAttributes<InstanceType<T>>
  | keyof ModelAttributes<InstanceType<T>>[],
   payload: Partial<ModelAttributes<InstanceType<T>>>[],
options?: ModelAssignOptions): Promise<InstanceType<T>[]>;

Find rows or create many when missing. One db call is invoked for each create

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
predicate| keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[]
payloadPartial<ModelAttributes<InstanceType<T>>>[]
options?ModelAssignOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.fetchOrCreateMany


fetchOrNewUpMany()

ts
fetchOrNewUpMany<T>(
   this: T,
   predicate:
  | keyof ModelAttributes<InstanceType<T>>
  | keyof ModelAttributes<InstanceType<T>>[],
   payload: Partial<ModelAttributes<InstanceType<T>>>[],
options?: ModelAssignOptions): Promise<InstanceType<T>[]>;

Find rows or create in-memory instances of the missing one's.

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
predicate| keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[]
payloadPartial<ModelAttributes<InstanceType<T>>>[]
options?ModelAssignOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.fetchOrNewUpMany


find()

ts
find<T>(
   this: T,
   value: any,
   options?: ModelAdapterOptions): Promise<
  | InstanceType<T>
| null>;

Find one using the primary key

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valueany
options?ModelAdapterOptions

Returns

Promise< | InstanceType<T> | null>

Inherited from

LucidModel.find


findBy()

Call Signature

ts
findBy<T>(
   this: T,
   clause: Record<string, unknown>,
   options?: ModelAdapterOptions): Promise<
  | InstanceType<T>
| null>;

Find one using a clause

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
clauseRecord<string, unknown>
options?ModelAdapterOptions
Returns

Promise< | InstanceType<T> | null>

Inherited from

LucidModel.findBy

Call Signature

ts
findBy<T>(
   this: T,
   key: string,
   value: any,
   options?: ModelAdapterOptions): Promise<
  | InstanceType<T>
| null>;

Find one using a key-value pair

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
keystring
valueany
options?ModelAdapterOptions
Returns

Promise< | InstanceType<T> | null>

Inherited from

LucidModel.findBy


findByOrFail()

Call Signature

ts
findByOrFail<T>(
   this: T,
   clause: Record<string, unknown>,
options?: ModelAdapterOptions): Promise<InstanceType<T>>;

Find one using a clause or fail

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
clauseRecord<string, unknown>
options?ModelAdapterOptions
Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.findByOrFail

Call Signature

ts
findByOrFail<T>(
   this: T,
   key: string,
   value: any,
options?: ModelAdapterOptions): Promise<InstanceType<T>>;

Find one using a key-value pair or fail

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
keystring
valueany
options?ModelAdapterOptions
Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.findByOrFail


findMany()

ts
findMany<T>(
   this: T,
   value: any[],
options?: ModelAdapterOptions): Promise<InstanceType<T>[]>;

Find many using an array of primary keys

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valueany[]
options?ModelAdapterOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.findMany


findManyBy()

Call Signature

ts
findManyBy<T>(
   this: T,
   clause: Record<string, unknown>,
options?: ModelAdapterOptions): Promise<InstanceType<T>[]>;

Find multiple models instance using a clause

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
clauseRecord<string, unknown>
options?ModelAdapterOptions
Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.findManyBy

Call Signature

ts
findManyBy<T>(
   this: T,
   key: string,
   value: any,
options?: ModelAdapterOptions): Promise<InstanceType<T>[]>;

Find multiple models instance using a key/value pair

Type Parameters
Type Parameter
T extends LucidModel
Parameters
ParameterType
thisT
keystring
valueany
options?ModelAdapterOptions
Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.findManyBy


findOrFail()

ts
findOrFail<T>(
   this: T,
   value: any,
options?: ModelAdapterOptions): Promise<InstanceType<T>>;

Find one using the primary key or fail

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
valueany
options?ModelAdapterOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.findOrFail


first()

ts
first<T>(this: T, options?: ModelAdapterOptions): Promise<
  | InstanceType<T>
| null>;

Same as query().first()

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
options?ModelAdapterOptions

Returns

Promise< | InstanceType<T> | null>

Inherited from

LucidModel.first


firstOrCreate()

ts
firstOrCreate<T>(
   this: T,
   searchPayload: Partial<ModelAttributes<InstanceType<T>>>,
   savePayload?: Partial<ModelAttributes<InstanceType<T>>>,
options?: ModelAssignOptions): Promise<InstanceType<T>>;

Returns the first row or save it to the database

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
searchPayloadPartial<ModelAttributes<InstanceType<T>>>
savePayload?Partial<ModelAttributes<InstanceType<T>>>
options?ModelAssignOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.firstOrCreate


firstOrFail()

ts
firstOrFail<T>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>>;

Same as query().firstOrFail()

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
options?ModelAdapterOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.firstOrFail


firstOrNew()

ts
firstOrNew<T>(
   this: T,
   searchPayload: Partial<ModelAttributes<InstanceType<T>>>,
   savePayload?: Partial<ModelAttributes<InstanceType<T>>>,
options?: ModelAssignOptions): Promise<InstanceType<T>>;

Returns the first row or create a new instance of model without persisting it

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
searchPayloadPartial<ModelAttributes<InstanceType<T>>>
savePayload?Partial<ModelAttributes<InstanceType<T>>>
options?ModelAssignOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.firstOrNew


query()

ts
query<Model, Result>(this: Model, options?: ModelAdapterOptions): ModelQueryBuilderContract<Model, Result>;

Returns the query for fetching a model instance

Type Parameters

Type ParameterDefault type
Model extends LucidModel-
ResultInstanceType<Model>

Parameters

ParameterType
thisModel
options?ModelAdapterOptions

Returns

ModelQueryBuilderContract<Model, Result>

Inherited from

LucidModel.query


truncate()

ts
truncate(cascade?: boolean): Promise<void>;

Truncate model table

Parameters

ParameterType
cascade?boolean

Returns

Promise<void>

Inherited from

LucidModel.truncate


updateOrCreate()

ts
updateOrCreate<T>(
   this: T,
   searchPayload: Partial<ModelAttributes<InstanceType<T>>>,
   updatePayload: Partial<ModelAttributes<InstanceType<T>>>,
options?: ModelAssignOptions): Promise<InstanceType<T>>;

Returns the first row or save it to the database

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
searchPayloadPartial<ModelAttributes<InstanceType<T>>>
updatePayloadPartial<ModelAttributes<InstanceType<T>>>
options?ModelAssignOptions

Returns

Promise<InstanceType<T>>

Inherited from

LucidModel.updateOrCreate


updateOrCreateMany()

ts
updateOrCreateMany<T>(
   this: T,
   predicate:
  | keyof ModelAttributes<InstanceType<T>>
  | keyof ModelAttributes<InstanceType<T>>[],
   payload: Partial<ModelAttributes<InstanceType<T>>>[],
options?: ModelAssignOptions): Promise<InstanceType<T>[]>;

Update existing rows or create new one's.

Type Parameters

Type Parameter
T extends LucidModel

Parameters

ParameterType
thisT
predicate| keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[]
payloadPartial<ModelAttributes<InstanceType<T>>>[]
options?ModelAssignOptions

Returns

Promise<InstanceType<T>[]>

Inherited from

LucidModel.updateOrCreateMany


useAdapter()

ts
useAdapter(adapter: AdapterContract): void;

Define an adapter to use for interacting with the database

Parameters

ParameterType
adapterAdapterContract

Returns

void

Inherited from

LucidModel.useAdapter