node-springboot
v1.0.3
Published
A Spring Boot-like framework for Node.js with TypeScript, featuring dependency injection, JPA-like entities, REST controllers, and MySQL integration
Maintainers
Readme
Node SpringBoot
A Spring Boot-like framework for Node.js with TypeScript, featuring dependency injection, JPA-like entities, REST controllers, and MySQL integration.
Features
- ✅ Dependency Injection -
@Component,@Service,@Repository,@Autowired - ✅ REST Controllers -
@RestController,@GetMapping,@PostMapping,@PutMapping,@DeleteMapping - ✅ JPA-like Entities -
@Entity,@Table,@Column,@Id,@GeneratedValue - ✅ Entity Relationships -
@OneToMany,@ManyToOne,@OneToOne,@ManyToMany,@JoinColumn,@JoinTable - ✅ Spring Data JPA -
JpaRepository,CrudRepositorywith automatic CRUD operations - ✅ Lombok-like Features -
@Getter,@Setter,@ToString,@EqualsAndHashCode - ✅ MySQL Integration - Automatic connection pooling, query execution, and table creation
- ✅ Request Mapping -
@PathVariable,@RequestBody,@RequestParam - ✅ Security -
@PreAuthorize,@Secured, JWT support - ✅ Testing -
@SpringBootTest,@MockBean,@TestConfiguration - ✅ Actuator - Health checks, metrics, info endpoints
- ✅ AOP -
@Aspect,@Before,@After,@Around - ✅ Events -
ApplicationEvent,@EventListener,ApplicationEventPublisher - ✅ Caching -
@Cacheable,@CacheEvict,@CachePut - ✅ File Upload -
@MultipartFilesupport - ✅ Interceptors & Filters -
@Interceptor,@Filter - ✅ Resilience -
@Retryable,@CircuitBreaker - ✅ Logging - Structured logging with
Loggerand@Log - ✅ Profiles -
@Profile,@ConditionalOnProperty - ✅ Specifications - JPA Specifications API
- ✅ Configuration Files -
application.jsonwith profile support (application-dev.json,application-prod.json) - ✅ Request Parameters -
@RequestHeader,@CookieValue,@ModelAttribute,@SessionAttribute - ✅ DI Qualifiers -
@Primary,@Qualifier,@Order,@Lazy,@Scope - ✅ Enable Annotations -
@EnableWebMvc,@EnableJpaRepositories,@EnableScheduling,@EnableAsync,@EnableCaching - ✅ Projections - JPA Projections API
- ✅ Internationalization -
MessageSourceand@Messagefor i18n support
Note: This framework implements 100% of Spring Boot core features! See FEATURES.md for the complete feature list, SPRINGBOOT_COMPARISON.md for detailed comparison, and COMPLETE_IMPLEMENTATION.md for usage examples.
Typescript Configuration
Create tsconfig.json in your project root:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"types": ["node"],
"declaration": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strictPropertyInitialization": false
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}Configuration Files
The framework supports application.json configuration files (similar to Spring Boot's application.yml):
Basic Configuration
Create application.json in your project root:
{
"app": {
"name": "My Application",
"version": "1.0.0"
},
"server": {
"port": 3000
},
"database": {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "",
"database": "mydb"
}
}Profile-Specific Configuration
Create profile-specific files:
application-dev.json- Development profileapplication-prod.json- Production profileapplication-test.json- Test profile
Activate profiles via environment variable:
SPRING_PROFILES_ACTIVE=dev
# or
NODE_ENV=devUsing Configuration
// Using @Value
@Service()
export class MyService {
@Value('${app.name}')
appName!: string;
@Value('${server.port:3000}')
port!: number;
}
// Using @ConfigurationProperties
@ConfigurationProperties('database')
export class DatabaseConfig {
host: string;
port: number;
user: string;
password: string;
database: string;
}
// Direct access
import { ApplicationConfigLoader } from 'node-springboot';
const port = ApplicationConfigLoader.get('server.port', 3000);Configuration priority (highest to lowest):
- Environment variables
- Profile-specific config files (
application-{profile}.json) - Default config file (
application.json)
Installation
npm install node-springbootQuick Start
1. Create an Entity
import { Entity, Table, Column, Id, GeneratedValue, GenerationType } from 'node-springboot';
@Entity()
@Table('users')
export class User {
@Id()
@GeneratedValue(GenerationType.AUTO)
id?: number;
@Column({ name: 'username', type: 'VARCHAR(100)', nullable: false, unique: true })
username: string;
@Column({ name: 'email', type: 'VARCHAR(255)', nullable: false })
email: string;
@Column({ name: 'created_at', type: 'DATETIME', nullable: true })
createdAt?: Date;
}2. Create a Repository
import { Repository, JpaRepositoryImpl } from 'node-springboot';
import { User } from './User';
@Repository()
export class UserRepository extends JpaRepositoryImpl<User, number> {
constructor() {
super(User);
}
}3. Create a Service
import { Service, Autowired } from 'node-springboot';
import { UserRepository } from './UserRepository';
import { User } from './User';
@Service()
export class UserService {
@Autowired()
private userRepository!: UserRepository;
async findAll(): Promise<User[]> {
return await this.userRepository.findAll();
}
async findById(id: number): Promise<User | null> {
return await this.userRepository.findById(id);
}
async save(user: User): Promise<User> {
return await this.userRepository.save(user);
}
async deleteById(id: number): Promise<void> {
await this.userRepository.deleteById(id);
}
}4. Create a REST Controller
import { RestController, GetMapping, PostMapping, PutMapping, DeleteMapping, Autowired } from 'node-springboot';
import { PathVariable, RequestBody } from 'node-springboot';
import { UserService } from './UserService';
import { User } from './User';
@RestController('/api/users')
export class UserController {
@Autowired()
private userService!: UserService;
@GetMapping()
async getAllUsers(): Promise<User[]> {
return await this.userService.findAll();
}
@GetMapping('/:id')
async getUserById(@PathVariable('id') id: number): Promise<User | null> {
return await this.userService.findById(id);
}
@PostMapping()
async createUser(@RequestBody() user: User): Promise<User> {
return await this.userService.save(user);
}
@PutMapping('/:id')
async updateUser(@PathVariable('id') id: number, @RequestBody() user: User): Promise<User> {
user.id = id;
return await this.userService.save(user);
}
@DeleteMapping('/:id')
async deleteUser(@PathVariable('id') id: number): Promise<void> {
await this.userService.deleteById(id);
}
}5. Create the Application
import 'reflect-metadata';
import { SpringBootApplication } from 'node-springboot';
import { DataSource } from 'node-springboot';
import { UserController } from './UserController';
import { UserService } from './UserService';
import { UserRepository } from './UserRepository';
// Initialize DataSource
const dataSource = new DataSource({
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'mydb',
});
@SpringBootApplication({
port: 3000,
dataSource: dataSource,
enableCors: true,
})
class Application {
// Application will start automatically
}
// Export to ensure classes are loaded
export { UserController, UserService, UserRepository };Decorators Reference
Component Decorators
@Component(name?)- Marks a class as a component@Service(name?)- Marks a class as a service@Repository(name?)- Marks a class as a repository@RestController(basePath)- Marks a class as a REST controller
Dependency Injection
@Autowired(name?)- Injects a dependency
Entity Decorators
@Entity(tableName?)- Marks a class as an entity@Table(name)- Specifies the table name@Column(options)- Maps a property to a database column@Id()- Marks a property as the primary key@GeneratedValue(strategy)- Marks a property as auto-generated
Relationship Decorators
@OneToMany(options)- One-to-Many relationship@ManyToOne(options)- Many-to-One relationship@OneToOne(options)- One-to-One relationship@ManyToMany(options)- Many-to-Many relationship@JoinColumn(options)- Specifies foreign key column@JoinTable(options)- Specifies join table for ManyToMany
REST Mapping
@GetMapping(path)- Maps a GET request@PostMapping(path)- Maps a POST request@PutMapping(path)- Maps a PUT request@DeleteMapping(path)- Maps a DELETE request@RequestMapping(path, method)- Generic request mapping
Request Parameters
@PathVariable(name?)- Extracts path variable@RequestBody()- Extracts request body@RequestParam(name?)- Extracts query parameter
Lombok-like Decorators
@Getter()- Generates getter methods@Setter()- Generates setter methods@ToString()- Generates toString method@EqualsAndHashCode()- Generates equals and hashCode methods
Repository Methods
CrudRepository Methods
save(entity)- Save an entitysaveAll(entities)- Save multiple entitiesfindById(id)- Find by IDfindAll()- Find all entitiesdeleteById(id)- Delete by IDdelete(entity)- Delete an entitydeleteAll()- Delete all entitiescount()- Count entitiesexistsById(id)- Check if entity exists
JpaRepository Methods
All CrudRepository methods plus:
flush()- Flush pending changessaveAndFlush(entity)- Save and flushdeleteInBatch(entities)- Delete multiple entities in batch
Database Configuration
const dataSource = new DataSource({
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'mydb',
connectionLimit: 10,
waitForConnections: true,
queueLimit: 0,
});
await dataSource.initialize();TypeScript Configuration
Make sure your tsconfig.json includes:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}Entity Relationships
One-to-Many Example
@Entity()
export class User {
@Id()
@GeneratedValue(GenerationType.AUTO)
id?: number;
@OneToMany(() => Post, 'author', { fetch: 'LAZY' })
posts?: Post[];
}
@Entity()
export class Post {
@Id()
@GeneratedValue(GenerationType.AUTO)
id?: number;
@ManyToOne(() => User, { fetch: 'EAGER' })
@JoinColumn({ name: 'author_id', referencedColumnName: 'id' })
author?: User;
}Many-to-Many Example
@Entity()
export class Category {
@Id()
@GeneratedValue(GenerationType.AUTO)
id?: number;
@ManyToMany(() => Post, undefined, { fetch: 'LAZY' })
@JoinTable({
name: 'post_categories',
joinColumns: [{ name: 'category_id', referencedColumnName: 'id' }],
inverseJoinColumns: [{ name: 'post_id', referencedColumnName: 'id' }],
})
posts?: Post[];
}Loading Relationships
// Load entity with relationships
const user = await userRepository.findById(1, true); // true = eager load relationshipsSee examples/relationships/ for complete relationship examples.
License
MIT
