# Migration Guide: 11.7.x → 11.8.x

## Overview

| Category | Details |
|----------|---------|
| **Breaking Changes** | 1 (File download endpoint) |
| **New Features** | 2 (TUS Module, CoreFileController) |
| **Bugfixes** | None |
| **Migration Effort** | ~10 minutes |

---

## Prerequisites

### Node.js Version

**Node.js >= 20.19.0 is required** for `@tus/server` support.

```bash
# Check your version
node --version

# Should output v20.19.0 or higher
```

### New Dependencies

The following packages are automatically installed with nest-server 11.8.x:

| Package | Version | Purpose |
|---------|---------|---------|
| `@tus/server` | 2.3.0 | TUS protocol server implementation |
| `@tus/file-store` | 2.0.0 | File storage backend for TUS uploads |

These are production dependencies and will be installed automatically when updating nest-server.

---

## Quick Migration

```bash
# Update package
npm install @lenne.tech/nest-server@11.8.x

# Install new TUS dependencies (automatically included)
npm install

# Verify build
npm run build

# Run tests
npm test
```

**Important:** If your project uses file downloads, see [Breaking Changes](#breaking-changes) below.

---

## What's New in 11.8.x

### 1. TUS Module (Resumable Uploads)

TUS is **enabled by default** - no configuration required! The module provides resumable file uploads using the [tus.io](https://tus.io) protocol.

**Endpoints (automatically available):**

| Method | Endpoint | Description |
|--------|----------|-------------|
| OPTIONS | `/tus` | Get server capabilities |
| POST | `/tus` | Create new upload |
| HEAD | `/tus/:id` | Get upload status |
| PATCH | `/tus/:id` | Continue upload |
| DELETE | `/tus/:id` | Terminate upload |

**Default Configuration:**
```typescript
{
  enabled: true,
  path: '/tus',
  maxSize: 50 * 1024 * 1024 * 1024, // 50 GB
  expiration: { expiresIn: '24h' },
}
```

> **Note:** `@tus/server` already includes all TUS protocol headers (Authorization, Content-Type, Tus-Resumable, Upload-Length, Upload-Metadata, Upload-Offset, etc.). The `allowedHeaders` option is only for project-specific custom headers.

**Add custom headers (if needed):**
```typescript
// config.env.ts
tus: {
  allowedHeaders: ['X-Custom-Header'], // Only additional project-specific headers
}
```

**Disable TUS (if needed):**
```typescript
// server.module.ts
TusModule.forRoot({ config: false })
```

**Client Usage:**
```typescript
import { Upload } from 'tus-js-client';

const upload = new Upload(file, {
  endpoint: 'http://localhost:3000/tus',
  metadata: { filename: file.name, filetype: file.type },
  onSuccess: () => console.log('Upload complete!'),
});
upload.start();
```

### 2. CoreFileController (Public Download Endpoints)

New abstract controller providing public file download endpoints:

| Endpoint | Description | Permission |
|----------|-------------|------------|
| `GET /files/id/:id` | Download by ID | S_EVERYONE |
| `GET /files/:filename` | Download by filename | S_EVERYONE |

Projects extending `CoreFileController` automatically get these endpoints.

---

## Breaking Changes

### Change 1: File Download Endpoint Pattern

The file download by ID endpoint has changed from `/files/:id` to `/files/id/:id`.

**Before (11.7.x):**
```typescript
// FileController with custom download endpoint
@Get(':id')
@Roles(RoleEnum.ADMIN)
async getFile(@Param('id') id: string, @Res() res: Response) { }

// Client usage
GET /files/abc123  → Downloads file by ID (admin only)
```

**After (11.8.x):**
```typescript
// FileController extends CoreFileController
export class FileController extends CoreFileController {
  constructor(protected override readonly fileService: FileService) {
    super(fileService);
  }
  // Inherited: GET /files/id/:id (public)
  // Inherited: GET /files/:filename (public)
}

// Client usage
GET /files/id/abc123  → Downloads file by ID (public)
GET /files/example.pdf  → Downloads file by filename (public)
```

**Migration Steps:**

1. **Update FileController** to extend `CoreFileController`:

```typescript
// src/server/modules/file/file.controller.ts
import { Controller, Delete, Get, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { CoreFileController, Roles, RoleEnum } from '@lenne.tech/nest-server';
import { FileService } from './file.service';

@Controller('files')
@Roles(RoleEnum.ADMIN)
export class FileController extends CoreFileController {
  constructor(protected override readonly fileService: FileService) {
    super(fileService);
  }

  // Keep your admin-only endpoints (upload, info, delete)
  @Post('upload')
  @Roles(RoleEnum.ADMIN)
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(@UploadedFile() file: Express.Multer.File) { /* ... */ }

  @Get('info/:id')
  @Roles(RoleEnum.ADMIN)
  async getFileInfo(@Param('id') id: string) { /* ... */ }

  @Delete(':id')
  @Roles(RoleEnum.ADMIN)
  async deleteFile(@Param('id') id: string) { /* ... */ }

  // REMOVE your old getFile() method - CoreFileController handles downloads
}
```

2. **Update client-side download URLs:**

```typescript
// Before
const downloadUrl = `/files/${fileId}`;

// After
const downloadUrl = `/files/id/${fileId}`;
// Or by filename:
const downloadUrl = `/files/${filename}`;
```

3. **Optional: Restrict download access** (if you need authentication):

```typescript
@Controller('files')
@Roles(RoleEnum.ADMIN)
export class FileController extends CoreFileController {
  // Override to require authentication
  @Get('id/:id')
  @Roles(RoleEnum.S_USER)  // Require logged-in user
  override async getFileById(@Param('id') id: string, @Res() res: Response) {
    return super.getFileById(id, res);
  }

  @Get(':filename')
  @Roles(RoleEnum.S_USER)
  override async getFile(@Param('filename') filename: string, @Res() res: Response) {
    return super.getFile(filename, res);
  }
}
```

---

## Compatibility Notes

### Pattern: Custom FileController without CoreFileController

If you want to keep the old behavior exactly:

```typescript
// This still works - don't extend CoreFileController
@Controller('files')
@Roles(RoleEnum.ADMIN)
export class FileController {
  constructor(private readonly fileService: FileService) {}

  @Get(':id')
  @Roles(RoleEnum.ADMIN)
  async getFile(@Param('id') id: string, @Res() res: Response) {
    // Your existing implementation
  }
}
```

### Pattern: TUS with Authentication

By default, TUS allows everyone to upload. To require authentication:

```typescript
// src/server/modules/tus/tus.controller.ts
import { Controller } from '@nestjs/common';
import { CoreTusController, Roles, RoleEnum } from '@lenne.tech/nest-server';

@Controller('tus')
@Roles(RoleEnum.S_USER)  // Require logged-in user
export class TusController extends CoreTusController {}

// server.module.ts
TusModule.forRoot({ controller: TusController })
```

---

## Troubleshooting

### Download returns 404 after migration

**Cause:** Using old endpoint pattern `/files/:id` instead of `/files/id/:id`

**Solution:** Update client to use `/files/id/:id` or `/files/:filename`

### TUS uploads not working

**Cause:** TUS might be disabled in config

**Solution:** Check that `tus: false` is not set in your config. TUS is enabled by default.

### TypeScript error: "must have an 'override' modifier"

**Cause:** `fileService` in constructor needs `override` when extending CoreFileController

**Solution:**
```typescript
// Add 'override' keyword
constructor(protected override readonly fileService: FileService) {
  super(fileService);
}
```

---

## Module Documentation

### TUS Module

- **README:** [src/core/modules/tus/README.md](../src/core/modules/tus/README.md)
- **Integration Checklist:** [src/core/modules/tus/INTEGRATION-CHECKLIST.md](../src/core/modules/tus/INTEGRATION-CHECKLIST.md)
- **Reference Implementation:** `src/server/server.module.ts`

### File Module

- **README:** [src/core/modules/file/README.md](../src/core/modules/file/README.md)
- **Reference Implementation:** `src/server/modules/file/file.controller.ts`

---

## References

- [TUS Protocol](https://tus.io/protocols/resumable-upload)
- [tus-js-client](https://github.com/tus/tus-js-client)
- [@tus/server](https://github.com/tus/tus-node-server)
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
