A TypeScript-first, Express-like HTTP server framework with modern features and comprehensive testing.
- 🚀 TypeScript-first with strict type safety
- 🛣️ Dynamic route parameters with
{param}
and:param
syntax - 📦 Built-in body parsing (JSON, form-encoded, raw)
- 🔧 Middleware support with error handling and prefix matching
- 🏭 Router support for modular route organization (Express.js style)
- 🧪 Comprehensive test suite (57+ tests, 100% coverage)
- ⚡ Express-like API for familiar development experience
- 🏗️ Modular architecture with clean separation of concerns
- Node.js 18.0.0 or higher
"type": "module"
in your package.json (ES modules required)- tsx recommended for TypeScript execution
- Linux/Unix environment for building from source (uses bash scripts and sed commands)
- TypeScript 5.8+ (for development)
Install from npm (recommended):
npm install @mouradisalah/express.ts
npm install --save-dev tsx @types/node typescript
Example package.json setup:
{
"type": "module",
"scripts": {
"start": "tsx server.ts"
},
"dependencies": {
"@mouradisalah/express.ts": "^1.0.5"
},
"devDependencies": {
"tsx": "^4.20.3",
"@types/node": "^24.1.0",
"typescript": "^5.8.3"
}
}
Or install from GitHub Packages (requires authentication):
npm install @mouradisalah/express.ts --registry=https://npm.pkg.github.com
# Clone the repository
git clone https://github.com/MouradiSalah/express.ts.git
cd express.ts
npm install
npm run build:check
npm run build
npm run dev
npm test
// Import for npm usage:
import { createApplication, createRouter } from '@mouradisalah/express.ts';
// Import for local development (if cloned):
// import { createApplication, createRouter } from './express';
const app = createApplication();
// Middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
// Routes with parameters (supports both {param} and :param)
app.get('/users/{id}', (req, res) => {
res.json({ userId: req.params?.id });
});
app.get('/users/:id/:name', (req, res) => {
res.json({
id: req.params?.id,
name: req.params?.name,
});
});
// Router for modular organization (Express.js style)
const apiRouter = createRouter();
apiRouter.use((req, res, next) => {
res.setHeader('X-API-Version', '1.0');
next();
});
apiRouter.get('/status', (req, res) => {
res.json({ status: 'active' });
});
app.use('/api', apiRouter);
// POST with body parsing
app.post('/users', (req, res) => {
res.status(201).json({
message: 'User created',
user: req.body,
});
});
// Start server
app.listen(3000, () => {
console.log('🚀 Server running on http://localhost:3000');
});
app.get(path, handler)
- Handle GET requestsapp.post(path, handler)
- Handle POST requestsapp.put(path, handler)
- Handle PUT requestsapp.patch(path, handler)
- Handle PATCH requestsapp.delete(path, handler)
- Handle DELETE requestsapp.use(middleware)
- Add middlewareapp.listen(port, callback)
- Start server
You can use either {param}
or :param
syntax for dynamic routes:
// Both of these are valid and equivalent:
app.get('/users/{id}/posts/{postId}', (req, res) => {
const id = req.params?.id;
const postId = req.params?.postId;
// Handle request
});
app.get('/users/:id/posts/:postId', (req, res) => {
const id = req.params?.id;
const postId = req.params?.postId;
// Handle request
});
Automatic body parsing for POST/PUT/PATCH requests:
app.post('/api/data', (req, res) => {
// req.body contains parsed JSON, form data, or raw text
console.log(req.body);
});
// Logger middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
// Prefix-based middleware (Express.js style)
app.use('/api', (req, res, next) => {
res.setHeader('X-API-Version', '1.0');
next();
});
// Error handling middleware
app.use((req, res, next) => {
try {
next();
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Express.js-style router for modular route organization:
// userController.ts
import { createRouter } from '@mouradisalah/express.ts';
const userRouter = createRouter();
userRouter.use((req, res, next) => {
console.log('User route accessed');
next();
});
userRouter.get('/', (req, res) => {
res.json({ users: [] });
});
userRouter.get('/{id}', (req, res) => {
res.json({ user: { id: req.params?.id } });
});
export default userRouter;
// app.ts
import userRouter from './userController';
app.use('/api/users', userRouter);
- Node.js 18+
- npm 8+
- Linux/Unix environment (required for build process)
Important: The build process requires a Linux/Unix environment due to:
- Bash shell scripts for ES module import fixing
sed
commands for post-build processing- Unix-style file paths in build scripts
For Windows users:
- Use WSL (Windows Subsystem for Linux)
- Use Docker with a Linux container
- Use GitHub Actions or other Linux-based CI/CD for building
# Install dependencies
npm install
# Set up Git hooks (automatic code quality checks)
npm run prepare
npm run dev
- Start development server with hot reloadnpm run build
- Build TypeScript to JavaScriptnpm run test
- Run all testsnpm run test:watch
- Run tests in watch modenpm run test:coverage
- Generate coverage reportnpm run lint
- Run ESLintnpm run lint:fix
- Fix linting issues automaticallynpm run format
- Format code with Prettiernpm run check
- Run lint, format check, and tests
This project enforces strict code quality standards:
- Pre-commit hooks automatically lint and format code
- Pre-push hooks run the full test suite
- GitHub Actions validate all PRs with comprehensive CI/CD pipeline
- TypeScript strict mode with no
any
types allowed - Jest testing with high coverage requirements
src/
├── app.ts # Main App class with HTTP methods
├── express.ts # Factory function for Express-like API
├── index.ts # Example server implementation
├── types/ # TypeScript type definitions
│ ├── application/ # Application interface
│ ├── handlers/ # Request/response handlers
│ ├── http/ # HTTP method and message types
│ └── routing/ # Route interface definitions
└── utils/ # Core utilities
├── route-parser.ts # Dynamic route parsing with {param} syntax
└── body-parser.ts # Request body parsing (JSON/form/raw)
The project includes comprehensive test coverage:
- Unit tests for all utilities and core classes
- Integration tests for complete API workflows
- Type validation tests for TypeScript interfaces
- Error handling tests for edge cases
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Run specific test file
npm test -- --testPathPattern=app.test.ts
We welcome contributions! Please see CONTRIBUTING.md for detailed guidelines.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes (hooks will validate code quality)
- Commit using conventional commits:
git commit -m "feat: add amazing feature"
- Push to your branch:
git push origin feature/amazing-feature
- Open a Pull Request
Use conventional commits with the provided template:
git config commit.template .gitmessage
This project is licensed under the MIT License.
- Inspired by Express.js but built with TypeScript-first principles
- Uses modern Node.js features and best practices
- Comprehensive testing approach inspired by industry standards