fragment-ts
v1.1.33
Published
Spring Boot-style framework for TypeScript with Express and TypeORM
Readme
Fragment TS - A Modern TypeScript Framework
Fragment TS is a lightweight, dependency injection-based framework for building scalable TypeScript applications with minimal configuration. Inspired by Spring and NestJS, it provides a clean architecture with powerful decorators for controllers, services, repositories, and more.
Features
- 🚀 Dependency Injection: Automatic wiring of components with
@Autowiredand other decorators - 🎮 REST Controllers: Define routes with familiar decorators like
@Get(),@Post() - 💾 TypeORM Integration: Seamless repository pattern with
@InjectRepository - ⚙️ Modular Architecture: Organize code into services, controllers, and repositories
- 🔧 Auto-configuration: Smart component scanning and registration
- 🧪 Testable Design: Easily mock dependencies for unit testing
- 📦 Production Ready: Works with compiled JavaScript and TypeScript source
- 🛡️ Enhancement Pipeline: Middleware, guards, interceptors, and exception filters for advanced request processing
- 🌐 Environment Management: Simple
.envworkflow withfragment env:usefor dev/staging/prod - 🛠️ CLI Tooling: Built-in commands for scaffolding, migrations, testing, and diagnostics
Installation
npm install fragment-ts reflect-metadata mysql2
# or
yarn add fragment-ts reflect-metadata mysql2Quick Start
1. Initialize your project
npx fragment init my-app
cd my-appThis creates:
src/with example controllers, services, and entitiesfragment.jsonwith database config.envand.env.examplefor environment managementtsconfig.jsonandpackage.jsonwith scripts
2. Configure your database
// fragment.json (flat structure)
{
"database": {
"type": "sqlite",
"database": "${DATABASE_FILE}",
"synchronize": true,
"logging": false,
"entities": ["src/**/*.entity.ts"],
"migrations": ["src/migrations/**/*.ts"]
}
}💡 Uses
${VARS}from.env— no hardcoded secrets.
3. Manage environments
# Create production config
cp .env .env.prod
# Edit DATABASE_URL, JWT_SECRET, etc.
# Switch to production environment
fragment env:use .env.prod
# Verify active config
fragment env:current4. Run in development
fragment serve- Auto-restarts on file changes
- Uses
ts-nodefor TypeScript - Respects
NODE_ENV=development
5. Build for production
fragment build- Compiles
src/→dist/ - Loads
.env.prodif present for build-time vars - Validates TypeScript config
6. Run in production
NODE_ENV=production fragment serve- Delegates to
npm start(i.e.,node dist/main.js) - Uses JavaScript from
dist/ - Never loads
ts-node
Enhancement Pipeline
Fragment TS provides a powerful request processing pipeline with four types of enhancements that can be applied at both class and method levels:
Middleware (@FragmentMiddleware)
Apply Express-compatible middleware to log requests, handle authentication headers, or modify the request/response cycle.
// src/middlewares/logging.middleware.ts
import { Injectable } from 'fragment-ts';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggingMiddleware {
use(req: Request, res: Response, next: NextFunction): void {
console.log(`📥 ${req.method} ${req.path}`);
next();
}
}
// Usage
import { Controller, Get } from 'fragment-ts';
import { LoggingMiddleware } from '../middlewares/logging.middleware';
@FragmentMiddleware(LoggingMiddleware)
@Controller('/api')
export class AppController {
@Get('/health')
health() {
return { status: 'OK' };
}
}Guards (@FragmentGuard)
Control access to routes with authorization logic. Guards run after middleware but before the route handler.
// src/guards/auth.guard.ts
import { Injectable } from 'fragment-ts';
import { Request } from 'express';
@Injectable()
export class AuthGuard {
canActivate(req: Request): boolean {
const token = req.headers.authorization;
return token === 'Bearer valid-token';
}
}
// Usage
import { Controller, Get } from 'fragment-ts';
import { AuthGuard } from '../guards/auth.guard';
@FragmentGuard(AuthGuard)
@Controller('/secure')
export class SecureController {
@Get('/data')
getData() {
return { secret: 'Protected data' };
}
}Interceptors (@FragmentInterceptor)
Transform the response data before it's sent to the client. Interceptors run after the route handler executes.
// src/interceptors/transform.interceptor.ts
import { Injectable } from 'fragment-ts';
import { Request, Response } from 'express';
@Injectable()
export class TransformInterceptor {
intercept(req: Request, res: Response, result: any): any {
return {
success: true,
data: result,
timestamp: new Date().toISOString()
};
}
}
// Usage
import { Controller, Get } from 'fragment-ts';
import { TransformInterceptor } from '../interceptors/transform.interceptor';
@FragmentInterceptor(TransformInterceptor)
@Controller('/api')
export class DataController {
@Get('/info')
getInfo() {
return { message: 'Hello World' };
}
}Exception Filters (@FragmentExceptionFilter)
Handle errors gracefully with custom error responses. Filters are checked in method → controller → application order.
// src/filters/http-exception.filter.ts
import { Injectable } from 'fragment-ts';
import { Request, Response } from 'express';
@Injectable()
export class HttpExceptionFilter {
catch(exception: Error, req: Request, res: Response): void {
if (exception.name === 'ValidationError') {
res.status(400).json({ error: 'Validation failed', message: exception.message });
} else if (exception.name === 'NotFoundError') {
res.status(404).json({ error: 'Not found', message: exception.message });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
}
// Usage
import { FragmentApplication } from 'fragment-ts';
import { HttpExceptionFilter } from './filters/http-exception.filter';
@FragmentApplication({
port: 3000,
autoScan: true,
})
@FragmentExceptionFilter(HttpExceptionFilter)
export class Application {
constructor() {
console.log('Application starting...');
}
}Combined Usage
All enhancement decorators can be combined and applied at different levels:
@FragmentMiddleware(LoggingMiddleware)
@FragmentGuard(AuthGuard)
@FragmentInterceptor(TransformInterceptor)
@Controller('/api')
export class ComplexController {
@Get('/public')
@FragmentGuard(PublicGuard) // Overrides class-level guard
publicData() {
return { message: 'Public data' };
}
@Post('/admin')
@FragmentGuard(AdminGuard) // Additional guard
@FragmentInterceptor(CacheInterceptor) // Additional interceptor
createAdminData(@Body() any) {
return { created: true, data };
}
}CLI Commands
Project Setup
fragment init [dir]– Scaffold a new projectfragment generate <type> <name>– Create controllers, services, entities, etc.
Environment
fragment env:use <file>– Activate.env.staging,.env.prod, etc.fragment env:list– Show available.env*filesfragment env:current– Show active environmentfragment env:diff [.env.example]– Compare configsfragment env:init– Create.envfrom.env.example
Development
fragment serve– Start dev server with hot reloadfragment test– Run unit tests (auto-detectssrc/vsdist/)fragment routes– List registered routesfragment beans– Inspect dependency graph
Database
fragment migrate:create <name>– Create empty migrationfragment migrate:generate– Auto-generate from entity changesfragment migrate:run– Execute pending migrationsfragment seed– Run database seeds
Production
fragment build– Compile TypeScript todist/fragment build --analyze– Show bundle size
Configuration
Fragment uses environment variables exclusively — no hardcoded modes.
- Development:
NODE_ENV=development(default) - Production:
NODE_ENV=production
Your app automatically:
- Uses
src/**/*.tswhenNODE_ENV=development - Uses
dist/**/*.jswhenNODE_ENV=production - Loads
.env→.env.localon startup - Loads
.env.prodduringfragment buildif present
You can override detection with:
FRAGMENT_DEV_MODE=true node dist/app.jsSupport
For issues and feature requests, please open an issue.
License
MIT © Digitwhale Innovations
