Skip to main content
Version: 4.0.0-preview

Release Notes

See the upgrade guide for migration instructions.

What's New in 4.0

FeatureDescription
InterceptorsAOP system with conditional execution
Testing ModuleZero-config test utilities
Event SystemType-safe events with auto-discovery
Lazy-LoadingOn-demand module loading
ConfigurationType-safe config with validation
Logging11-phase logging system with transports
AuthorizationGuards with permission hierarchy
StudioLocal developer experience platform: request timeline, architecture map, live logs, error inspector, security view

Versioning Scheme

ExpressoTS follows Semantic Versioning:

  • Major: Breaking changes (roughly yearly)
  • Minor: New features (bi-weekly / monthly)
  • Patch: Bug fixes (as needed)

Releases are bundled. All packages share the same version number:

  • @expressots/core
  • @expressots/adapter-express
  • @expressots/shared
  • @expressots/templates
  • @expressots/cli
  • @expressots/studio
  • @expressots/studio-agent

Support Policy

Starting with v4.0.0, every major release receives 24 months of bug fixes and security patches from its release date. Releases on the v3.x line and earlier follow the prior 18-month policy. Enterprise customers with support contracts receive extended support.

VersionNode.jsReleaseBug & Security fixed untilStatus
4.0.0>= 20.18.0May 2026May 2028🟢
3.0.0>= 20.18.0December 2024December 2026🟡
2.0.0>= 18.10.0September 2023March 2025🔴

🟢 Active support 🟡 Bug & Security fixes only 🔴 End-of-life

v3.0.0 was originally on the 18-month policy. With v4.0.0 we extended the v3 window by 6 months so users have a smooth transition runway through the rest of 2026.

ExpressoTS 4.0

Version 4.0.0 introduces significant features and architectural improvements.

Nodejs version

ExpressoTS v4.0.0 requires Node.js version 20.18.0 or higher.

Core Features

1. Interceptors System

AOP system for cross-cutting concerns:

  • whenInterceptor(), unlessInterceptor() for conditional execution
  • Auto-discovery via @provide() + @UseInterceptors()
  • Composition: pipeInterceptors(), combineInterceptors()
  • Built-in: PerformanceInterceptor, LoggingInterceptor, TimeoutInterceptor
import {
UseInterceptors,
PerformanceInterceptor,
whenInterceptor,
} from "@expressots/core";

@controller("/users")
export class UserController {
@Get("/")
@UseInterceptors(
PerformanceInterceptor,
whenInterceptor(
(ctx) => ctx.request.headers["x-cache"] === "true",
CacheInterceptor,
),
)
getUsers() {
return this.userService.findAll();
}
}

2. Testing Module

Testing utilities for unit, integration, and E2E:

  • createTestApp() for zero-config test setup
  • mockProvider() with dependency auto-suggestion
  • Fluent HTTP testing API
  • Snapshot testing with snapshotRequest()
  • Load testing with percentile metrics
  • Database fixtures with createTestDatabase()
import { createTestApp, request } from "@expressots/core";

describe("UserController", () => {
const { app, container } = await createTestApp(App);

test("GET /users returns user list", async () => {
await request(app)
.get("/users")
.expectStatus(200)
.expectBody<User[]>((users) => users.length > 0)
.expectTime({ lessThan: 100 });
});
});

3. Event System

Type-safe events for decoupled architecture:

  • Event classes with full TypeScript inference
  • Auto-discovery via @OnEvent() decorator
  • Priority-based handler execution
  • Conditional handlers with @When()
  • Event recording and replay
  • Flow visualization
// Type-safe event class
export class UserCreatedEvent {
constructor(
public readonly userId: string,
public readonly email: string,
) {}
}

// Auto-discovered handler
@provide(SendWelcomeEmailHandler)
@OnEvent(UserCreatedEvent, { priority: 1 })
export class SendWelcomeEmailHandler implements IEventHandler<UserCreatedEvent> {
handle(event: UserCreatedEvent) {
// Full TypeScript inference on event payload
this.emailService.sendWelcome(event.email);
}
}

4. Lazy-Loading Modules

Performance optimization for large applications:

  • On-demand module loading
  • Auto-detection of lazy-loadable modules
  • Preloading hints for critical modules
  • Progressive startup cost distribution
import { LazyModule } from "@expressots/core";

// Module only loaded when /admin routes are accessed
@LazyModule({ preload: false })
export class AdminModule {
// Heavy admin functionality loaded on demand
}

5. Enhanced Configuration

Type-safe configuration with validation:

  • Full TypeScript inference
  • Detailed validation error messages
  • Automatic environment switching
  • SecretValue for secure handling
import { defineConfig, Env } from "@expressots/core";

export default defineConfig({
database: {
url: Env.string("DATABASE_URL").required(),
pool: Env.number("DB_POOL_SIZE").default(10),
},
features: {
caching: Env.boolean("ENABLE_CACHE").default(true),
},
});

Enhanced Logging System

11-phase production logging:

FeatureDescription
Log LevelsTRACE, DEBUG, INFO, WARN, ERROR, FATAL
Structured LoggingObjects and metadata with formatting
Context ManagementwithContext() and child()
File TransportDaily rotating files, JSON in production
Log QueryingIn-memory buffer with query API
ExportMarkdown export with statistics
RedactionAutomatic sensitive data masking
Flow VisualizationVisual log flow representation
TransportsConsole, File, Custom
import { Logger, LogLevel, FileTransport } from "@expressots/core";

logger.configure({
level: LogLevel.DEBUG,
transports: [FileTransport.daily({ directory: "logs" })],
});

// Query logs
const errors = logger
.query()
.level(LogLevel.ERROR)
.context("UserService")
.search("authentication")
.execute();

// Export to markdown
const report = logger.exportLogsToMarkdown({
query: { level: LogLevel.ERROR },
groupBy: "level",
});

Content Negotiation

RFC 7231 compliant format negotiation:

  • Formats: JSON, XML, CSV, YAML, Plain Text
  • Quality value support
  • @Consumes() and @Produces() decorators
  • Automatic format selection from Accept headers
import { provide } from "@expressots/core";
import { controller, Get, Produces } from "@expressots/adapter-express";

@provide(UsersController)
@controller("/users")
export class UsersController {
@Get("/")
@Produces("application/json", "application/xml", "text/csv")
getUsers() {
return this.userService.findAll();
}
}

Smart Validation System

TypeScript-first validation with a pluggable adapter registry:

  • Built-in adapters for class-validator, Zod, and Yup (all opt-in via validationRegistry)
  • Smart field detection (email, phone, URL, UUID)
  • Helpful error messages with examples
  • Custom adapters via IValidationAdapter
import { provide, validationRegistry, createZodValidator } from "@expressots/core";
import { controller, Post, validatedBody } from "@expressots/adapter-express";
import { z } from "zod";

validationRegistry.register(createZodValidator());

const CreateUser = z.object({
name: z.string(),
email: z.string().email(),
password: z.string().min(8),
});

@provide(UsersController)
@controller("/users")
export class UsersController {
@Post("/")
createUser(@validatedBody(CreateUser) data: z.infer<typeof CreateUser>) {
return this.userService.create(data);
}
}

See the Validation guide for class-validator and Yup variants.

Health Monitoring

Application health monitoring is built-in at three layers: middleware pipeline, IHealthCheck providers, and an aggregated dashboard. Full deep-dive in the Health & Monitoring guide.

import { AppExpress } from "@expressots/adapter-express";

export class App extends AppExpress {
async configureServices() {
this.Middleware.applyPreset("api");
this.Middleware.addHealthCheck({ path: "/health/middleware", includeMetrics: true });
}
}

Any provider implementing IHealthCheck is auto-discovered and aggregated by ProviderRegistry.checkHealth() so you can expose GET /health from your own controller.

Custom Scopes

Advanced DI scopes:

  • Tenant, Transaction, Workflow, Session scopes
  • Complete isolation between contexts
  • Manual lifecycle control
import { provideInScope } from "@expressots/core";

@provideInScope(TenantConfigService, "tenant")
export class TenantConfigService {
// Instance shared within tenant, isolated between tenants
}

API Versioning

  • URL versioning (/v1/users, /v2/users)
  • Header and query parameter versioning
  • Multiple active versions

Route Constraints

  • Type constraints: UUID, integer, string patterns
  • Custom constraint validators
  • Automatic validation before handler execution

Enhanced Middleware System

  • Presets: api, production, development
  • Built-in profiler with metrics
  • Pipeline introspection at runtime
  • Conditional execution with when() and unless()
  • Zero-config validation with @validatedBody()

Enhanced Authorization System

Guard system with advanced access control:

  • Built-in: AuthenticatedGuard, RoleGuard, PermissionGuard, ResourceOwnerGuard
  • ABAC with RequirePolicy()
  • Composition: combineGuards(), sequenceGuards(), whenGuard()
  • Request-scoped caching for performance
  • Permission hierarchy and multi-tenant support
  • Decorators: @RequireAuthentication(), @RequireRoles(), @RequirePermissions()
import {
controller,
Get,
RequireRoles,
RequirePermissions,
} from "@expressots/core";

@controller("/documents")
export class DocumentController {
@Get("/")
@RequireRoles("user", "admin")
@RequirePermissions("documents:read")
getDocuments() {
return this.documentService.findAll();
}
}

Enhanced Error Handling

RFC 7807 compliant error handling:

  • Exception filters via @Catch() decorator
  • @UseFilters() at controller and method level
  • AppError helpers: badRequest(), notFound(), validationFailed()
  • Route suggestions for 404 errors
  • Context-aware error hints (disabled in production)

Application Lifecycle Hooks

AppExpress exposes four lifecycle hooks you can override on your App class. All four are optional and run in the order shown:

import { AppExpress } from "@expressots/adapter-express";

export class App extends AppExpress {
// 1. Synchronous container wiring (custom binds, scopes)
protected globalConfiguration(): void { /* ... */ }

// 2. Async configuration once the container is live
protected async configureServices(): Promise<void> {
this.Middleware.applyPreset("api");
}

// 3. After the HTTP server starts listening
protected async postServerInitialization(): Promise<void> { /* ... */ }

// 4. On SIGINT / SIGTERM, before the process exits
protected async serverShutdown(signal?: NodeJS.Signals): Promise<void> { /* ... */ }
}

Providers can also implement IBootstrap.onBootstrap() and IShutdown.onShutdown(). They're auto-discovered by the lifecycle registry and run alongside the application-level hooks.

CLI Improvements

The v4 CLI ships with four templates and middleware presets:

TemplateHighlights
applicationCanonical full app: controllers, providers, lifecycle, presets
application-with-eventsSame as above plus the event system pre-wired
microMinimal micro(): single file, fast bootstrap
providerLibrary template for publishing reusable providers (dual ESM/CJS, release-it)

Plus:

  • --preset <api|web|serverless|fullstack> injects the right dependencies and replaces the placeholder before npm install.
  • --events adds the event system to application scaffolds.
  • --package-manager <npm|pnpm|yarn> for consistent scaffolding.
  • EXPRESSOTS_TEMPLATE_REF, EXPRESSOTS_DEV, EXPRESSOTS_USE_LOCAL_TEMPLATES, EXPRESSOTS_SKIP_INSTALL env switches for CI / local development.
  • expressots create <kind> for in-project code generation.
  • expressots build for production compilation.
  • expressots studio to launch the Studio dashboard.

Studio

ExpressoTS Studio is the local developer experience platform that ships as part of v4.0.0. Everything runs on your machine; nothing is sent off the box.

  • Status Dashboard: app health, runtime info, DI scope counts, top routes, aggregate security grade.
  • Architecture Map: read-only graph of controllers / use-cases / providers / middleware with DI scope badges and active-path highlighting.
  • Request Timeline + Trace Detail: live recording of every HTTP request with OpenTelemetry spans, headers/body diff, and one-click Replay.
  • Live Logs: in-memory buffer of every framework + app log line, filterable by level, route, and context.
  • Error Inspector: aggregated runtime errors with stack frames and deep-links to source.
  • Security View: npm audit + OSV.dev advisories with transitive root-cause chains, reachability scoring (confirmed / likely / unreachable / unknown), and one-click fixes. OWASP API Top 10 runtime posture findings derived from recorded traffic.
npm install -D @expressots/studio @expressots/studio-agent
npx expressots-studio

The studio-agent dynamically loads only when NODE_ENV=development and the package is installed, so production deployments pay zero runtime cost. See the Studio section for the full tour.

Breaking Changes

ChangeImpact
Node.js 20.18.0+Update runtime
DI patternsReview injection syntax
Lifecycle hooksUpdate app.ts

See the upgrade guide for migration instructions.


Previous Releases

For information about previous releases, please see: