Skip to content

ks-labs/adonis4-soft-deletes

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Adonis Soft Deletes

Notes (PLEASE READ)

  • This is for Adonis v4.x
  • I'll try to recreate this package for Adonis v5 as well

Breaking changes from version 2.x.x

  • It is needed to define .withTrashed()/.onlyTrashed() before using .restore()

Notable changes from version 2.x.x

  • Every query has been changed to use tableName.fieldName format instead of just fieldName due to ambiguous field errors
  • Package now works with manyThrough relations
  • Due to core Adonis changes 2 tests are failing but are still working as intended

Introduction

This package allows you to soft delete entries in the DB meaning that they will still be there but will have 'deleted_at' set to some value and as such 'deleted'

Installation

Make sure to install it using npm or yarn.

# npm
npm i @ksgl/adonis4-soft-deletes

# yarn
yarn add @ksgl/adonis4-soft-deletes

Provider registration

Make sure to register the provider inside start/app.js file.

const providers = [
  ...
  '@ksgl/adonis4-soft-deletes/providers/SoftDeletesProvider',
  ...
]

Setup

Inside your boot() method in model

const Model = use('Model')

class Post extends Model {
  static boot () {
    super.boot()
    this.addTrait('@provider:SoftDeletes')
  }
}

Options

tableName

Type: string

Description: If you need to define table name before a field name

Default: Whatever the table name is

fieldName

Type: string

Description: If you need to define field name to use when deleting

Default: "deleted_at"

Usage

const Model = use('Model')

class Post extends Model {
  static boot () {
    super.boot()
    this.addTrait('@provider:SoftDeletes', { fieldName: "deleted_at", hideSoftDeletedRows: true })
  }
}

NOTE: Make sure that your model table has deleted_at datetime column (or whatever your fieldName name is)

NOTE: By default it hide any deleted rows, to show deleted rows by default use hideSoftDeletedRows = false to disable filtering

NOTE: If the model has this trait, upon delete() we will soft delete, if you want to delete then call forceDelete()

Custom model hooks

Depending on where you called .delete, .forceDelete(), .restore() you will get either one instance (on Model) or multiple instances (on query) as "someCustomName"

softDelete

This is a model hook fired before/after .delete()

this.addHook('beforeSoftDelete', async (someCustomName) => {
  // Do something
})

this.addHook('afterSoftDelete', async (someCustomName) => {
// Do something
})

delete (default Adonis hook)

This is a default adonis hook fired before/after real delete or in this case .forceDelete()

this.addHook('beforeDelete', async (someCustomName) => {
  // Do something
})

this.addHook('afterDelete', async (someCustomName) => {
// Do something
})

restore

This is a default adonis hook but I couldn't find any place where it is used so I've decided to use it for restore()

this.addHook('beforeRestore', async (someCustomName) => {
  // Do something
})

this.addHook('afterRestore', async (someCustomName) => {
// Do something
})

Model instance

NOTE: Upon soft delete/restore we change the $frozen property.

When we want to soft delete a model instance

 ...
 let user = await User.find(1)
 await user.delete()
 ...

When we want to restore a model instance

 ...
 let user = await User.query().withTrashed().where("id",1).first()
 await user.restore()
 ...

When we want to force delete a model instance

 ...
 let user = await User.find(1)
 await user.forceDelete()
 ...

Check if model instance is soft deleted

 ...
 let user = await User.query().withTrashed().where("id",1).first()
 let isSoftDeleted = await user.isSoftDeleted()
 ...

Model query builder

NOTE: Upon delete/restore we DO NOT change the $frozen property since it is not possible

When we want to soft delete using query

 ...
 await User.query()
 .where('country_id', 4)
 .delete()
 ...

When we want to restore using query

 ...
 await User.query()
 .where('country_id', 4)
 .onlyTrashed()
 .restore()
 ...

When we want to force delete using query

 ...
 await User.query()
 .where('country_id', 4)
 .forceDelete()
 ...

When we want to fetch non trashed users

 ...
 // We will automatically get only non trashed users
 await User.query().fetch()
 ...

When we want to fetch with trashed users

 ...
 await User.query().withTrashed().fetch()
 ...

When we want to fetch only trashed users

 ...
 await User.query().onlyTrashed().fetch()
 ...

Relationships

When we want to soft delete relations

 ...
 await ownerUser.cars().delete();
 ...

When we want to restore relations

 ...
 await  ownerUser.cars().onlyTrashed().restore();
 ...

When we want to get non trashed relations

 ...
 await  ownerUser.cars().fetch();
 ...

When we want to get all relations

 ...
 await  ownerUser.cars().withTrashed().fetch();
 ...

When we want to get onlyTrashed relations

 ...
 await  ownerUser.cars().onlyTrashed().fetch();
 ...

manyThrough relations

There are some additional things required for use with manyThrough

If you have updated_at timestamp available for Model then you need to redefine updatedAtColumn to be tableName.fieldName

 ...
class User extends Model {
  static boot() {
    super.boot()
    this.addTrait('@provider:SoftDeletes')
  }

  static get updatedAtColumn() {
    return 'users.updated_at'
  }
}
 ...

Thanks

Special thanks to the creator(s) of AdonisJS for creating such a great framework.

About

Implementation of soft deletes in AdonisJS

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%