# Usage Guide

## 📖 Usage Guide

### Basic Query Operations

#### Filtering and Selection

```typescript
// Simple where clause
const activeTests = await repository.test.Where({ isActive: true }).ToArray();

// 🌟 FEATURED: AsQueryable uses Prisma query syntax for database-level operations
const queryableResults = await repository.test
    .AsQueryable()
    .Where({
        isActive: true,
        description: { not: null },
        createdAt: { gte: new Date('2024-01-01') },
    })
    .Select({
        id: true,
        name: true,
        description: true,
    })
    .OrderBy({ name: 'asc' })
    .Take(10)
    .ToArrayAsync();

// 🔗 LINQ-style operations require ToEnumerable() for in-memory processing
const linqTransformations = await repository.test
    .Where({ isActive: true })
    .ToEnumerable()
    .Where((test) => test.description != null)
    .Select((test) => ({
        id: test.id,
        name: test.name,
        description: test.description,
        displayName: `${test.name} - ${test.description}`,
        category: test.name.length > 10 ? 'Long' : 'Short',
    }))
    .OrderBy((item) => item.displayName)
    .ToArray();

// Prisma-style field selection with OrderBy
const fieldSelection = await repository.test
    .Where({
        isActive: true,
        createdAt: { gte: new Date('2024-01-01') },
    })
    .Select({
        id: true,
        name: true,
        description: true,
        createdAt: true,
    })
    .OrderBy({ createdAt: 'desc' })
    .Take(10)
    .ToArray();

// 🆕 Advanced Select with nested relations and type safety
const relationData = await repository.test
    .Select<TestWithCategory>({
        createdAt: true,
        description: true,
        id: true,
        isActive: true,
        name: true,
        category: {
            select: {
                id: true,
                name: true,
                description: true,
            },
        },
    })
    .Where({
        isActive: {
            equals: true,
        },
        category: {
            isNot: null,
        },
    })
    .OrderBy({ createdAt: 'desc' })
    .ToArray();

// Complex nested selection with multiple relations
const complexSelection = await repository.user
    .Select<UserWithPostsAndProfile>({
        id: true,
        name: true,
        email: true,
        profile: {
            select: {
                bio: true,
                avatar: true,
                location: true,
            },
        },
        posts: {
            select: {
                id: true,
                title: true,
                publishedAt: true,
                category: {
                    select: {
                        name: true,
                    },
                },
            },
            where: {
                published: true,
            },
            orderBy: {
                publishedAt: 'desc',
            },
            take: 5,
        },
    })
    .Where({
        isActive: true,
        posts: {
            some: {
                published: true,
            },
        },
    })
    .OrderBy({ name: 'asc' })
    .ToArray();
    .Select({
        id: true,
        name: true,
        description: true,
        createdAt: true,
    })
    .OrderBy({ createdAt: 'desc' })
    .Take(10)
    .ToArray();

// Advanced LINQ transformations with computed fields
const enrichedData = await repository.test
    .Where({ isActive: true })
    .ToEnumerable()
    .Where((test) => test.description != null)
    .Select((test) => ({
        id: test.id,
        name: test.name,
        description: test.description,
        displayName: `${test.name} - ${test.description || 'No description'}`,
        shortName: test.name.substring(0, 10),
        hasDescription: test.description !== null,
        formattedDate: test.createdAt.toISOString().split('T')[0],
    }))
    .OrderBy((item) => item.displayName)
    .ThenBy((item) => item.id)
    .ToArray();

// Combining database and in-memory operations for complex transformations
const processedTests = await repository.test
    .Where({ isActive: true })
    .ToEnumerable(); // Fetch from database

const finalResults = processedTests
    .Where((test) => test.description != null)
    .Select((test) => ({
        id: test.id,
        name: test.name.toUpperCase(),
        description: test.description,
        category: test.name.length > 10 ? 'Long' : 'Short',
        hasDescription: test.description != null,
    }))
    .OrderBy((test) => test.category)
    .ThenBy((test) => test.name)
    .ThenByDescending((test) => test.id)
    .ToArray();

// Multiple OrderBy examples - LINQ-style sorting with computed fields
const sortingExamples = await repository.test
    .Where({ isActive: true })
    .ToEnumerable()
    .Select((test) => ({
        id: test.id,
        name: test.name,
        description: test.description,
        priority: test.name.length, // Example computed field
    }))
    .OrderBy((item) => item.priority) // Primary sort
    .ThenBy((item) => item.name) // Secondary sort (ascending)
    .ThenByDescending((item) => item.id) // Tertiary sort (descending)
    .ToArray();
```

### 🔗 GraphQL Data Source Examples

```typescript
// Querying with GraphQL data source using the new async methods
const gqlResults = await repository.test
    .Where({ isActive: true })
    .Select({
        id: true,
        name: true,
        description: true,
    })
    .OrderBy({ name: 'asc' })
    .ToArrayAsync();

// Using LINQ operations with GraphQL and async enumerables
const linqGqlResults = await repository.test
    .Where({ isActive: true })
    .ToAsyncEnumerable()
    .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();

// Mixed operations: start with GraphQL, transform with LINQ
const mixedResults = await repository.test
    .model('test') // Use .model() for fresh builder instances
    .Where({ isActive: true })
    .ToAsyncEnumerable()
    .Where((test) => test.name.length > 5)
    .Select((test) => ({
        ...test,
        category: test.name.length > 10 ? 'Long Name' : 'Short Name',
        priority: test.description ? 'High' : 'Low',
    }))
    .GroupBy((item) => item.category)
    .Select((group) => ({
        category: group.key,
        count: group.count(),
        items: group.toArray(),
    }))
    .ToArray();
```

> **Note**: Transaction support is available only with Prisma ORM data sources. GraphQL data sources do not support transactional operations due to the stateless nature of GraphQL APIs.

## Next Steps

- [Learn about LINQ operations](./linq-operations.md)
- [Explore the Universal Repository Pattern](./repository-pattern.md)
- [See performance benchmarks](./performance.md)
