# Migration Guide: 11.14.x → 11.15.0

## Overview

| Category | Details |
|----------|---------|
| **Breaking Changes** | `IServerOptions.graphQl` type changed from `object \| undefined` to `false \| object \| undefined` (TypeScript only — runtime is backward compatible) |
| **New Features** | Disable GraphQL entirely via `graphQl: false`, test artifact cleanup script |
| **Bugfixes** | None |
| **Migration Effort** | Minimal (~1 minute) — update package and verify build |

---

## Quick Migration

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

# Verify build
npm run build

# Run tests
npm test
```

---

## What's New in 11.15.0

### 1. Disable GraphQL (`graphQl: false`)

Projects that only need REST endpoints (e.g. pure API backends, microservices) can now completely disable GraphQL by setting `graphQl: false` in the configuration.

**What gets disabled:**
- `GraphQLModule` is not imported (no `/graphql` endpoint)
- `ComplexityPlugin` is not registered
- `graphqlUploadExpress()` middleware is not applied
- No Apollo Server startup overhead

**What stays active:**
- MongoDB / Mongoose
- All REST controllers and middleware
- BetterAuth (if configured)
- Email, Template, Config services
- All other core modules (File, HealthCheck, SystemSetup, etc.)

**Usage:**

```typescript
// config.env.ts
const config: Partial<IServerOptions> = {
  // ... other config

  // Disable GraphQL entirely
  graphQl: false,
};
```

**Works with all CoreModule.forRoot signatures:**

```typescript
// 1-param (IAM-only)
CoreModule.forRoot({ ...config, graphQl: false })

// 3-param (Legacy + IAM)
CoreModule.forRoot(CoreAuthService, AuthModule.forRoot(jwt), { ...config, graphQl: false })
```

**Default behavior (no change needed):**

```typescript
// GraphQL is enabled by default — these are equivalent:
CoreModule.forRoot(config)                          // graphQl: undefined → enabled
CoreModule.forRoot({ ...config, graphQl: {} })      // explicit empty config → enabled
CoreModule.forRoot({ ...config, graphQl: { ... } }) // with options → enabled
```

### 2. Test Artifact Cleanup Script

New npm script to remove leftover `.txt` and `.bin` files from the `tests/` directory that can remain after failed file upload or TUS upload tests:

```bash
npm run test:cleanup
```

**Affected files:**
- `tests/*.txt` — file upload test artifacts
- `tests/stories/*.txt` — TUS upload test text files
- `tests/stories/*.bin` — TUS upload test binary files

This script is safe — it only deletes `.txt` and `.bin` files within the `tests/` directory tree and preserves `.gitkeep` files.

### 3. `.gitignore` Updated

Added `tests/**/*.bin` to `.gitignore` to prevent accidental commits of binary test artifacts (e.g. the 100KB `test-tus-upload-large.bin` from TUS tests).

---

## Breaking Changes

### TypeScript Interface Change: `IServerOptions.graphQl`

The `graphQl` property type in `IServerOptions` changed from:

```typescript
// Before (11.14.x)
graphQl?: {
  driver?: ApolloDriverConfig;
  enableSubscriptionAuth?: boolean;
  maxComplexity?: number;
  options?: GqlModuleAsyncOptions;
};
```

To:

```typescript
// After (11.15.0)
graphQl?:
  | false
  | {
      driver?: ApolloDriverConfig;
      enableSubscriptionAuth?: boolean;
      maxComplexity?: number;
      options?: GqlModuleAsyncOptions;
    };
```

**Impact:** This is a **TypeScript-only** breaking change. The union type `false | { ... }` is a widening change — all existing configurations remain valid without modification. However, code that directly accesses `config.graphQl.driver` without checking for `false` first may now show TypeScript errors.

**If you access `graphQl` properties directly:**

```typescript
// Before — may now show TS error: "Property 'driver' does not exist on type 'false'"
const driver = config.graphQl?.driver;

// After — add type narrowing
const driver = typeof config.graphQl === 'object' ? config.graphQl?.driver : undefined;

// Or simpler:
const driver = config.graphQl && config.graphQl !== false ? config.graphQl.driver : undefined;
```

**If you only pass config to CoreModule.forRoot():** No changes needed.

---

## Detailed Migration Steps

### Step 1: Update Package

```bash
npm install @lenne.tech/nest-server@11.15.0
```

### Step 2: Check TypeScript Compilation

```bash
npm run build
```

If you get TypeScript errors related to `graphQl` property access, add type narrowing as shown above.

### Step 3: Adopt New Features (Optional)

#### Disable GraphQL for REST-only projects

```typescript
// config.env.ts
graphQl: false,
```

#### Use test cleanup script

```bash
npm run test:cleanup
```

### Step 4: Run Tests

```bash
npm test
```

---

## Compatibility Notes

### Existing Projects (No Action Required)

Projects that don't set `graphQl: false` are completely unaffected. GraphQL remains enabled by default when `graphQl` is `undefined` or an object.

### Projects Using `graphQl` Config

If your project configures GraphQL options:

```typescript
// This still works exactly as before
graphQl: {
  maxComplexity: 100,
  enableSubscriptionAuth: true,
}
```

### BetterAuth Without GraphQL

When using `graphQl: false` with BetterAuth, the BetterAuth REST endpoints (`/iam/*`) continue to work. Only GraphQL resolvers and subscriptions are disabled.

### Test Cleanup Script

The `test:cleanup` script is available in nest-server itself. Consuming projects with similar file upload tests may want to add a similar script to their own `package.json`.

---

## Troubleshooting

### TypeScript Error: "Property does not exist on type 'false'"

**Cause:** Code accesses `config.graphQl?.someProperty` without narrowing the union type.

**Solution:** Add a type check:
```typescript
if (config.graphQl && config.graphQl !== false) {
  // Safe to access config.graphQl.driver etc.
}
```

### GraphQL Endpoint Returns 404 After Setting `graphQl: false`

**Cause:** This is the intended behavior. Setting `graphQl: false` removes the `/graphql` endpoint entirely.

**Solution:** Remove `graphQl: false` from config to re-enable GraphQL.

### Resolvers/Mutations Not Found After Setting `graphQl: false`

**Cause:** GraphQL resolvers require the GraphQLModule. With `graphQl: false`, no resolvers are registered.

**Solution:** Use REST controllers for API endpoints when GraphQL is disabled.

---

## Module Documentation

### CoreModule (Updated)

- **Key File:** [src/core.module.ts](../src/core.module.ts)
- **Interface:** [src/core/common/interfaces/server-options.interface.ts](../src/core/common/interfaces/server-options.interface.ts)
- **Changes:**
  - `graphQl: false` support in `forRoot()` — skips GraphQLModule import, ComplexityPlugin, and upload middleware
  - Static `graphQlEnabled` flag controls middleware registration in `configure()`
  - Type-safe `graphQlOpts` extraction in all three GraphQL driver builders

---

## References

- [IServerOptions Interface](../src/core/common/interfaces/server-options.interface.ts) — Updated `graphQl` type definition
- [CoreModule](../src/core.module.ts) — Implementation of `graphQl: false` support
- [Unit Tests](../tests/unit/core-module-signatures.spec.ts) — Tests for all `graphQl: false` scenarios
- [Configurable Features Pattern](../.claude/rules/configurable-features.md) — Configuration patterns used
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) — Reference implementation
