Upgrade Guide
Upgrade from ExpressoTS 3.x to 4.0.0.
Prerequisites
| Requirement | Version |
|---|---|
| Node.js | 20.18.0+ |
| Current app | ExpressoTS 3.x |
Breaking changes summary
There is exactly one breaking change in v4.0.0; everything else is additive or opt-in.
.env files are now opt-in (ADR-001)
In v3.x the framework called dotenv.config() automatically. In v4 you opt in by passing envFileConfig to bootstrap(). This was changed because containerised deployments (Docker, Kubernetes, serverless) inject env vars via process.env and a missing .env file used to trip alarms in production.
v3.x (implicit):
import { AppFactory } from "@expressots/core";
import { App } from "./app";
AppFactory.create(App).then((app) => app.listen(3000));
// .env was always loaded
v4 (explicit):
import { bootstrap } from "@expressots/core";
import { App } from "./app";
await bootstrap(App, {
envFileConfig: {
files: { development: ".env", production: ".env.prod" },
autoCreateTemplate: true,
},
});
If you do nothing, v4 will silently skip .env loading and rely on process.env only. CI environments are auto-detected (GitHub Actions, GitLab CI, Jenkins, generic CI=true).
Recommended alternative: call
loadEnvSync()(also from@expressots/core) directly insrc/main.tsbeforebootstrap(App). This is what theapplicationandapplication-with-eventstemplates do. It's an explicit, side-effect-free import that loads.env,.env.${NODE_ENV}, and the matching.localoverrides, with no extrabootstrap()config to remember:src/main.tsimport { bootstrap, loadEnvSync } from "@expressots/core";import { App } from "./app";loadEnvSync();void bootstrap(App);Use
envFileConfigonly when you need bootstrap-time validation (required,validateValues) orautoCreateTemplate.
For the full rationale see ADR-001 in expressots/packages/core/src/application/.docs/decision-log.md.
New in v4.0.0 (non-breaking)
Nothing in this section requires code changes. These are additive features you can adopt incrementally after the upgrade.
Studio is part of v4.0.0
@expressots/studio and @expressots/studio-agent ship alongside @expressots/core in the v4.0.0 release. Install both as dev dependencies:
npm install -D @expressots/studio @expressots/studio-agent
The agent auto-activates when NODE_ENV=development and the package is installed; no app.ts changes are needed. Production deployments pay zero runtime cost. See the Studio section for the full tour, including supply-chain and runtime posture security analysis.
Interceptors, events, lazy loading, content negotiation, advanced authorization
These are all new in v4.0.0. None of them require changes to a v3 app; you opt in when you want them. See the dedicated pages under Features and Guides.
Step 1: Update Dependencies
Update your package.json dependencies to the latest versions:
{
"dependencies": {
"@expressots/core": "^4.0.0",
"@expressots/adapter-express": "^4.0.0",
"@expressots/shared": "^4.0.0"
},
"devDependencies": {
"@expressots/cli": "^4.0.0"
}
}
Then run:
- npm
- yarn
- pnpm
npm install
yarn install
pnpm install
Step 2: Update Node.js Version
Ensure your Node.js version is 20.18.0 or higher:
node --version
Step 3: Application Changes
Bootstrap Function (Optional)
v4 introduces a simplified bootstrap() function. The AppFactory.create() pattern still works.
Before (v3):
import { AppFactory } from "@expressots/core";
import { App } from "app";
AppFactory.create(App).then((app) => app.listen(3000));
After (v4 - new option):
import { bootstrap } from "@expressots/core";
import { App } from "app";
await bootstrap(App);
// Or with options
await bootstrap(App, {
port: 4000,
appName: "My API",
appVersion: "1.0.0",
});
Core APIs (No Changes)
All core APIs remain backward compatible: configContainer(), globalConfiguration(), configureServices(), postServerInitialization(), serverShutdown().
Step 4: New Features (Optional)
Interceptors
Add interceptors to your routes:
import { UseInterceptors, PerformanceInterceptor, LoggingInterceptor } from "@expressots/core";
@controller("/users")
export class UserController {
@Get("/")
@UseInterceptors(PerformanceInterceptor, LoggingInterceptor)
getUsers() {
return this.userService.findAll();
}
}
Event System
Create type-safe events:
// events/user.events.ts
export class UserCreatedEvent {
constructor(
public readonly userId: string,
public readonly email: string
) {}
}
// handlers/user-created.handler.ts
import { provide, OnEvent, IEventHandler } from "@expressots/core";
import { UserCreatedEvent } from "../events/user.events";
@provide(UserCreatedHandler)
@OnEvent(UserCreatedEvent)
export class UserCreatedHandler implements IEventHandler<UserCreatedEvent> {
handle(event: UserCreatedEvent) {
console.log(`User created: ${event.userId}`);
}
}
Testing Module
Use the new testing utilities:
import { createTestApp, request } from "@expressots/core";
describe("UserController", () => {
let app: any;
beforeAll(async () => {
const testApp = await createTestApp(App);
app = testApp.app;
});
test("GET /users", async () => {
await request(app)
.get("/users")
.expectStatus(200);
});
});
Enhanced Configuration
Use type-safe configuration:
import { defineConfig, Env } from "@expressots/core";
export default defineConfig({
database: {
url: Env.string("DATABASE_URL").required(),
pool: Env.number("DB_POOL_SIZE").default(10),
},
});
Step 5: Testing
After upgrading, run your tests to ensure everything works:
- npm
- yarn
- pnpm
npm test
yarn test
pnpm test
Troubleshooting
Common Issues
-
Node.js Version Error
If you see errors about unsupported Node.js features, ensure you're using Node.js 20.18.0 or higher.
-
TypeScript Errors
Update your TypeScript to version 5.x or higher for best compatibility.
-
Dependency Conflicts
Clear your
node_modulesand lock file, then reinstall:rm -rf node_modules package-lock.jsonnpm install
Getting Help
If you encounter issues during the upgrade:
- Check the GitHub Issues
- Join our Discord community
- Read the documentation
Summary
| Step | Action |
|---|---|
| 1 | Update dependencies to v4.0.0 |
| 2 | Ensure Node.js 20.18.0+ |
| 3 | Run tests |
| 4 | Adopt new features (optional) |
v4.0.0 is backward compatible. New features are additive and can be adopted gradually.