> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zopio.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# CRUD Engine

> Core CRUD functionality built on top of data providers

# CRUD Engine

The CRUD Engine is the core component of the `@repo/crud` package, providing enhanced CRUD operations with support for plugins, permissions, and auditing. It wraps a data provider from the `@repo/data` package and adds additional functionality.

## Features

* **Enhanced CRUD Operations**: Extends the basic CRUD operations with additional features
* **Plugin System**: Support for plugins that can modify behavior before and after operations
* **Permissions Integration**: Built-in support for access control
* **Audit Logging**: Automatic tracking of data changes
* **Internationalization**: Support for multiple languages
* **Error Handling**: Consistent error handling across operations

## Basic Usage

### Creating a CRUD Engine

```typescript theme={"system"}
import { engine } from '@repo/crud';
import { providers } from '@repo/data';

// Create a data provider
const dataProvider = providers.supabase.createProvider({
  url: process.env.SUPABASE_URL,
  key: process.env.SUPABASE_KEY
});

// Create a CRUD engine
const crudEngine = engine.createCrudEngine({
  dataProvider,
  enableAudit: true,
  enablePermissions: true,
  plugins: [],
  defaultLocale: 'en',
  supportedLocales: ['en', 'fr', 'de', 'es', 'tr']
});
```

### Using the CRUD Engine

```typescript theme={"system"}
// Get a list of resources
const { data, total } = await crudEngine.getList({
  resource: 'users',
  pagination: { page: 1, perPage: 10 },
  sort: { field: 'createdAt', order: 'desc' },
  filter: { role: 'admin' }
});

// Get a single resource
const { data: user } = await crudEngine.getOne({
  resource: 'users',
  id: '123'
});

// Create a resource
const { data: newUser } = await crudEngine.create({
  resource: 'users',
  data: { name: 'John Doe', email: 'john@example.com' }
});

// Update a resource
const { data: updatedUser } = await crudEngine.update({
  resource: 'users',
  id: '123',
  data: { name: 'John Smith' }
});

// Delete a resource
const { data: deletedUser } = await crudEngine.delete({
  resource: 'users',
  id: '123'
});
```

## Configuration Options

The CRUD Engine accepts the following configuration options:

```typescript theme={"system"}
interface CrudEngineOptions {
  /** The data provider to use */
  dataProvider: CrudProvider;
  /** Enable auditing of operations */
  enableAudit?: boolean;
  /** Audit provider for custom audit logging */
  auditProvider?: AuditProvider;
  /** Enable permissions checking */
  enablePermissions?: boolean;
  /** Permissions provider for custom permission checks */
  permissionsProvider?: PermissionsProvider;
  /** Plugins to use */
  plugins?: CrudPlugin[];
  /** Default locale for internationalization */
  defaultLocale?: string;
  /** Supported locales for internationalization */
  supportedLocales?: string[];
  /** Error handler for custom error handling */
  errorHandler?: ErrorHandler;
}
```

## Plugin System

The CRUD Engine includes a powerful plugin system that allows you to extend its functionality. Plugins can modify the behavior of CRUD operations by intercepting them before and after they are executed.

### Plugin Interface

```typescript theme={"system"}
interface CrudPlugin {
  /** Unique name of the plugin */
  name: string;
  /** Plugin initialization function */
  initialize: (engine: CrudEngine) => void;
  /** Hooks for different CRUD operations */
  hooks?: {
    beforeGetList?: (params: GetListParams) => GetListParams;
    afterGetList?: (result: any, params: GetListParams) => any;
    beforeGetOne?: (params: GetOneParams) => GetOneParams;
    afterGetOne?: (result: any, params: GetOneParams) => any;
    beforeCreate?: (params: CreateParams) => CreateParams;
    afterCreate?: (result: any, params: CreateParams) => any;
    beforeUpdate?: (params: UpdateParams) => UpdateParams;
    afterUpdate?: (result: any, params: UpdateParams) => any;
    beforeDelete?: (params: DeleteParams) => DeleteParams;
    afterDelete?: (result: any, params: DeleteParams) => any;
  };
}
```

### Creating a Plugin

```typescript theme={"system"}
import { engine } from '@repo/crud';

// Create a logging plugin
const loggingPlugin: engine.CrudPlugin = {
  name: 'logging',
  initialize: (engine) => {
    console.log('Logging plugin initialized');
  },
  hooks: {
    beforeGetList: (params) => {
      console.log('Getting list', params);
      return params;
    },
    afterGetList: (result, params) => {
      console.log('Got list', result);
      return result;
    },
    beforeCreate: (params) => {
      console.log('Creating resource', params);
      return params;
    },
    afterCreate: (result, params) => {
      console.log('Created resource', result);
      return result;
    }
    // Add more hooks as needed
  }
};

// Use the plugin
const crudEngine = engine.createCrudEngine({
  dataProvider,
  plugins: [loggingPlugin]
});
```

### Plugin Execution Order

Plugins are executed in the order they are provided in the `plugins` array. For example, if you have three plugins:

```typescript theme={"system"}
const crudEngine = engine.createCrudEngine({
  dataProvider,
  plugins: [pluginA, pluginB, pluginC]
});
```

The execution order for a `getList` operation would be:

1. `pluginA.hooks.beforeGetList`
2. `pluginB.hooks.beforeGetList`
3. `pluginC.hooks.beforeGetList`
4. Actual `getList` operation
5. `pluginC.hooks.afterGetList`
6. `pluginB.hooks.afterGetList`
7. `pluginA.hooks.afterGetList`

Note that the "after" hooks are executed in reverse order, allowing each plugin to process the result in the reverse order of the "before" hooks.

## Permissions Integration

The CRUD Engine includes built-in support for permissions checking. When enabled, it will check if the current user has permission to perform the requested operation.

### Enabling Permissions

```typescript theme={"system"}
import { engine, permissions } from '@repo/crud';

// Create a permissions provider
const permissionsProvider = permissions.createPermissionsProvider({
  getPermissions: async (user) => {
    return {
      users: {
        read: true,
        create: user.role === 'admin',
        update: (user, resource) => user.id === resource.id || user.role === 'admin',
        delete: user.role === 'admin'
      }
    };
  }
});

// Create a CRUD engine with permissions
const crudEngine = engine.createCrudEngine({
  dataProvider,
  enablePermissions: true,
  permissionsProvider
});
```

### Permissions Context

When using permissions, you need to set the current user in the permissions context:

```typescript theme={"system"}
import { permissions } from '@repo/crud';

// Set the current user
permissions.setUser({
  id: '123',
  role: 'admin'
});

// Now CRUD operations will be checked against this user
const result = await crudEngine.getList({
  resource: 'users',
  pagination: { page: 1, perPage: 10 }
});
```

## Audit Logging

The CRUD Engine includes built-in support for audit logging. When enabled, it will log all changes to data.

### Enabling Audit Logging

```typescript theme={"system"}
import { engine, audit } from '@repo/crud';

// Create an audit provider
const auditProvider = audit.createAuditProvider({
  logAudit: async (auditLog) => {
    // Store audit log in database
    await db.auditLogs.create(auditLog);
  }
});

// Create a CRUD engine with audit logging
const crudEngine = engine.createCrudEngine({
  dataProvider,
  enableAudit: true,
  auditProvider
});
```

### Audit Context

When using audit logging, you need to set the current user in the audit context:

```typescript theme={"system"}
import { audit } from '@repo/crud';

// Set the current user
audit.setUser({
  id: '123',
  name: 'John Doe'
});

// Now CRUD operations will include this user in audit logs
const result = await crudEngine.create({
  resource: 'posts',
  data: { title: 'New Post', content: 'Hello World' }
});
```

## Internationalization

The CRUD Engine includes built-in support for internationalization. You can specify the default locale and supported locales when creating the engine.

### Configuring Internationalization

```typescript theme={"system"}
import { engine } from '@repo/crud';

// Create a CRUD engine with internationalization
const crudEngine = engine.createCrudEngine({
  dataProvider,
  defaultLocale: 'en',
  supportedLocales: ['en', 'fr', 'de', 'es', 'tr']
});
```

### Using Translations

The CRUD Engine uses the `next-intl` package for translations. You can use the `useTranslation` hook to get translations:

```tsx theme={"system"}
import { useTranslation } from 'next-intl';

function MyComponent() {
  const { t } = useTranslation();
  
  return (
    <div>
      <h1>{t('users.title')}</h1>
      <p>{t('users.description')}</p>
    </div>
  );
}
```

## Error Handling

The CRUD Engine includes built-in error handling. You can provide a custom error handler when creating the engine.

### Custom Error Handler

```typescript theme={"system"}
import { engine } from '@repo/crud';

// Create a custom error handler
const errorHandler: engine.ErrorHandler = (error, operation, params) => {
  console.error(`Error in ${operation} operation:`, error);
  console.error('Params:', params);
  
  // You can transform the error
  if (error.code === 'PERMISSION_DENIED') {
    return new Error('You do not have permission to perform this operation');
  }
  
  return error;
};

// Create a CRUD engine with custom error handling
const crudEngine = engine.createCrudEngine({
  dataProvider,
  errorHandler
});
```

## Advanced Usage

### Creating a CRUD Engine with a Provider Type

You can create a CRUD Engine with a specific provider type:

```typescript theme={"system"}
import { engine } from '@repo/crud';

// Create a CRUD engine with a Supabase provider
const crudEngine = engine.createCrudEngineWithProvider('supabase', {
  url: process.env.SUPABASE_URL,
  key: process.env.SUPABASE_KEY
}, {
  enableAudit: true,
  enablePermissions: true
});
```

### Extending the CRUD Engine

You can extend the CRUD Engine with custom methods:

```typescript theme={"system"}
import { engine } from '@repo/crud';

// Create a custom CRUD engine class
class CustomCrudEngine extends engine.CrudEngine {
  constructor(options) {
    super(options);
  }
  
  // Add custom methods
  async getByEmail(resource, email) {
    const { data, total } = await this.getList({
      resource,
      filter: { email }
    });
    
    return data[0] || null;
  }
  
  async bulkCreate(resource, items) {
    const results = [];
    
    for (const item of items) {
      const result = await this.create({
        resource,
        data: item
      });
      
      results.push(result.data);
    }
    
    return results;
  }
}

// Create a custom CRUD engine
const customEngine = new CustomCrudEngine({
  dataProvider,
  enableAudit: true,
  enablePermissions: true
});

// Use custom methods
const user = await customEngine.getByEmail('users', 'john@example.com');
const posts = await customEngine.bulkCreate('posts', [
  { title: 'Post 1', content: 'Content 1' },
  { title: 'Post 2', content: 'Content 2' }
]);
```

## API Reference

### CrudEngine Class

```typescript theme={"system"}
class CrudEngine {
  constructor(options: CrudEngineOptions);
  
  // Get the data provider
  getDataProvider(): CrudProvider;
  
  // CRUD operations
  getList(params: GetListParams): Promise<GetListResult>;
  getOne(params: GetOneParams): Promise<GetOneResult>;
  create(params: CreateParams): Promise<CreateResult>;
  update(params: UpdateParams): Promise<UpdateResult>;
  delete(params: DeleteParams): Promise<DeleteResult>;
}
```

### Factory Functions

```typescript theme={"system"}
// Create a CRUD engine
function createCrudEngine(options: CrudEngineOptions): CrudEngine;

// Create a CRUD engine with a provider type
function createCrudEngineWithProvider(
  providerType: string,
  providerConfig: any,
  engineOptions?: Partial<CrudEngineOptions>
): CrudEngine;
```

For a complete API reference, please refer to the TypeScript definitions in the package.
