bootgs-validation · v1.0.0 · 2026-09-13 · sha256 db6e31e40dabf432

bootgs-validation v1.0.0A

Immutable. This exact content is served forever at /api/v1/blob/db6e31e40dabf432.

---
name: bootgs-validation
description: Documents bootgs' parameter-level validation decorators (@Min, @Max, @Email, @Pattern, @Size, @NotBlank, @NotEmpty, @AssertTrue, @AssertFalse, @Positive, @PositiveOrZero, @Negative, @NegativeOrZero), the built-in Parse pipes, and how to write custom pipes with @UsePipes. Use when adding input validation or type coercion to a bootgs controller method, or when invalid input reaches a handler unrejected.
license: Apache-2.0
metadata:
  author: Maksym Stoianov
  version: "1.0.0"
  framework: bootgs
---

# Bootgs Validation

## Available files

- **`references/decorators-and-pipes.md`** — full list of validation decorators and Parse pipes. Load it when you need to check whether a specific constraint exists or what a pipe coerces to; the pattern for using them is below.

## Model

bootgs validates individual **parameters**, not whole DTO classes — there is no class-validator-style `@ValidateNested`/decorated-DTO pipeline. A validation decorator stacks on top of an extraction decorator (`@Query`, `@Param`, `@Body`) and runs against the already-extracted value before the handler body executes:

```ts
@Get()
findAll(
  @Query("page") @Min(1) page: number,
  @Query("limit") @Max(100) limit: number,
) { /* page and limit are guaranteed valid here */ }
```

Multiple validators stack freely on one parameter; each runs in decorator-application order. The available decorators — `@Min`, `@Max`, `@Email`, `@Pattern`, `@Size`, `@NotBlank`, `@NotEmpty`, `@AssertTrue`/`@AssertFalse`, `@Positive`/`@PositiveOrZero`, `@Negative`/`@NegativeOrZero` — are listed with their exact checks in `references/decorators-and-pipes.md`.

## Parse pipes (extraction-time coercion)

GAS delivers every parameter as a string. Use a Parse pipe as the **second argument** to `@Param`/`@Query` to coerce it before your handler sees it — don't hand-parse `Number(value)` in the handler body:

```ts
@Get("{id}")
findOne(@Param("id", ParseNumberPipe) id: number) { /* id is a number, not "42" */ }
```

Six are available (`ParseIntPipe`, `ParseFloatPipe`, `ParseBigIntPipe`, `ParseBooleanPipe`, `ParseNumberPipe`, `ParseStringPipe`) — see `references/decorators-and-pipes.md` for what each coerces to.

## Custom pipes

```ts
import { PipeTransform, ArgumentMetadata, UsePipes } from "bootgs";

class TrimPipe implements PipeTransform<string, string> {
  transform(value: string, metadata: ArgumentMetadata): string {
    return value.trim();
  }
}

@UsePipes(TrimPipe)
@Post()
create(@Body("name") name: string) { /* name is trimmed */ }
```

`@UsePipes` applies at the class or method level and accepts multiple pipes, run in order.

## Gotcha: validation failures throw a bare `Error`, not `HttpException`

Every built-in validation decorator throws `new Error("Validation failed (...)")` on failure — **not** `AppException`/`HttpException`. If your `@ControllerAdvice`/`@ExceptionHandler` only catches `AppException`, a validation failure falls through as an unhandled 500 instead of a clean 400. Handle it explicitly:

```ts
@ControllerAdvice()
class GlobalExceptionHandler {
  @ExceptionHandler(Error)
  handleValidation(err: Error) {
    return ResponseEntity.badRequest().body({ message: err.message });
  }
}
```

Order `@ExceptionHandler` registrations from most-specific to least-specific (`AppException` before the generic `Error` catch-all) if you need different status codes for domain exceptions versus validation failures.

## Verification

For each validation decorator you add, write one test that calls the handler with a value that should fail and assert the response status/message — a decorator with no corresponding negative test is unverified surface area, since bootgs doesn't type-check the constraint against the parameter's type at compile time (e.g. `@Email()` on a `number` parameter compiles fine and fails at runtime).