npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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

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, CrudRepository with 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 - @MultipartFile support
  • Interceptors & Filters - @Interceptor, @Filter
  • Resilience - @Retryable, @CircuitBreaker
  • Logging - Structured logging with Logger and @Log
  • Profiles - @Profile, @ConditionalOnProperty
  • Specifications - JPA Specifications API
  • Configuration Files - application.json with 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 - MessageSource and @Message for 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 profile
  • application-prod.json - Production profile
  • application-test.json - Test profile

Activate profiles via environment variable:

SPRING_PROFILES_ACTIVE=dev
# or
NODE_ENV=dev

Using 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):

  1. Environment variables
  2. Profile-specific config files (application-{profile}.json)
  3. Default config file (application.json)

Installation

npm install node-springboot

Quick 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 entity
  • saveAll(entities) - Save multiple entities
  • findById(id) - Find by ID
  • findAll() - Find all entities
  • deleteById(id) - Delete by ID
  • delete(entity) - Delete an entity
  • deleteAll() - Delete all entities
  • count() - Count entities
  • existsById(id) - Check if entity exists

JpaRepository Methods

All CrudRepository methods plus:

  • flush() - Flush pending changes
  • saveAndFlush(entity) - Save and flush
  • deleteInBatch(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 relationships

See examples/relationships/ for complete relationship examples.

License

MIT