npm package: @nutriplatform/hasura-client
Description: Hasura client for Nutriplatform
Author: Florent Bejina
Latest version: 0.0.1-alpha4

# @nutriplatform/hasura-client

A TypeScript client library for interacting with the NutriBudget Hasura GraphQL API using Prisma ORM.

## Introduction

The `@nutriplatform/hasura-client` module provides a convenient way to interact with the NutriBudget database through Prisma ORM. It serves as a bridge between your application and the Hasura GraphQL API, allowing you to:

- Create a Prisma client instance with a specified database URL
- Access and manipulate data in the database using TypeScript
- Leverage Prisma's type safety and auto-completion features
- Work with the database schema in a type-safe manner

This module is a key component of the NutriBudget platform architecture, supporting the Nutriplatform decision support tool by providing direct database access for backend services and data analysis components.

## Repository Structure

This module is part of the NutriBudget project, which follows a monorepo structure:

```
NutriBudget/
├── apps/                # Applications
│   ├── frontend/        # Frontend application
│   ├── backend/         # Backend services including Hasura
│
├── libs/                # Shared libraries
│   ├── common/          # Common utilities and business logic
│   ├── ui/              # Shared UI components
│   └── hasura-client/   # This module - TypeScript client for Hasura
│
├── docker/              # Docker configurations
├── docs/                # Project documentation
├── tools/               # Scripts and tools
└── ...
```

The `hasura-client` module serves as a bridge between backend services and the Hasura GraphQL API, providing a type-safe way to interact with the database using Prisma ORM.

## Installation

### Prerequisites

- Node.js (v18 or higher)
- npm or yarn
- Access to the NutriBudget database

### Installation Steps

```bash
# Using npm
npm install @nutriplatform/hasura-client

# Using yarn
yarn add @nutriplatform/hasura-client
```

### Configuration

The client requires a database URL to connect to the Hasura database. This URL should be provided as an environment variable or passed directly to the client.

Example `.env` file:

```
DATABASE_URL=postgresql://username:password@localhost:5433/hasura
```

## Usage

### Creating a Client Instance

```typescript
import prismaClient from '@nutriplatform/hasura-client';

// Create a client instance with the database URL
const prisma = prismaClient.create('postgresql://username:password@localhost:5433/hasura');

// Or use an environment variable
const prisma = prismaClient.create(process.env.DATABASE_URL);
```

### Querying Data

#### Fetching Farms

```typescript
// Get all farms
const farms = await prisma.farm.findMany();

// Get a specific farm by ID
const farm = await prisma.farm.findUnique({
  where: {
    id: 1,
  },
});
```

#### Working with Relationships

```typescript
// Get a farm with its fields
const farmWithFields = await prisma.farm.findUnique({
  where: {
    id: 1,
  },
  include: {
    field: true,
  },
});

// Create a new field for a farm
const newField = await prisma.field.create({
  data: {
    name: 'North Field',
    crop: 'Wheat',
    surface: 10.5,
    farm: {
      connect: {
        id: 1,
      },
    },
  },
});
```

### Transactions

For operations that require multiple database changes, you can use transactions to ensure data integrity:

```typescript
const result = await prisma.$transaction(async (tx) => {
  // Create a new farm
  const farm = await tx.farm.create({
    data: {
      name: 'New Farm',
    },
  });

  // Create fields for the farm
  const field1 = await tx.field.create({
    data: {
      name: 'Field 1',
      surface: 5.0,
      farm: {
        connect: {
          id: farm.id,
        },
      },
    },
  });

  const field2 = await tx.field.create({
    data: {
      name: 'Field 2',
      surface: 7.5,
      farm: {
        connect: {
          id: farm.id,
        },
      },
    },
  });

  return { farm, fields: [field1, field2] };
});
```

### Error Handling

```typescript
try {
  const farm = await prisma.farm.create({
    data: {
      name: 'New Farm',
    },
  });
  console.log('Farm created:', farm);
} catch (error) {
  console.error('Error creating farm:', error);
}
```

## API Reference

### `prismaClient.create(databaseUrl: string): PrismaClient`

Creates and returns a new Prisma client instance configured with the provided database URL.

- **Parameters:**
  - `databaseUrl`: A string representing the PostgreSQL connection URL.
- **Returns:**
  - A `PrismaClient` instance that can be used to interact with the database.

### Types

The module also exports types from the Prisma client:

```typescript
import { types } from '@nutriplatform/hasura-client';

// Use types in your code
const farm: types.farm = {
  id: 1,
  name: 'My Farm',
};
```

## Database Schema

The current database schema includes the following models:

### Farm Model

```prisma
model farm {
  id    Int     @id @default(autoincrement())
  name  String
  field field[]
}
```

### Field Model

```prisma
model field {
  id      Int     @id @default(autoincrement())
  name    String
  crop    String?
  surface Decimal @db.Decimal
  farm_id Int
  farm    farm    @relation(fields: [farm_id], references: [id], onUpdate: Restrict)
}
```

## Integration with NutriBudget Components

### Integration with Backend Services

The hasura-client module can be used in backend services to interact with the database:

```typescript
import prismaClient from '@nutriplatform/hasura-client';

// Create a service that uses the Prisma client
export class FarmService {
  private prisma;

  constructor(databaseUrl: string) {
    this.prisma = prismaClient.create(databaseUrl);
  }

  async getAllFarms() {
    return this.prisma.farm.findMany();
  }

  async getFarmById(id: number) {
    return this.prisma.farm.findUnique({
      where: { id },
      include: { field: true },
    });
  }

  // Other methods...
}
```

### Integration with Frontend

While this client is primarily designed for backend use, it's important to understand how it relates to the frontend application.

The frontend application uses the urql GraphQL client to interact with the Hasura GraphQL API:

```typescript
// Example of frontend GraphQL query
const GET_FARMS = gql`
  query getFarms {
    farm {
      id
      name
    }
  }
`;
```

The Hasura GraphQL API exposes the same data that this client accesses directly through Prisma, but with the added benefits of GraphQL such as selective field retrieval and built-in relationship handling.

### Integration with Nutrimodels

The hasura-client can be used by Nutrimodels to access and manipulate data:

```typescript
import prismaClient from '@nutriplatform/hasura-client';

export class NutrientFlowAnalysis {
  private prisma;

  constructor(databaseUrl: string) {
    this.prisma = prismaClient.create(databaseUrl);
  }

  async analyzeNutrientFlow(farmId: number) {
    const farm = await this.prisma.farm.findUnique({
      where: { id: farmId },
      include: { field: true },
    });

    // Perform nutrient flow analysis using farm data
    // ...

    return {
      farmName: farm.name,
      fieldCount: farm.field.length,
      totalSurface: farm.field.reduce((sum, field) => sum + Number(field.surface), 0),
      // Other analysis results...
    };
  }
}
```

## Development and Maintenance

### Updating the Schema

When the database schema changes, you need to update the Prisma schema:

1. Update the `schema.prisma` file in the `prisma` directory
2. Run `npx prisma generate` to regenerate the Prisma client

The module includes a `postinstall` script that automatically runs `prisma generate` when the package is installed.

### Handling Migrations

Database migrations are managed through Hasura. When the schema changes:

1. Create a new migration using the Hasura CLI
2. Apply the migration to update the database schema
3. Update the Prisma schema to reflect the changes
4. Regenerate the Prisma client

For more information on migrations, see the [Hasura Migrations Guide](../../docs/hasura/migrations-guide.md).

## Troubleshooting

### Common Issues

#### Connection Issues

If you encounter connection issues:

1. Verify that the database URL is correct
2. Check that the database is running and accessible
3. Ensure that the user has the necessary permissions

#### Type Errors

If you encounter type errors:

1. Make sure you've regenerated the Prisma client after schema changes
2. Check that you're using the correct types from the client

#### Missing Tables or Columns

If tables or columns are missing:

1. Verify that the migrations have been applied correctly
2. Check the Hasura metadata to ensure tables are exposed
3. Regenerate the Prisma client to reflect the latest schema

### Getting Help

If you encounter issues not covered here, please:

1. Check the Prisma documentation: https://www.prisma.io/docs/
2. Review the Hasura documentation: https://hasura.io/docs/latest/index/
3. Contact the NutriBudget development team for project-specific assistance

## Project Context

The hasura-client module is a key component of the NutriBudget platform, which aims to develop an integrated nutrient management platform as a decision-support tool for farmers, advisors, and policy makers. As the project evolves from the proposal phase to implementation, this module will be expanded to support additional models and functionality related to nutrient management.