npm package: @inovan.do/adonis-crud
Description: A crud abstraction for AdonisJs
Author: Tiago Cristiano Alves
Latest version: 0.1.70


# adonis-crud

Advanced abstraction to use with Adonis Framework

# Contents

- [Installation](#installation)
- [Configuration](#configuration)
- [Features](#features)
- [File Generated by Adonis Crud](#file-generated-by-adonis-crud)
- [Query Builder](#query-builder)

# Installation

```bash
npm install @inovan.do/adonis-crud

```

# Configuration

## Install Lucid Orm

As informed here [Adonis DataBase Introduction](https://docs.adonisjs.com/guides/database/introduction)

## Install Auth

As informed here [Adonis Auth Introduction](https://docs.adonisjs.com/guides/auth/introduction)

![auth install orientation](/docs/Auth.png "Answer this questions").

Also install the hash dependencie
[available-hashers](https://docs.adonisjs.com/guides/security/hashing#available-hashers)

```bash
npm i phc-argon2
```

## Configure package

```bash
node ace configure adonis-crud
```

This should update your `.adonisrc.json`, `tsconfig.json` and add a list of other files: [File Genereted](#file-generated-by-adonis-crud)


## Usage Example
Let's create some come.

## Create the route for the resource

- in **routes.ts** add

```ts
Route.resource('/posts', 'PostController')
```

### Create the migration to the model
```bash
node ace make:migration Posts
```

```ts

import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class extends BaseSchema {
  protected tableName = 'posts'

  public async up() {
    this.schema.createTable(this.tableName, (table) => {
      table.increments('id')
      table.string('title').notNullable()
      table.string('content').notNullable()
      table.boolean('status').defaultTo(true)
      table.timestamp('created_at', { useTz: true })
      table.timestamp('updated_at', { useTz: true })
    })
  }

  public async down() {
    this.schema.dropTable(this.tableName)
  }
}

```

## Migration and seeders

>Create database initial structure

```bash
  node ace migration:run
```

>Seeds Initial Data

```bash
  node ace make:model Post
```

## Create the model to persist data to the database

```bash
  node ace make:model Post
```

## Fulfill as needed

```ts
import { DateTime } from 'luxon'
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'

export default class Post extends BaseModel {
 @column({ isPrimary: true })
  public id: number

  @column.dateTime({ autoCreate: true })
  public createdAt: DateTime

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  public updatedAt: DateTime

  @column()
  public status: boolean

  @column()
  public title: string

  @column()
  public content: string
}
```

## Create your repository to deal with your model using the decorator provided

```ts
import Event from '@ioc:Adonis/Core/Event'
import CrudRepository, { CrudRepositoryInterface } from '@ioc:AdonisCrud/Crud/Repository'
import User from 'App/Models/Post'

@CrudRepository<Post>({
  event: Event,
  model: Post,
  selectFields: ['id', 'title', 'content'],
 
})
export default class PostRepository implements CrudRepositoryInterface<Post> {}

```

### Crud repository props

| Property         |  Description    | Required?|
|------------------| -----------| -----------|
| **event**        | Event emiter from Adonis to be used in hooks features | &#9745;|
| **model**        | Model     | &#9745;|
| **selectFields** | Array of fields to be used in select | &#9745;|

## Create your transformer

```ts
import { TransformerAbstract } from '@ioc:Adonis/Addons/Bumblebee'
export default class PostTransformer extends TransformerAbstract {
  public transform(model) {
    return {
      id: model.id,
      status: model.status,
      title: model.title,
      content: model.content,
      createdAt: model.createdAt,
    }
  }
}

```

> Here you can format or transform your data, format a date field, make a computed property....

## Create your controller and use the decorator provided

```ts
import Crud, { CrudControllerInterface, OptionsCrud } from '@ioc:AdonisCrud/Crud/Controller'
import Post from 'App/Models/Post'
import PostRepository from '@ioc:PostRepository'
import BaseTransformer from 'App/Transformers/BaseTransformer'

@Crud<Post>({
  repository: PostRepository,
  storeProps: ['title','content'],
  updateProps: ['content'],
  transformer: BaseTransformer,
  validators: {
    store: '', //Adonis validator class
    update: ''
  }
})
export default class PostsController<Post> implements CrudControllerInterface<Post> {
  options: OptionsCrud<Post>
}
```

### Crud decorator options

| Property        |  Description    | **Required**?|
|-----------------| -----------| -----------|
 | **repository**  | Repository used to deal with your model data.| &#9745;|
 | **storeProps**  | Allow properties to create your model.| &#9745;|
 | **updateProps** | Allow properties to update your model.|&#9745;|
 | **transformer** | Adonis bublebee class to trasform data | &#9745;|
 | **validators**  | [Validator class](https://docs.adonisjs.com/guides/validator/introduction#validator-classes) for each method used to store and update ] |&#9744;|

> If a not allowed param is provided in store or update request a exception will be returned.

> If a validator object is not provided validation will not be applied to store and update methods.

# Features

- &#9745; Crud Abstraction
- &#9745; Validators
- &#9745; Events (on update, on delete, on create)
- &#9745; Intercept flow and develop your own bussines logic
- &#9745; Apply Scoped Queries
- &#9745; Transformer with includes (join relationship automagically). Thanks to [adonis-bublebee-ts](https://github.com/kmorpex/adonis-bublebee-ts).
- &#9745; Generate report csv/ pdf.
- &#9745; ACL based on Adonis ACL.

# **Create**

- Validate data to create based on Adonis Validators.
- Bulk Insert

# **Read**

- Default pagination
- Feature includes (add relationship to return data)
- [Query builder](#query-builder) from request params
- Feature All (get all itens)
- Configurable select fields
- Configurable order

# **U**pdate

- Validate update props based on adonis validators
- Bulk update

# **D**elete

- Default soft delete strategy
- Bulk delete

## Dependencies

- [Adonis ACL](https://github.com/shagital/adonisjs-acl) for role and permission management
- [Adonis Bublebee ts](https://github.com/kmorpex/adonis-bublebee-ts) for tranform and include data to response.

## File Generated by Adonis Crud

- Models:
  - [BaseCrudModel](#basecrudmodel)
  - [Profile](#profile)
  - [User](#user)

### BaseCrudModel

```ts
import { DateTime } from 'luxon'
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'

export default class BaseCrudModel extends BaseModel {
  @column({ isPrimary: true })
  public id: number

  @column.dateTime({ autoCreate: true })
  public createdAt: DateTime

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  public updatedAt: DateTime

  @column()
  public status: boolean
}

```

### Profile

```ts
import { column } from '@ioc:Adonis/Lucid/Orm'
import BaseCrudModel from './BaseCrudModel'
export default class Profile extends BaseCrudModel {
  @column()
  public name: string
}
```

### User

```ts
import { DateTime } from 'luxon'
import Hash from '@ioc:Adonis/Core/Hash'
import { column, beforeSave, ManyToMany, manyToMany } from '@ioc:Adonis/Lucid/Orm'
import BaseCrudModel from './BaseCrudModel'
import Profile from './Profile'

export default class User extends BaseCrudModel {
  @column()
  public name: string

  @column()
  public email: string

  @column({ serializeAs: null })
  public password: string

  @column()
  public status: boolean

  @column()
  public rememberMeToken?: string

  @column.dateTime({ autoCreate: true })
  public createdAt: DateTime

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  public updatedAt: DateTime

  @column.dateTime()
  public deletedAt: DateTime

  @beforeSave()
  public static async hashPassword(user: User) {
    if (user.$dirty.password) {
      user.password = await Hash.make(user.password)
    }
  }

  @manyToMany(() => Profile, {
    localKey: 'id',
    pivotForeignKey: 'user_id',
    relatedKey: 'id',
    pivotRelatedForeignKey: 'profile_id',
    pivotTable: 'user_profiles',
  })
  public profiles: ManyToMany<typeof Profile>
}

```

## Query Builder


## Contributing
- Clone this repo
- Install dependencies: `npm install`
- Implement your feature
- build de code: `yarn build`