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
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
new ResourcefulModel(): LucidRow;Returns
LucidRow
Inherited from
Properties
| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
$adapter | public | AdapterContract | Adapter to work as a bridge between query builder and the model | LucidModel.$adapter |
$columnsDefinitions | public | Map<string, ModelColumnOptions> | A map of defined columns | LucidModel.$columnsDefinitions |
$computedDefinitions | public | Map<string, ComputedOptions> | A map of computed properties | LucidModel.$computedDefinitions |
$hooks | public | Hooks<any> | Reference to hooks | LucidModel.$hooks |
$keys | public | { 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 versions | LucidModel.$keys |
$keys.attributesToColumns | public | ModelKeysContract | - | - |
$keys.attributesToSerialized | public | ModelKeysContract | - | - |
$keys.columnsToAttributes | public | ModelKeysContract | - | - |
$keys.columnsToSerialized | public | ModelKeysContract | - | - |
$keys.serializedToAttributes | public | ModelKeysContract | - | - |
$keys.serializedToColumns | public | ModelKeysContract | - | - |
$relationsDefinitions | public | Map<string, RelationshipsContract> | A map of defined relationships | LucidModel.$relationsDefinitions |
$resourcefulAccessControlFilters | public | { 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.create | public | ResourcefulGeneralAccessControlFilter[] | - | - |
$resourcefulAccessControlFilters.delete | public | ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[] | - | - |
$resourcefulAccessControlFilters.list | public | ResourcefulGeneralAccessControlFilter[] | - | - |
$resourcefulAccessControlFilters.read | public | ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[] | - | - |
$resourcefulAccessControlFilters.update | public | ResourcefulResourceAccessControlFilter<LucidModel, LucidRow>[] | - | - |
$resourcefulColumns | public | Map<string, ResourcefulColumnDefinition<ResourcefulPropertySchema>> | Map of column property names to their resourceful metadata definitions | - |
$resourcefulComputedAccessors | public | Map<string, ResourcefulComputedAccessorDefinition<ResourcefulPropertySchema>> | Map of computed accessor property names to their resourceful metadata definitions | - |
$resourcefulEnforcedPreloads | public | Set<string> | Set of enforced preloads for the model | - |
$resourcefulMetaDescription? | public | string | Optional description for OpenAPI schema documentation | - |
$resourcefulMetaExample? | public | string | Optional example value for OpenAPI schema documentation | - |
$resourcefulMetaExternalDocs? | public | ExternalDocumentationObject | Optional external documentation reference for OpenAPI schema | - |
$resourcefulName | public | string | The display name for this model used in API documentation and error messages | - |
$resourcefulOnACLError | public | "bubble" | "pass" | "fail" | Error handling strategy when ACL evaluation fails | - |
$resourcefulPayloadValidationSchemaBuilders | public | { create: ResourcefulPayloadValidatorGetter[]; update: ResourcefulPayloadValidatorGetter[]; } | Payload validation schema builder functions for create and update operations | - |
$resourcefulPayloadValidationSchemaBuilders.create | public | ResourcefulPayloadValidatorGetter[] | - | - |
$resourcefulPayloadValidationSchemaBuilders.update | public | ResourcefulPayloadValidatorGetter[] | - | - |
$resourcefulQueryScopeCallbacks | public | { access: ResourcefulQueryScopeCallback[]; list: ResourcefulQueryScopeCallback[]; } | Query scope callback functions for constraining database queries | - |
$resourcefulQueryScopeCallbacks.access | public | ResourcefulQueryScopeCallback[] | - | - |
$resourcefulQueryScopeCallbacks.list | public | ResourcefulQueryScopeCallback[] | - | - |
$resourcefulRelationships | public | Map<string, ResourcefulRelationshipDefinition<LucidModel>> | Map of relationship property names to their resourceful metadata definitions | - |
$resourcefulTitleColumn? | public | string | The column used as the title of the model instance when displayed in a list | - |
booted | readonly | boolean | Whether or not model has been booted. After this model configurations are ignored | LucidModel.booted |
connection? | public | string | Custom database connection to use | LucidModel.connection |
namingStrategy | public | NamingStrategyContract | Naming strategy to use | LucidModel.namingStrategy |
primaryKey | public | string | The primary key for finding unique referencing to a model | LucidModel.primaryKey |
selfAssignPrimaryKey | public | boolean | Self assign the primary instead of relying on the database to return it back | LucidModel.selfAssignPrimaryKey |
table | public | string | Database table to use | LucidModel.table |
transaction | public | TransactionFn | Returns transaction client from the model. It is same as calling "db.transaction" | LucidModel.transaction |
Methods
$addColumn()
$addColumn(name: string, options: Partial<ColumnOptions>): ColumnOptions;Managing columns
Parameters
| Parameter | Type |
|---|---|
name | string |
options | Partial<ColumnOptions> |
Returns
ColumnOptions
Inherited from
$addComputed()
$addComputed(name: string, options: Partial<ComputedOptions>): ComputedOptions;Managing computed columns
Parameters
| Parameter | Type |
|---|---|
name | string |
options | Partial<ComputedOptions> |
Returns
Inherited from
$addRelation()
$addRelation(
name: string,
type: "hasOne" | "hasMany" | "belongsTo" | "manyToMany" | "hasManyThrough",
relatedModel: () => LucidModel,
options: ModelRelationOptions): void;Managing relationships
Parameters
| Parameter | Type |
|---|---|
name | string |
type | "hasOne" | "hasMany" | "belongsTo" | "manyToMany" | "hasManyThrough" |
relatedModel | () => LucidModel |
options | ModelRelationOptions |
Returns
void
Inherited from
$asOpenApiSchemaObject()
$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
| Parameter | Type | Description |
|---|---|---|
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application 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 schemastitle: The model's resourceful namedescription: Optional model description from metadataproperties: Object containing schema definitions for accessible fieldsrequired: Array of required field names (non-nullable fields)externalDocs: Optional external documentation referenceexample: Optional example value for the schema
Example
// 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()
$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
| Parameter | Type |
|---|---|
this | T |
result? | ModelObject |
sideloadAttributes? | ModelObject |
options? | ModelAdapterOptions |
Returns
| InstanceType<T> | null
Inherited from
LucidModel.$createFromAdapterResult
$createFromHttpContext()
$createFromHttpContext(ctx: HttpContext): Promise<LucidRow>;Creates a new model instance from HTTP context data.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | HttpContext | The HTTP context containing the request data |
Returns
Promise<LucidRow>
A Promise that resolves to a new model instance
$createMultipleFromAdapterResult()
$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
| Parameter | Type |
|---|---|
this | T |
results | ModelObject[] |
sideloadAttributes? | ModelObject |
options? | ModelAdapterOptions |
Returns
InstanceType<T>[]
Inherited from
LucidModel.$createMultipleFromAdapterResult
$defineProperty()
$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
| Parameter | Type |
|---|---|
this | Model |
propertyName | Prop |
defaultValue | Model[Prop] |
strategy | "inherit" | "define" | (value: Model[Prop]) => Model[Prop] |
Returns
void
Inherited from
$getAsResourcefulForContext()
$getAsResourcefulForContext(ctx: HttpContext, app: ApplicationService): Promise<ResourcefulModelMetaSchema>;Parameters
| Parameter | Type |
|---|---|
ctx | HttpContext |
app | ApplicationService |
Returns
Promise<ResourcefulModelMetaSchema>
$getColumn()
$getColumn(name: string):
| ModelColumnOptions
| undefined;Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
| ModelColumnOptions | undefined
Inherited from
$getComputed()
$getComputed(name: string): ComputedOptions | undefined;Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
ComputedOptions | undefined
Inherited from
$getRelation()
Call Signature
$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
| Parameter | Type |
|---|---|
this | Model |
name | Name |
Returns
NonNullable<InstanceType<Model>[Name]> extends ModelRelations<LucidModel, LucidModel> ? NonNullable<NonNullable<InstanceType<Model>[Name]>>["client"]["relation"] : RelationshipsContract
Inherited from
Call Signature
$getRelation<Model>(this: Model, name: string): RelationshipsContract;Type Parameters
| Type Parameter |
|---|
Model extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | Model |
name | string |
Returns
RelationshipsContract
Inherited from
$getResourcefulWriteValidationSchema()
$getResourcefulWriteValidationSchema(
ctx: HttpContext,
app: ApplicationService,
forUpdate?: boolean): Promise<{
schema: ResourcefulModelOpenApiSchema;
validator: ObjectSchema<any>;
}>;Parameters
| Parameter | Type |
|---|---|
ctx | HttpContext |
app | ApplicationService |
forUpdate? | boolean |
Returns
Promise<{ schema: ResourcefulModelOpenApiSchema; validator: ObjectSchema<any>; }>
$hasColumn()
$hasColumn(name: string): boolean;Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
boolean
Inherited from
$hasComputed()
$hasComputed(name: string): boolean;Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
boolean
Inherited from
$hasRelation()
$hasRelation(name: string): boolean;Find if a relationship exists
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
boolean
Inherited from
$offResourcefulEvent()
$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 Parameter | Description |
|---|---|
K | The event key type from the resourceful event map |
Parameters
| Parameter | Type | Description |
|---|---|---|
event | Key<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
// Remove specific listener
User.$offResourcefulEvent("acl:error", myErrorHandler);
// Remove all listeners for an event
User.$offResourcefulEvent("acl:error");$onceResourcefulEvent()
$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 Parameter | Description |
|---|---|
K | The event key type from the resourceful event map |
Parameters
| Parameter | Type | Description |
|---|---|---|
event | Key<K, ResourcefulMixinEventMap<Model, ModelInstance>> | The name of the event to listen for |
listener | Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>> | Function to call when the event is emitted |
Returns
this
The model class for method chaining
Example
User.$onceResourcefulEvent(
"validation:scope:error",
(error, ctx, app, key, datatype) => {
console.warn("Validation scope error (one-time):", error);
},
);$onResourcefulBulkUpdate()
$onResourcefulBulkUpdate(
filter: string | null | undefined,
payload: any,
ctx: HttpContext,
app: ApplicationService,
hooks?: Partial<ResourcefulHooks>): Promise<
| Error
| {
[key: string]: any;
}>;Parameters
| Parameter | Type |
|---|---|
filter | string | null | undefined |
payload | any |
ctx | HttpContext |
app | ApplicationService |
hooks? | Partial<ResourcefulHooks> |
Returns
Promise< | Error | { [key: string]: any; }>
$onResourcefulBulkUpdateByUid()
$onResourcefulBulkUpdateByUid(
uids: (string | number)[],
payload: any,
ctx: HttpContext,
app: ApplicationService,
hooks?: Partial<ResourcefulHooks>): Promise<{
[key: string]: any;
}>;Parameters
| Parameter | Type |
|---|---|
uids | (string | number)[] |
payload | any |
ctx | HttpContext |
app | ApplicationService |
hooks? | Partial<ResourcefulHooks> |
Returns
Promise<{ [key: string]: any; }>
$onResourcefulCreate()
$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
| Parameter | Type | Description |
|---|---|---|
payload | any | The data object containing field values for the new record |
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application service instance for accessing app-level services |
hooks? | ResourcefulValidationHooks | Optional 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
// 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()
$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
| Parameter | Type | Description |
|---|---|---|
uid | number | The unique identifier of the record to delete |
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application service instance for accessing app-level services |
hooks? | ResourcefulScopeHooks | Optional 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
// 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()
$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 Parameter | Description |
|---|---|
K | The event key type from the resourceful event map |
Parameters
| Parameter | Type | Description |
|---|---|---|
event | Key<K, ResourcefulMixinEventMap<Model, ModelInstance>> | The name of the event to listen for ('acl:error', 'validation:scope:error') |
listener | Listener<K, ResourcefulMixinEventMap<Model, ModelInstance>> | Function to call when the event is emitted |
Returns
this
The model class for method chaining
Example
User.$onResourcefulEvent("acl:error", (error, ctx, app, instance) => {
console.error("ACL error occurred:", error);
});$onResourcefulIndex()
$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
| Parameter | Type | Description |
|---|---|---|
filter | string | null | undefined | Lucene-style query string for filtering records (e.g., "name:john AND email:*.com"). If null or undefined, defaults to empty string (no filtering). |
page | number | The page number for pagination (must be ≥ 1). Used with perPage to calculate offset. |
perPage | number | Number of records per page (must be ≥ 1 and ≤ 100 by default). |
fields | string | string[] | null | undefined | Array 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 | undefined | Array of sort specifications as [fieldName, direction] tuples. Field names must be marked as sortable in their column definitions. |
ctx | HttpContext | HTTP context containing request information, authentication, and other request-scoped data. |
app | ApplicationService | Application service instance providing access to application-level services and configuration. |
hooks? | ResourcefulScopeHooks | Optional array of query scope callbacks to apply additional filtering constraints. |
aggregations? | ResourcefulIndexAggregateOptions | Optional 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 fieldstotal: 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 methodcountQuery: SQL query string used for counting total recordsrecordsQuery: 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
// 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()
$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
| Parameter | Type | Description |
|---|---|---|
uid | number | The unique identifier of the record to retrieve |
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application service instance for accessing app-level services |
hooks? | ResourcefulScopeHooks | Optional 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
// 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()
$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
| Parameter | Type | Description |
|---|---|---|
uid | any | The unique identifier of the parent record |
relationshipKey | string | The name of the relationship property to load |
filter | string | null | undefined | Lucene-style query string for filtering related records |
page | number | The page number for pagination (must be ≥ 1) |
perPage | number | Number of records per page (must be ≥ 1 and ≤ 100) |
fields | string | string[] | null | undefined | Array of field names to include in the response from the related model |
sort | [string, "asc" | "desc"][] | null | undefined | Array of sort criteria as [field, direction] tuples |
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application service instance for accessing app-level services |
hooks? | ResourcefulScopeHooks | Optional 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
// 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()
$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
| Parameter | Type | Description |
|---|---|---|
uid | number | The unique identifier of the record to update |
payload | any | The data object containing field values to update |
ctx | HttpContext | HTTP context containing request information and authentication |
app | ApplicationService | Application 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
// 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
after<Model>(
this: Model,
event: "fetch",
handler: HooksHandler<InstanceType<Model>[], "fetch">): void;Register an after hook
Type Parameters
| Type Parameter |
|---|
Model extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | Model |
event | "fetch" |
handler | HooksHandler<InstanceType<Model>[], "fetch"> |
Returns
void
Inherited from
Call Signature
after<Model>(
this: Model,
event: "paginate",
handler: HooksHandler<ModelPaginatorContract<InstanceType<Model>>, "paginate">): void;Type Parameters
| Type Parameter |
|---|
Model extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | Model |
event | "paginate" |
handler | HooksHandler<ModelPaginatorContract<InstanceType<Model>>, "paginate"> |
Returns
void
Inherited from
Call Signature
after<Model, Event>(
this: Model,
event: Event,
handler: HooksHandler<InstanceType<Model>, Event>): void;Type Parameters
| Type Parameter |
|---|
Model extends LucidModel |
Event extends EventsList |
Parameters
| Parameter | Type |
|---|---|
this | Model |
event | Event |
handler | HooksHandler<InstanceType<Model>, Event> |
Returns
void
Inherited from
all()
all<T>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>[]>;Fetch all rows
Type Parameters
| Type Parameter |
|---|
T extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | T |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
before()
Call Signature
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
| Parameter | Type |
|---|---|
this | Model |
event | Event |
handler | HooksHandler<ModelQueryBuilderContract<Model, InstanceType<Model>>, Event> |
Returns
void
Inherited from
Call Signature
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
| Parameter | Type |
|---|---|
this | Model |
event | "paginate" |
handler | HooksHandler<[ModelQueryBuilderContract<Model, InstanceType<Model>>, ModelQueryBuilderContract<Model, InstanceType<Model>>], "paginate"> |
Returns
void
Inherited from
Call Signature
before<Model, Event>(
this: Model,
event: Event,
handler: HooksHandler<InstanceType<Model>, Event>): void;Type Parameters
| Type Parameter |
|---|
Model extends LucidModel |
Event extends EventsList |
Parameters
| Parameter | Type |
|---|---|
this | Model |
event | Event |
handler | HooksHandler<InstanceType<Model>, Event> |
Returns
void
Inherited from
boot()
boot(): void;Boot model
Returns
void
Inherited from
create()
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
| Parameter | Type |
|---|---|
this | T |
values | Partial<ModelAttributes<InstanceType<T>>> |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>>
Inherited from
createMany()
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
| Parameter | Type |
|---|---|
this | T |
values | Partial<ModelAttributes<InstanceType<T>>>[] |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
createManyQuietly()
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
| Parameter | Type |
|---|---|
this | T |
values | Partial<ModelAttributes<InstanceType<T>>>[] |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
createQuietly()
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
| Parameter | Type |
|---|---|
this | T |
values | Partial<ModelAttributes<InstanceType<T>>> |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>>
Inherited from
fetchOrCreateMany()
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
| Parameter | Type |
|---|---|
this | T |
predicate | | keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[] |
payload | Partial<ModelAttributes<InstanceType<T>>>[] |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
fetchOrNewUpMany()
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
| Parameter | Type |
|---|---|
this | T |
predicate | | keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[] |
payload | Partial<ModelAttributes<InstanceType<T>>>[] |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
find()
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
| Parameter | Type |
|---|---|
this | T |
value | any |
options? | ModelAdapterOptions |
Returns
Promise< | InstanceType<T> | null>
Inherited from
findBy()
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
clause | Record<string, unknown> |
options? | ModelAdapterOptions |
Returns
Promise< | InstanceType<T> | null>
Inherited from
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
key | string |
value | any |
options? | ModelAdapterOptions |
Returns
Promise< | InstanceType<T> | null>
Inherited from
findByOrFail()
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
clause | Record<string, unknown> |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>>
Inherited from
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
key | string |
value | any |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>>
Inherited from
findMany()
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
| Parameter | Type |
|---|---|
this | T |
value | any[] |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
findManyBy()
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
clause | Record<string, unknown> |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
Call Signature
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
| Parameter | Type |
|---|---|
this | T |
key | string |
value | any |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
findOrFail()
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
| Parameter | Type |
|---|---|
this | T |
value | any |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>>
Inherited from
first()
first<T>(this: T, options?: ModelAdapterOptions): Promise<
| InstanceType<T>
| null>;Same as query().first()
Type Parameters
| Type Parameter |
|---|
T extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | T |
options? | ModelAdapterOptions |
Returns
Promise< | InstanceType<T> | null>
Inherited from
firstOrCreate()
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
| Parameter | Type |
|---|---|
this | T |
searchPayload | Partial<ModelAttributes<InstanceType<T>>> |
savePayload? | Partial<ModelAttributes<InstanceType<T>>> |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>>
Inherited from
firstOrFail()
firstOrFail<T>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>>;Same as query().firstOrFail()
Type Parameters
| Type Parameter |
|---|
T extends LucidModel |
Parameters
| Parameter | Type |
|---|---|
this | T |
options? | ModelAdapterOptions |
Returns
Promise<InstanceType<T>>
Inherited from
firstOrNew()
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
| Parameter | Type |
|---|---|
this | T |
searchPayload | Partial<ModelAttributes<InstanceType<T>>> |
savePayload? | Partial<ModelAttributes<InstanceType<T>>> |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>>
Inherited from
query()
query<Model, Result>(this: Model, options?: ModelAdapterOptions): ModelQueryBuilderContract<Model, Result>;Returns the query for fetching a model instance
Type Parameters
| Type Parameter | Default type |
|---|---|
Model extends LucidModel | - |
Result | InstanceType<Model> |
Parameters
| Parameter | Type |
|---|---|
this | Model |
options? | ModelAdapterOptions |
Returns
ModelQueryBuilderContract<Model, Result>
Inherited from
truncate()
truncate(cascade?: boolean): Promise<void>;Truncate model table
Parameters
| Parameter | Type |
|---|---|
cascade? | boolean |
Returns
Promise<void>
Inherited from
updateOrCreate()
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
| Parameter | Type |
|---|---|
this | T |
searchPayload | Partial<ModelAttributes<InstanceType<T>>> |
updatePayload | Partial<ModelAttributes<InstanceType<T>>> |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>>
Inherited from
updateOrCreateMany()
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
| Parameter | Type |
|---|---|
this | T |
predicate | | keyof ModelAttributes<InstanceType<T>> | keyof ModelAttributes<InstanceType<T>>[] |
payload | Partial<ModelAttributes<InstanceType<T>>>[] |
options? | ModelAssignOptions |
Returns
Promise<InstanceType<T>[]>
Inherited from
useAdapter()
useAdapter(adapter: AdapterContract): void;Define an adapter to use for interacting with the database
Parameters
| Parameter | Type |
|---|---|
adapter | AdapterContract |
Returns
void