### Installation and Setup Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Instructions for installing the package and registering the service provider. ```APIDOC ## Install and Setup ```bash # Command line npm install adonis-lucid-soft-deletes node ace configure adonis-lucid-soft-deletes ``` ```typescript // Manual provider registration in adonisrc.ts providers: [ () => import('adonis-lucid-soft-deletes/provider'), ] ``` ``` -------------------------------- ### Install and Setup Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Install the package via npm and register the service provider. Manual registration can be done in `adonisrc.ts`. ```typescript // Command line npm install adonis-lucid-soft-deletes node ace configure adonis-lucid-soft-deletes // Manual provider registration in adonisrc.ts providers: [ () => import('adonis-lucid-soft-deletes/provider'), ] ``` -------------------------------- ### Install and Configure via AdonisJS CLI Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Install the package and then run the configure command to automatically update configuration files. ```bash # After installing the package npm install adonis-lucid-soft-deletes # Run the configure command node ace configure adonis-lucid-soft-deletes ``` -------------------------------- ### Install and Configure Package Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/index.md Install the package using npm and then configure it within your AdonisJS application using the ace command. ```bash npm install adonis-lucid-soft-deletes node ace configure adonis-lucid-soft-deletes ``` -------------------------------- ### configure() Setup Function Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md A setup function to configure the LucidSoftDeletes package by updating the adonisrc.ts file to register the service provider. ```APIDOC ## configure() ### Description Updates `adonisrc.ts` to register the `LucidSoftDeletesProvider`, enabling soft delete functionality for Lucid models. ### Behavior Modifies the `adonisrc.ts` configuration file to include the soft delete provider. ``` -------------------------------- ### Instance Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Examples of using instance methods on a model to perform soft delete, restore, and force delete operations. ```APIDOC ## Instance Methods ```typescript const user = await User.find(1) // Soft delete await user.delete() // Check if deleted if (user.trashed) { ... } // Restore await user.restore() // Permanently delete await user.forceDelete() ``` ``` -------------------------------- ### Configure Adonis Lucid Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/README.md After installation, run the configure command to set up the addon. ```bash node ace configure adonis-lucid-soft-deletes ``` -------------------------------- ### Install Adonis Lucid Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/README.md Install the package using npm, yarn, or pnpm. ```bash # npm npm i adonis-lucid-soft-deletes # yarn yarn add adonis-lucid-soft-deletes # pnpm pnpm add adonis-lucid-soft-deletes ``` -------------------------------- ### Install AdonisJS Lucid Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Install the `adonis-lucid-soft-deletes` package using npm. This command should be run in your project's root directory. ```bash npm install adonis-lucid-soft-deletes ``` -------------------------------- ### Query Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Examples of using query builder methods to retrieve records, including soft-deleted ones. ```APIDOC ## Query Methods ```typescript // Default: excludes soft-deleted await User.query().exec() // Include soft-deleted await User.query().withTrashed().exec() // Only soft-deleted await User.query().onlyTrashed().exec() // Restore records await User.query().withTrashed().restore() ``` ``` -------------------------------- ### Create Table with Soft Delete Column Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Example migration for creating a new table with a `deleted_at` column to support soft deletes. The column must be nullable. ```typescript import { BaseSchema } from '@adonisjs/lucid/schema' export default class CreateUsersTable extends BaseSchema { protected tableName = 'users' async up() { this.schema.createTable(this.tableName, (table) => { table.increments('id') table.string('email').unique() table.string('username').unique() table.string('password') table.timestamps() table.timestamp('deleted_at').nullable() // Add this }) } async down() { this.schema.dropTable(this.tableName) } } ``` -------------------------------- ### Multi-Tenant Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Demonstrates how soft deletes work in a multi-tenant setup, where each tenant has its own soft-deleted records. Use `.withTrashed()` to include soft-deleted records in the query. ```typescript class Post extends compose(BaseModel, SoftDeletes) { @column() declare tenantId: number @column.dateTime() declare deletedAt: DateTime | null } // Get active posts for a tenant const posts = await Post.query() .where('tenantId', userId) .exec() // Automatically excludes soft-deleted // Get all posts including soft-deleted const allPosts = await Post.query() .withTrashed() .where('tenantId', userId) .exec() ``` -------------------------------- ### Example Model Usage with Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Define a Lucid model that includes the SoftDeletes mixin. Ensure the `deletedAt` column is of type `DateTime` and nullable. ```typescript import { compose } from '@adonisjs/core/helpers' import { BaseModel, column } from '@adonisjs/lucid/orm' import { SoftDeletes } from 'adonis-lucid-soft-deletes' import { DateTime } from 'luxon' export default class User extends compose(BaseModel, SoftDeletes) { @column({ isPrimary: true }) declare id: number @column() declare email: string @column.dateTime() declare deletedAt: DateTime | null } ``` -------------------------------- ### Initialize Soft Deletes Provider for Testing Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/provider.md Extend the ModelQueryBuilder with soft delete functionality during test setup. This ensures that soft delete methods are available for use in your tests. ```typescript import { extendModelQueryBuilder } from 'adonis-lucid-soft-deletes/bindings' import { ModelQueryBuilder } from '@adonisjs/lucid/orm' // In test setup extendModelQueryBuilder(ModelQueryBuilder) // Now tests can use soft delete methods const users = await User.query().withTrashed().exec() ``` -------------------------------- ### Add Soft Delete Column to Existing Table Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Example migration for altering an existing table to add a `deleted_at` column. Includes logic to drop the column in the `down` method. ```typescript import { BaseSchema } from '@adonisjs/lucid/schema' export default class AddDeletedAtToUsersTable extends BaseSchema { protected tableName = 'users' async up() { this.schema.alterTable(this.tableName, (table) => { table.timestamp('deleted_at').nullable() }) } async down() { this.schema.alterTable(this.tableName, (table) => { table.dropColumn('deleted_at') }) } } ``` -------------------------------- ### Extending Model Query Builder for Tests Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md In your test files, manually extend the ModelQueryBuilder to enable soft delete functionality during testing. This setup is required before running tests that involve soft deleted models. ```typescript import { test } from '@japa/runner' import { ModelQueryBuilder } from '@adonisjs/lucid/orm' import { extendModelQueryBuilder } from 'adonis-lucid-soft-deletes/bindings' test.group('Soft Deletes Tests', (group) => { group.setup(() => { // Extend query builder for tests extendModelQueryBuilder(ModelQueryBuilder) }) test('soft delete works', async ({ assert }) => { const user = await User.create({ email: 'test@example.com' }) await user.delete() assert.isTrue(user.trashed) }) }) ``` -------------------------------- ### Getting Full Error Details in TypeScript Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Use a try-catch block to capture and log detailed information about errors thrown during soft delete operations. This includes error code, message, status, stack trace, and the original underlying error. ```typescript try { await user.restore() } catch (error) { console.error({ code: error.code, message: error.message, status: error.status, stack: error.stack, originalError: error.cause, }) } ``` -------------------------------- ### Run Configure Command (Idempotent) Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Execute the `ace configure` command to set up the package. Running this command multiple times is safe due to idempotency. ```bash node ace configure adonis-lucid-soft-deletes # First run - adds provider node ace configure adonis-lucid-soft-deletes # Second run - no-op or updates existing ``` -------------------------------- ### Running Type Checking Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md After registering the provider, execute the type checking command to ensure all types are correctly configured. This helps catch potential issues early in the development process. ```bash npm run typecheck # or npx tsc --noEmit ``` -------------------------------- ### Dynamic Module Import Pattern Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/provider.md Demonstrates the pattern for dynamically importing modules to avoid circular dependencies and ensure Lucid is initialized. ```typescript const { ModelQueryBuilder } = await this.app.import('@adonisjs/lucid/orm') ``` -------------------------------- ### Direct Import Configuration (Advanced) Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md For advanced scenarios, you can directly import and execute the configure function. This is normally handled by the CLI. ```typescript import { configure } from 'adonis-lucid-soft-deletes' import Configure from '@adonisjs/core/commands/configure' // Only for advanced scenarios - normally handled by CLI await configure(new Configure(app)) ``` -------------------------------- ### Instance Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Details the instance methods available on models using SoftDeletes, and their coverage. ```APIDOC ## Instance Methods Details the instance methods available on models using SoftDeletes, and their coverage. | Method | |---| | `delete()` | | `restore()` | | `forceDelete()` | ``` -------------------------------- ### Import SoftDeletes and Configure Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/index.md Import the SoftDeletes mixin and the configure function from the main entry point of the package. ```typescript import { SoftDeletes, configure } from 'adonis-lucid-soft-deletes' ``` -------------------------------- ### Configuring SQLite Database for Tests Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Utilize an in-memory SQLite database for fast test execution. This configuration snippet shows how to set up a new Database instance with SQLite connection details. ```typescript const db = new Database({ connection: 'sqlite', connections: { sqlite: { client: 'sqlite3', connection: { filename: ':memory:', }, }, }, }) ``` -------------------------------- ### ExcludeSoftDeletesMethods Usage Example Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/types.md Illustrates how ExcludeSoftDeletesMethods conditionally includes or excludes soft delete methods based on whether a model extends ModelWithSoftDeletes. This ensures type safety by only applying relevant methods. ```typescript // If User extends ModelWithSoftDeletes: type UserMethods = ExcludeSoftDeletesMethods, User> // Result: includes withTrashed, onlyTrashed, restore // If Post does not extend ModelWithSoftDeletes: type PostMethods = ExcludeSoftDeletesMethods, Post> // Result: all methods become 'never', effectively excluding them ``` -------------------------------- ### Query Builder Type Narrowing with SoftDeletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/types.md Query builder types automatically narrow based on the model's capability to handle soft deletes. This example shows a model with SoftDeletes having access to `withTrashed()`. ```typescript // User has SoftDeletes, so these methods exist: await User.query().withTrashed().exec() ``` -------------------------------- ### Static Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Lists the static methods available in the SoftDeletes module, along with their coverage status. ```APIDOC ## Static Methods Lists the static methods available in the SoftDeletes module, along with their coverage status. | Method | |---| | `withTrashed()` | | `onlyTrashed()` | | `disableIgnore()` | | `ignoreDeleted()` | | `ignoreDeletedPaginate()` | ``` -------------------------------- ### Composite Index Strategy Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Illustrates creating a composite index on `deleted_at` and another column (e.g., `status`) for tables frequently filtered by multiple criteria. ```typescript table.timestamp('deleted_at').nullable() table.string('status') table.index(['deleted_at', 'status']) ``` -------------------------------- ### Chaining Query Builder Methods with Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Demonstrates how to chain various Lucid query builder methods, including soft delete specific ones like `withTrashed()`, with standard query conditions and ordering. ```typescript const results = await User.query() .withTrashed() .where('created_at', '>', startDate) .where('is_active', true) .orderBy('deleted_at', 'desc') .limit(10) .exec() ``` -------------------------------- ### Instance Methods: restore() Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Restores a soft-deleted model instance by setting `deleted_at` to `null` and persisting the change. If the model is not soft deleted, it returns immediately. Throws an exception if the model was force deleted. ```APIDOC ## Instance Methods: restore() ### Description Restores a soft-deleted model instance by setting `deleted_at` to `null` and persisting the change. If the model is not soft deleted, it returns immediately. Throws an exception if the model was force deleted. ### Signature ```typescript async restore(): Promise ``` ### Parameters None ### Returns The restored model instance. Type: `Promise` ### Behavior If the model is not soft deleted (already has `deleted_at` as null), returns immediately without modification. If the model was force deleted, throws an exception. ### Example ```typescript const user = await User.withTrashed().find(1) if (user.trashed) { await user.restore() } // Or use query builder restore await User.withTrashed().where('id', 1).restore() ``` ``` -------------------------------- ### Properties and Getters Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Lists the properties and getters related to soft deletes available on models, and their coverage. ```APIDOC ## Properties & Getters Lists the properties and getters related to soft deletes available on models, and their coverage. | Property | |---| | `deletedAt` | | `$forceDelete` | | `trashed` | ``` -------------------------------- ### Recommended Soft Delete Column Constraints Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Configuration for a `deleted_at` column that is nullable, has no default value, and is indexed for optimal query performance. ```typescript // Recommended configuration: table.timestamp('deleted_at').nullable().index() ``` -------------------------------- ### Bulk Restore with Query Builder Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Provides a safer approach for bulk operations by using the query builder to restore only records that still exist in the database, filtering by a date range. ```typescript // Safer approach - restore only records in database await User.query() .withTrashed() .where('deleted_at', '>', DateTime.local().minus({ days: 7 })) .restore() ``` -------------------------------- ### Check User Existence and Deletion Status Before Restore Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Before attempting to restore a user, verify if the user exists and if they are currently soft-deleted. This prevents unnecessary operations and handles cases where a user might have been permanently deleted. ```typescript async restoreUserIfPossible(userId: number) { const user = await User.withTrashed().find(userId) if (!user) { throw new Error('User not found') } if (!user.trashed) { return user // Already not deleted } try { await user.restore() return user } catch (error) { if (error.code === 'E_MODEL_FORCE_DELETED') { // User was force deleted, cannot restore throw new Error('User was permanently deleted and cannot be restored') } throw error } } ``` -------------------------------- ### Import extendModelQueryBuilder Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Import the function to extend the ModelQueryBuilder. This is usually handled by the service provider. ```typescript import { extendModelQueryBuilder } from 'adonis-lucid-soft-deletes/bindings' ``` -------------------------------- ### Chaining Soft Delete Queries Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Demonstrates chaining `withTrashed()` with standard Lucid query methods to retrieve users, including those that have been soft-deleted. Ensure the User model extends `SoftDeletes`. ```typescript const results = await User.query() .withTrashed() .where('email', 'like', '%@example.com') .where('created_at', '>', date) .orderBy('deleted_at', 'desc') .limit(10) .exec() ``` -------------------------------- ### Import Soft Deletes Provider Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Import the configure function from the adonis-lucid-soft-deletes package. ```typescript import { configure } from 'adonis-lucid-soft-deletes' ``` -------------------------------- ### Basic Soft Delete Query Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Demonstrates how soft delete filtering automatically adds a WHERE clause to exclude deleted records. Indexing the `deleted_at` column is recommended for performance. ```typescript const users = await User.query().exec() ``` -------------------------------- ### Use Query Builder for Safer Batch Restores Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Employing the query builder's `restore` method is safer for batch operations as it inherently avoids the `E_MODEL_FORCE_DELETED` error because force-deleted records are not included in the query. ```typescript async restoreUsersByDate(daysAgo: number) { // This won't throw E_MODEL_FORCE_DELETED // because force-deleted records don't exist const threshold = DateTime.local().minus({ days: daysAgo }) await User.query() .withTrashed() .where('deleted_at', '>', threshold) .restore() ``` -------------------------------- ### Provider Module Path Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md The package registers its provider using this exact path, which resolves to the built provider file. ```typescript 'adonis-lucid-soft-deletes/provider' ``` -------------------------------- ### Import SoftDeletes Mixin Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Import the SoftDeletes mixin to apply it to your Lucid models. ```typescript import { SoftDeletes } from 'adonis-lucid-soft-deletes' ``` -------------------------------- ### Restore Instance Method Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md The `restore()` instance method un-deletes a soft-deleted model instance, making it available for querying again. It returns the instance itself. ```typescript async restore(): Promise ``` -------------------------------- ### ModelQueryBuilderContract for Models With SoftDeletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/types.md Illustrates the `ModelQueryBuilderContract` interface for models that support soft deletes. It includes methods like `withTrashed`, `onlyTrashed`, and `restore`. ```typescript interface ModelQueryBuilderContract { // ... standard Lucid methods withTrashed(): ModelQueryBuilderContract onlyTrashed(): ModelQueryBuilderContract restore(): Promise } ``` -------------------------------- ### restore() Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Restore all soft-deleted records matched by the query. This method sets the `deleted_at` column to `null` for matching records. ```APIDOC ## restore() ### Description Restore all soft-deleted records matched by the query. Sets the `deleted_at` column to `null` for matching records. ### Method Macro (Implicitly POST/PUT-like behavior for updating) ### Endpoint N/A (Query Builder Method) ### Parameters None ### Request Example ```typescript // Restore all soft-deleted users await User.query().withTrashed().restore() // Restore soft-deleted users from a specific time await User.query() .withTrashed() .where('deleted_at', '>', DateTime.local().minus({ days: 1 })) .restore() // Restore soft-deleted users with a specific condition await User.query() .onlyTrashed() .where('is_admin', false) .restore() ``` ### Response #### Success Response (200) - **void** - Promise that resolves when the update is complete. #### Response Example (No content, resolves promise) ``` -------------------------------- ### Restore Soft-Deleted Records with restore() Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Use `restore()` to restore soft-deleted records matched by the query. This method sets the `deleted_at` column to `null` for matching records. It can be used with `withTrashed()`, `onlyTrashed()`, and other query conditions. ```typescript // Restore all soft-deleted users await User.query().withTrashed().restore() // Restore soft-deleted users from a specific time await User.query() .withTrashed() .where('deleted_at', '>', DateTime.local().minus({ days: 1 })) .restore() // Restore soft-deleted users with a specific condition await User.query() .onlyTrashed() .where('is_admin', false) .restore() ``` -------------------------------- ### Indexing Deleted At Column Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Shows how to add an index to the `deleted_at` column in the database schema for improved query performance. ```typescript table.timestamp('deleted_at').nullable().index() ``` -------------------------------- ### Query Usage with Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Demonstrates common query operations with soft-deleted records. By default, `User.all()` filters out soft-deleted records. Use `withTrashed()` to include them, `onlyTrashed()` to select only soft-deleted records, and `restore()` to un-delete records. ```typescript // Automatically filters soft-deleted records const users = await User.all() // Include soft-deleted records const withTrashed = await User.withTrashed().exec() // Only soft-deleted records const onlyTrashed = await User.onlyTrashed().exec() // Restore soft-deleted records await User.query().withTrashed().where('id', 1).restore() ``` -------------------------------- ### Querying Soft-Deleted Records Directly Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Illustrates how to query models directly to include or filter soft-deleted records using `withTrashed()` and `onlyTrashed()`. The default behavior of `query().exec()` is to filter out soft-deleted records. ```typescript // Default: filters soft-deleted records const active = await User.query().exec() // Include soft-deleted records const all = await User.withTrashed().exec() // Only soft-deleted records const trash = await User.onlyTrashed().exec() ``` -------------------------------- ### Safely Restoring Soft-Deleted Models Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Shows how to safely restore a model by first checking if it was soft-deleted and not force-deleted, using User.withTrashed() and checking the $isDeleted flag. ```typescript const user = await User.withTrashed().find(1) // Check if the user was soft deleted (not force deleted) if (user.trashed && !user.$isDeleted) { await user.restore() // ✓ Safe } // Or check the deletion method before restoring: const user2 = await User.find(1) if (user2 && !user2.$isDeleted) { await user2.restore() // ✓ Safe, user still in database } else { console.log('User cannot be restored') // User was force deleted } ``` -------------------------------- ### Import LucidSoftDeletesProvider Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/provider.md Import the LucidSoftDeletesProvider to integrate soft delete functionality into your AdonisJS application. ```typescript import LucidSoftDeletesProvider from 'adonis-lucid-soft-deletes/provider' ``` -------------------------------- ### Query Builder Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Outlines the methods added to the Lucid Query Builder for soft delete functionality, and their coverage. ```APIDOC ## Query Builder Methods Outlines the methods added to the Lucid Query Builder for soft delete functionality, and their coverage. | Method | |---| | `withTrashed()` | | `onlyTrashed()` | | `restore()` | ``` -------------------------------- ### Adonisrc.ts Before Configure Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Shows the adonisrc.ts configuration before the soft delete provider is registered. ```typescript import { defineConfig } from '@adonisjs/core/app' export const appConfig = defineConfig({ // ... other config providers: [ () => import('@adonisjs/core/providers/app_provider'), () => import('@adonisjs/lucid/providers/lucid_provider'), // SoftDeletes provider not yet registered ], }) ``` -------------------------------- ### ModelQueryBuilderContract (Augmented with Soft Deletes) Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/types.md The standard Lucid `ModelQueryBuilderContract` is augmented to conditionally include soft delete methods for models that implement soft delete functionality. ```APIDOC ## Interface: ModelQueryBuilderContract (Augmented) The standard Lucid `ModelQueryBuilderContract` is augmented to conditionally include soft delete methods. ### Behavior: The interface conditionally extends `SoftDeletesMethods` based on whether the model implements `ModelWithSoftDeletes`. #### For Models With SoftDeletes: ```typescript interface ModelQueryBuilderContract { // ... standard Lucid methods withTrashed(): ModelQueryBuilderContract onlyTrashed(): ModelQueryBuilderContract restore(): Promise } ``` #### For Models Without SoftDeletes: ```typescript interface ModelQueryBuilderContract { // ... standard Lucid methods // No soft delete methods } ``` ``` -------------------------------- ### Query All Records (Including Soft-Deleted) Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/index.md Retrieves all records, including those that have been soft-deleted. Use `withTrashed()` to include them. ```typescript const allUsers = await User.withTrashed().exec() ``` -------------------------------- ### Paginate Soft-Deleted Records Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Shows how to use pagination with soft-deleted records by combining the `onlyTrashed()` method with Lucid's `paginate()` function. Access the paginated data and metadata via the returned object. ```typescript // Get page 2 of soft-deleted users, 20 per page const result = await User.query() .onlyTrashed() .paginate(2, 20) // Access the paginated data result.data // array of soft-deleted users result.meta // pagination metadata ``` -------------------------------- ### Query Builder Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Extends the query builder with methods to manage soft-deleted records. These methods allow including, filtering, and restoring soft-deleted records. ```APIDOC ## Integration with Query Builder When a model uses the `SoftDeletes` mixin: 1. All `Model.query()` operations automatically exclude soft-deleted records. 2. All `Model.paginate()` operations respect soft delete filtering on both count and result queries. 3. The query builder extends with three additional methods available only on soft-delete models: - `withTrashed()` - Include soft-deleted records. - `onlyTrashed()` - Include only soft-deleted records. - `restore()` - Restore soft-deleted records in bulk. ``` -------------------------------- ### LucidSoftDeletesProvider Class Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md The service provider for LucidSoftDeletes. It registers the soft delete extensions with Lucid during the boot process. ```typescript class LucidSoftDeletesProvider { constructor(protected app: ApplicationService) async boot(): Promise } ``` -------------------------------- ### Handling E_MODEL_FORCE_DELETED Error Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Demonstrates how to catch and log the details of the E_MODEL_FORCE_DELETED error when attempting to restore a force-deleted model. ```typescript const user = await User.find(1) // Permanently delete the user await user.forceDelete() // Later, try to restore it try { await user.restore() } catch (error) { console.error(error.code) // 'E_MODEL_FORCE_DELETED' console.error(error.status) // 500 console.error(error.message) // "Cannot restore a model instance is was force deleted" } ``` -------------------------------- ### Default Soft Delete Column Configuration Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Configure the default `deleted_at` column for soft deletes in a Lucid model. Ensure the database migration includes a nullable timestamp column named `deleted_at`. ```typescript class User extends compose(BaseModel, SoftDeletes) { // Automatically uses deleted_at column @column.dateTime() declare deletedAt: DateTime | null } ``` ```typescript table.timestamp('deleted_at').nullable() ``` -------------------------------- ### Soft Deletes with Relations Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Shows how to include soft-deleted records when querying related models and how to restore them. ```typescript // Get all companies including soft-deleted ones const companies = await user.related('companies').withTrashed().exec() // Restore soft-deleted related records await user.related('companies').withTrashed().restore() ``` -------------------------------- ### Instance Methods for Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Perform actions on a specific model instance, such as soft deleting, restoring, or permanently deleting. ```typescript const user = await User.find(1) // Soft delete await user.delete() // Check if deleted if (user.trashed) { ... } // Restore await user.restore() // Permanently delete await user.forceDelete() ``` -------------------------------- ### Import Type Definitions Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/index.md Import the TypeScript type definition for models with soft delete capabilities. ```typescript import type { ModelWithSoftDeletes } from '@adonisjs/lucid/types/model' ``` -------------------------------- ### Preventing Force Delete Restoration (Conditional Restore) Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Illustrates a prevention strategy by checking if a model is soft-deleted before attempting to restore it, ensuring restore() is only called on valid candidates. ```typescript const trashed = await User.withTrashed().find(1) if (trashed.trashed && !trashed.$isDeleted) { await trashed.restore() } ``` -------------------------------- ### Adonisrc.ts After Configure Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/configure.md Shows the adonisrc.ts configuration after the soft delete provider has been automatically registered by the configure() function. ```typescript import { defineConfig } from '@adonisjs/core/app' export const appConfig = defineConfig({ // ... other config providers: [ () => import('@adonisjs/core/providers/app_provider'), () => import('@adonisjs/lucid/providers/lucid_provider'), () => import('adonis-lucid-soft-deletes/provider'), // Added automatically ], }) ``` -------------------------------- ### ModelQueryBuilder Extensions Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md Provides extensions to the ModelQueryBuilder for models utilizing the SoftDeletes mixin. These methods allow for querying trashed, restoring, and including trashed records. ```APIDOC ## ModelQueryBuilder Extensions ### Description Adds soft delete capabilities to the Lucid model query builder. Allows for querying trashed records, restoring them, and including them in query results. ### Methods #### `withTrashed()` - **Description**: Includes trashed models in the query results. - **Returns**: Query Builder instance. - **Condition**: Model must have the `SoftDeletes` mixin. #### `onlyTrashed()` - **Description**: Queries only trashed models. - **Returns**: Query Builder instance. - **Condition**: Model must have the `SoftDeletes` mixin. #### `restore()` - **Description**: Restores a trashed model. - **Returns**: `Promise`. - **Condition**: Model must have the `SoftDeletes` mixin. ``` -------------------------------- ### ModelQueryBuilderContract for Models Without SoftDeletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/types.md Illustrates the `ModelQueryBuilderContract` interface for models that do not support soft deletes. This version does not include soft delete-specific methods. ```typescript interface ModelQueryBuilderContract { // ... standard Lucid methods // No soft delete methods } ``` -------------------------------- ### Custom Deleted At Column Name Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Demonstrates how the soft delete extension automatically detects and uses a custom `deletedAt` column name defined in the model. ```typescript class User extends compose(BaseModel, SoftDeletes) { @column.dateTime({ columnName: 'removed_at' }) declare deletedAt: DateTime | null } // The extension will use 'removed_at' automatically await User.query().onlyTrashed().exec() ``` -------------------------------- ### Apply to Model Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md How to apply the SoftDeletes trait to a Lucid model and define the `deletedAt` column. ```APIDOC ## Apply to Model ```typescript import { compose } from '@adonisjs/core/helpers' import { SoftDeletes } from 'adonis-lucid-soft-deletes' class User extends compose(BaseModel, SoftDeletes) { @column.dateTime() declare deletedAt: DateTime | null } ``` ``` -------------------------------- ### Add deleted_at Column to Database Migration Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/README.md Ensure your database table has a nullable `deleted_at` timestamp column for models using soft deletes. ```typescript // migrations/1234566666_users.ts import { BaseSchema } from '@adonisjs/lucid/schema' export default class Users extends BaseSchema { protected tableName = 'users' async up() { this.schema.createTable(this.tableName, (table) => { // ... table.timestamp('deleted_at').nullable() }) } // ... } ``` -------------------------------- ### Tracking Deletion Type for Restoration Logic Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Suggests a method to distinguish between soft and force deletes by checking the record's existence in a separate query before attempting restoration. ```typescript // If you need to distinguish between soft and force deletes, // consider checking the presence of the record in a separate query const stillExists = await User.withTrashed().find(user.id) if (stillExists) { await user.restore() // Safe } else { // User was force deleted } ``` -------------------------------- ### Querying Soft-Deleted Records in Relations Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Shows how to use `withTrashed()` and `onlyTrashed()` methods on relation queries to include or filter soft-deleted records. The `restore()` method can also be used on these queries. ```typescript // Include soft-deleted posts from a user const posts = await user.related('posts').withTrashed().exec() // Only soft-deleted posts const deleted = await user.related('posts').onlyTrashed().exec() // Restore soft-deleted posts await user.related('posts').withTrashed().restore() ``` -------------------------------- ### Documented Types Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Lists the types defined or augmented by the SoftDeletes package, and their coverage. ```APIDOC ## Types Lists the types defined or augmented by the SoftDeletes package, and their coverage. | Type | |---| | `ModelWithSoftDeletes` | | `ModelQueryBuilderContract` (augmented) | | `ExcludeSoftDeletesMethods` | | `SoftDeletesMethods` | | `ModelQueryBuilderContractWithIgnoreDeleted` | ``` -------------------------------- ### Conditional Use of Soft Delete Methods Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Illustrates how to correctly use soft delete methods only on models that have the SoftDeletes mixin applied, and how to avoid calling them on models that do not. ```typescript // Only call soft delete methods on User (which has SoftDeletes) const softDeletedUsers = await User.query().withTrashed().exec() // Don't call soft delete methods on Post (which doesn't have SoftDeletes) const posts = await Post.query().exec() // ✓ Fine // await Post.query().withTrashed().exec() // ✗ Would throw ``` -------------------------------- ### Register Provider in adonisrc.ts Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/README.md Register the provider in your `adonisrc.ts` file to enable the addon's functionality. ```typescript providers: [ // ... () => import('adonis-lucid-soft-deletes/provider'), ] ``` -------------------------------- ### Error Handling for Models Without Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/model-query-builder-extensions.md Illustrates the error handling mechanism when attempting to use soft delete query builder methods on a model that does not support soft deletes. ```typescript class Post extends BaseModel { // No SoftDeletes mixin } try { await Post.query().withTrashed().exec() } catch (error) { console.error(error.code) // E_MODEL_SOFT_DELETE console.error(error.message) // "Post model don't support Soft Deletes" } ``` -------------------------------- ### SoftDeletes Exports Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/MANIFEST.md Details the main exported symbols from the SoftDeletes module, indicating their completeness. ```APIDOC ## Exported Symbols Details the main exported symbols from the SoftDeletes module, indicating their completeness. | Symbol | |---| | `SoftDeletes` | | `configure` | | `LucidSoftDeletesProvider` | | `extendModelQueryBuilder` | ``` -------------------------------- ### Restore Soft Deleted Models Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/README.md Restore a soft-deleted model by calling the `.restore()` method on the instance or using query builder methods like `.withTrashed().where(...).restore()`. ```typescript import type { HttpContext } from '@adonisjs/core/http' import User from '#models/user' export default class TrashUsersController { /** * Update trashed user by id * PUT /trash/users/:id */ async update({ params }: HttpContext) { const user = await User.withTrashed().where('id', params.id).firstOrFail() await user.restore() return user // or await User.withTrashed().where('id', params.id).restore() await User.query().withTrashed().where('id', params.id).restore() } } ``` -------------------------------- ### Instance Methods: delete() Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Overrides the default delete method to perform a soft delete. It sets the `deleted_at` property to the current time and saves the model. The model will be filtered from default queries but can be retrieved using `withTrashed()`. ```APIDOC ## Instance Methods: delete() ### Description Overrides the default delete method to perform a soft delete. It sets the `deleted_at` property to the current time and saves the model. The model will be filtered from default queries but can be retrieved using `withTrashed()`. ### Signature ```typescript async delete(): Promise ``` ### Parameters None ### Returns Promise that resolves when the soft delete is complete. Type: `Promise` ### Behavior Sets the `deleted_at` property to `DateTime.local()` and calls `save()`. The model remains in the database but is filtered from queries by default. ### Example ```typescript const user = await User.find(1) await user.delete() // Soft delete // The record is now filtered from default queries const found = await User.find(1) // returns null // But still accessible with withTrashed() const deleted = await User.withTrashed().find(1) // returns the user console.log(deleted.trashed) // true ``` ``` -------------------------------- ### LucidSoftDeletesProvider Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-summary.md The service provider for the LucidSoftDeletes package. It is responsible for registering the soft delete extensions with Lucid during the application boot process. ```APIDOC ## LucidSoftDeletesProvider ### Description Service provider for the LucidSoftDeletes package. Registers the soft delete query builder extensions with the Lucid ORM. ### Constructor - **Signature**: `constructor(app: ApplicationService)` - **Description**: Initializes the provider with the AdonisJS application instance. ### Boot Method - **Signature**: `async boot(): Promise` - **Description**: Registers the soft delete extensions with Lucid ORM. ``` -------------------------------- ### $getQueryFor Hook Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Overrides the default query generation method to handle soft delete operations. This hook intercepts delete actions and converts them to soft deletes when `$forceDelete` is false. ```APIDOC ## $getQueryFor() Hook ### Description Overrides the default query generation method to handle soft delete operations. This hook intercepts delete actions and converts them to soft deletes when `$forceDelete` is false. Otherwise, it delegates to the parent class. ### Signature ```typescript $getQueryFor( action: 'insert' | 'update' | 'delete' | 'refresh', client: QueryClientContract ): any ``` ### Parameters #### Parameters - **action** (string) - Required - The database operation type. - **client** (QueryClientContract) - Required - The database client. ### Returns - **any**: Query methods for the action. ``` -------------------------------- ### Restoring a Soft Deleted Model Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/soft-deletes.md Use the `restore()` method on a soft-deleted model instance to set its `deleted_at` timestamp to `null`, making it visible in default queries again. You can also use the query builder for bulk restoration. ```typescript const user = await User.withTrashed().find(1) if (user.trashed) { await user.restore() } // Or use query builder restore await User.withTrashed().where('id', 1).restore() ``` -------------------------------- ### Custom Soft Delete Column Types Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Demonstrates different timestamp column types compatible with the `SoftDeletes` mixin. Ensure the chosen type can store DateTime values and is nullable. ```typescript table.timestamp('deleted_at').nullable() ``` ```typescript table.timestamp('deleted_at', { useTz: true }).nullable() ``` ```typescript table.dateTime('deleted_at').nullable() ``` -------------------------------- ### Models with Relations Using Soft Deletes Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Demonstrates how to apply the SoftDeletes mixin to models that have `hasMany` and `belongsTo` relations. Soft deletes are automatically compatible with all relation types. ```typescript import { hasMany, belongsTo } from '@adonisjs/lucid/orm' export default class User extends compose(BaseModel, SoftDeletes) { @column({ isPrimary: true }) declare id: number @hasMany(() => Post) declare posts: HasMany } export default class Post extends compose(BaseModel, SoftDeletes) { @column({ isPrimary: true }) declare id: number @column() declare userId: number @belongsTo(() => User) declare user: BelongsTo } ``` -------------------------------- ### Implement Conditional Soft Delete or Force Delete Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Provide an option to either soft delete a user (allowing for restoration) or permanently force delete them. This is useful for scenarios where data retention policies differ. ```typescript async deleteUser(userId: number, permanent: boolean = false) { const user = await User.find(userId) if (!user) { throw new Error('User not found') } if (permanent) { // Ensure no one tries to restore later await user.forceDelete() } else { // Soft delete allows later restoration await user.delete() } } ``` -------------------------------- ### Configure LucidSoftDeletesProvider in AdonisJS Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/provider.md Register the LucidSoftDeletesProvider in your AdonisJS application's configuration to enable soft delete functionality. This provider is automatically booted by the framework. ```typescript // In config/app.ts import { defineConfig } from '@adonisjs/core/app' export const appConfig = defineConfig({ providers: [ () => import('@adonisjs/core/providers/app_provider'), () => import('@adonisjs/lucid/providers/lucid_provider'), () => import('adonis-lucid-soft-deletes/provider'), // Automatically booted ], }) ``` -------------------------------- ### Apply SoftDeletes Mixin to Model Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/configuration.md Compose your Lucid model with the `SoftDeletes` mixin to enable soft delete capabilities. Ensure the `deletedAt` column is defined as a DateTime type. ```typescript import { compose } from '@adonisjs/core/helpers' import { BaseModel, column } from '@adonisjs/lucid/orm' import { SoftDeletes } from 'adonis-lucid-soft-deletes' import { DateTime } from 'luxon' export default class User extends compose(BaseModel, SoftDeletes) { @column({ isPrimary: true }) declare id: number @column() declare email: string @column() declare username: string @column.dateTime() declare createdAt: DateTime @column.dateTime() declare updatedAt: DateTime @column.dateTime() declare deletedAt: DateTime | null } ``` -------------------------------- ### Triggering E_MODEL_SOFT_DELETE Error Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/errors.md Demonstrates how the E_MODEL_SOFT_DELETE error is thrown when soft delete query methods are used on a model without the SoftDeletes mixin. Shows how to catch the error and inspect its properties. ```typescript class Post extends BaseModel { // No SoftDeletes mixin - soft delete methods not available } try { await Post.query().withTrashed().exec() } catch (error) { console.error(error.code) // 'E_MODEL_SOFT_DELETE' console.error(error.status) // 500 console.error(error.message) // "Post model don't support Soft Deletes" } ``` -------------------------------- ### Manual Query Builder Extension Source: https://github.com/lookinlab/adonis-lucid-soft-deletes/blob/master/_autodocs/api-reference/provider.md Manually extend the ModelQueryBuilder with soft delete methods for custom scenarios or testing without the provider. ```typescript import { ModelQueryBuilder } from '@adonisjs/lucid/orm' import { extendModelQueryBuilder } from 'adonis-lucid-soft-deletes/bindings' // Manually extend the builder extendModelQueryBuilder(ModelQueryBuilder) // Now soft delete methods are available ```