# Quick Setup Guide

## 🛠️ Quick Setup Guide

### Step 1: Define Your Prisma Schema

Create or update your `prisma/schema.prisma` file:

```prisma
generator client {
  provider = "prisma-client-js"
  output   = "../generated/prisma"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model Test {
  id          Int      @id @default(autoincrement())
  name        String
  description String?
  isActive    Boolean  @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model User {
  id       Int      @id @default(autoincrement())
  email    String   @unique
  name     String?
  age      Int?
  isActive Boolean  @default(true)
  posts    Post[]
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  content  String?
  userId   Int
  user     User   @relation(fields: [userId], references: [id])
}
```

### Step 2: Configure the Module

Set up the `PrismaCoreModule` in your NestJS application:

```typescript
import { Module } from '@nestjs/common';
import { PrismaClient } from '../generated/prisma';
import { PrismaCoreModule } from '@algochad/prisma-core';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

const PRISMA_CLIENT_PROVIDER = {
    provide: 'PRISMA_CLIENT',
    useFactory: () => new PrismaClient(),
};

@Module({
    imports: [
        PrismaCoreModule.forRoot({
            prismaClientProvider: PRISMA_CLIENT_PROVIDER,
        }),
    ],
    controllers: [AppController],
    providers: [AppService, AppRepository],
})
export class AppModule {}
```

### Alternative: GraphQL Setup

For GraphQL data sources, configure your GraphQL client and use the GraphQL repository:

```typescript
import { Module } from '@nestjs/common';
import { createClient } from '../generated/graphql';
import { PrismaCoreModule } from '@algochad/prisma-core';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

const GRAPHQL_CLIENT_PROVIDER = {
    provide: 'GRAPHQL_CLIENT',
    useFactory: () =>
        createClient({
            url: 'http://localhost:4000/graphql', // Your GraphQL endpoint
        }),
};

@Module({
    imports: [
        PrismaCoreModule.forRoot({
            graphqlClientProvider: GRAPHQL_CLIENT_PROVIDER,
        }),
    ],
    controllers: [AppController],
    providers: [AppService, AppRepository],
})
export class AppModule {}
```

> **Note**: When using GraphQL as a data source, ensure your GraphQL schema matches your Prisma models for seamless type compatibility and LINQ operations.

### Step 3: Create Your Repository

Create a typed repository with full type safety:

```typescript
import { Injectable } from '@nestjs/common';
import { Prisma, Test, User, Post } from '../generated/prisma';
import {
    PrismaCoreService,
    PrismaRepository,
    PrismaUnifiedBuilder,
} from '@algochad/prisma-core';

@Injectable()
export class AppRepository extends PrismaRepository {
    constructor(databaseService: PrismaCoreService) {
        super(databaseService);
    }

    // Typed accessor for Test model
    get test(): PrismaUnifiedBuilder<
        Test,
        Test,
        Prisma.TestWhereInput,
        Prisma.TestOrderByWithRelationInput,
        Prisma.TestInclude,
        Prisma.TestSelect,
        Prisma.TestCreateInput,
        Prisma.TestUpdateInput,
        Prisma.TestWhereUniqueInput
    > {
        return this.model<Test>('test') as any;
    }

    // Typed accessor for User model
    get user(): PrismaUnifiedBuilder<
        User,
        User,
        Prisma.UserWhereInput,
        Prisma.UserOrderByWithRelationInput,
        Prisma.UserInclude,
        Prisma.UserSelect,
        Prisma.UserCreateInput,
        Prisma.UserUpdateInput,
        Prisma.UserWhereUniqueInput
    > {
        return this.model<User>('user') as any;
    }

    // Typed accessor for Post model
    get post(): PrismaUnifiedBuilder<
        Post,
        Post,
        Prisma.PostWhereInput,
        Prisma.PostOrderByWithRelationInput,
        Prisma.PostInclude,
        Prisma.PostSelect,
        Prisma.PostCreateInput,
        Prisma.PostUpdateInput,
        Prisma.PostWhereUniqueInput
    > {
        return this.model<Post>('post') as any;
    }
}
```

#### Alternative: GraphQL Repository

For GraphQL data sources, extend `GraphQLRepository` and use the `.model()` method:

```typescript
import { Injectable } from '@nestjs/common';
import { Test, User, Post } from '../generated/graphql/types';
import {
    PrismaCoreService,
    GraphQLRepository,
    GraphQLQueryBuilder,
} from '@algochad/prisma-core';

@Injectable()
export class AppRepository extends GraphQLRepository {
    constructor(databaseService: PrismaCoreService) {
        super(databaseService);
    }

    // Typed accessor for Test model via GraphQL
    get test(): GraphQLQueryBuilder<Test> {
        return this.model<Test>('test');
    }

    // Typed accessor for User model via GraphQL
    get user(): GraphQLQueryBuilder<User> {
        return this.model<User>('user');
    }

    // Typed accessor for Post model via GraphQL
    get post(): GraphQLQueryBuilder<Post> {
        return this.model<Post>('post');
    }
}
```

### Step 4: Use in Your Service

Inject and use the repository in your services:

```typescript
import { Injectable } from '@nestjs/common';
import { AppRepository } from './app.repository';

@Injectable()
export class AppService {
    constructor(private readonly repository: AppRepository) {}

    // Simple query example
    async getActiveTests() {
        return await this.repository.test
            .Where({ isActive: true })
            .OrderBy({ createdAt: 'desc' })
            .ToArray();
    }

    // Complex query with LINQ operations
    async getTestsWithTransformation() {
        const tests = await this.repository.test
            .Where({ isActive: true })
            .ToEnumerable();

        return tests
            .Where((test) => test.description != null)
            .Select((test) => ({
                id: test.id,
                displayName: test.name.toUpperCase(),
                summary: `${test.name}: ${test.description}`,
                hasDescription: true,
            }))
            .OrderBy((item) => item.displayName)
            .ToArray();
    }
}
```

#### GraphQL Service Examples

For GraphQL data sources, the same LINQ patterns work seamlessly:

```typescript
import { Injectable } from '@nestjs/common';
import { AppRepository } from './app.repository';

@Injectable()
export class AppService {
    constructor(private readonly repository: AppRepository) {}

    // GraphQL query with LINQ-style operations
    async getActiveTestsFromGraphQL() {
        return await this.repository.test
            .Where({ isActive: true })
            .Select({
                id: true,
                name: true,
                description: true,
            })
            .OrderBy({ name: 'asc' })
            .ToArrayAsync();
    }

    // Complex GraphQL query with transformations
    async getGraphQLTestsWithTransformation() {
        const tests = await this.repository.test
            .Where({ isActive: true })
            .ToAsyncEnumerable();

        return tests
            .Where((test) => test.description != null)
            .Select((test) => ({
                id: test.id,
                displayName: test.name.toUpperCase(),
                summary: `${test.name}: ${test.description}`,
                hasDescription: true,
            }))
            .OrderBy((item) => item.displayName)
            .ToArray();
    }
}
```

## Next Steps

- [Learn about Select & OrderBy patterns](./quick-start-patterns.md)
- [Explore LINQ operations](./linq-operations.md)
- [Understand the Universal Repository Pattern](./repository-pattern.md)
