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 🙏

© 2026 – Pkg Stats / Ryan Hefner

spring-moon

v0.0.6

Published

Core library for Spring Moon framework

Readme

Spring Moon

一个轻量级的 Node.js 框架,灵感来自 Spring Framework,支持分层架构和依赖注入。

✨ 特性

  • 🚀 TypeScript 支持
  • 💉 依赖注入容器(构造器注入)
  • 🏗️ 分层架构装饰器(@Controller、@Service、@Mapper)
  • 🔄 模块系统和组件扫描
  • 🌐 请求上下文管理
  • 📦 事务管理
  • 🔒 HTTP 过滤器和处理器拦截器
  • ⚙️ 配置文件支持(application.yml,类似 Spring Boot)

🎯 分层装饰器

类似 Spring Boot 的装饰器系统:

| 装饰器 | 用途 | 作用域 | | ---------------- | ---------- | --------- | | @Controller | 控制器层 | Request | | @Service | 业务逻辑层 | Singleton | | @Mapper | 数据访问层 | Singleton | | @Component | 通用组件 | Singleton | | @Configuration | 配置类 | Singleton | | @Filter | HTTP 过滤器 | Singleton | | @Interceptor | 处理器拦截器 | Singleton |

🚀 快速开始

安装

npm install spring-moon
# 或
pnpm add spring-moon
# 或
yarn add spring-moon

基本使用

import { Controller, Service, Mapper, Module } from 'spring-moon'

// 数据访问层
@Mapper()
class UserMapper {
  private users = [
    { id: 1, name: 'Alice', email: '[email protected]' },
    { id: 2, name: 'Bob', email: '[email protected]' },
  ]

  findAll() {
    return this.users
  }

  findById(id: number) {
    return this.users.find(user => user.id === id)
  }
}

// 业务逻辑层
@Service()
class UserService {
  constructor(private userMapper: UserMapper) {}

  getAllUsers() {
    return this.userMapper.findAll()
  }

  getUserById(id: number) {
    const user = this.userMapper.findById(id)
    if (!user) {
      throw new Error(`User with id ${id} not found`)
    }
    return user
  }
}

// 控制器层
@Controller()
class UserController {
  constructor(private userService: UserService) {}

  @GetMapping('/api/users')
  async handleGetAllUsers() {
    return this.userService.getAllUsers()
  }

  @GetMapping('/api/users/:id')
  async handleGetUser(@PathVariable('id') id: number) {
    return this.userService.getUserById(id)
  }
}

// 创建应用模块
const appModule = Module.create({
  components: [
    UserMapper, // @Mapper
    UserService, // @Service
    UserController, // @Controller
  ],
})

// 启动应用
async function bootstrap() {
  const context = appModule.getContext()
  const requestContext = context.startRequest()

  try {
    const userController = appModule.resolve<UserController>(UserController)

    const allUsers = await userController.handleGetAllUsers()
    console.log('All users:', allUsers)

    const user = await userController.handleGetUser(1)
    console.log('User 1:', user)

    console.log(`Controllers: ${appModule.getControllers().length}`)
    console.log(`Services: ${appModule.getServices().length}`)
    console.log(`Mappers: ${appModule.getRepositories().length}`)
  } finally {
    context.endRequest()
  }
}

bootstrap().catch(console.error)

📚 核心概念

依赖注入

Spring Moon 使用构造器注入来管理依赖关系:

@Service()
class EmailService {
  sendEmail(to: string, subject: string, body: string) {
    console.log(`Sending email to ${to}: ${subject}`)
  }
}

@Service()
class UserService {
  constructor(
    private userMapper: UserMapper,
    private emailService: EmailService // 自动注入
  ) {}

  async createUser(userData: any) {
    const user = this.userMapper.create(userData)
    await this.emailService.sendEmail(user.email, 'Welcome!', 'Welcome to our platform!')
    return user
  }
}

作用域管理

  • Singleton: 单例模式(默认),整个应用生命周期内只创建一个实例
  • Request: 请求作用域,每个请求创建新实例
@Controller() // Request 作用域
class ApiController {}

@Service() // Singleton 作用域
class BusinessService {}

配置系统(application.yml)

Spring Moon 支持类似 Spring Boot 的 YAML 配置文件,遵循"约定大于配置"的原则:

配置文件位置

YAML 仅从项目根下 resources/(与 src 同级)读取,不兼容 src/config 等其它路径:

  • resources/application.yml
  • resources/application-dev.yml
  • resources/application-prod.yml

多环境配置

支持多环境配置,通过 SPRING_PROFILES_ACTIVE 环境变量切换:

# 开发环境
SPRING_PROFILES_ACTIVE=dev pnpm run dev

# 生产环境
SPRING_PROFILES_ACTIVE=prod pnpm start

配置文件示例

resources/application.yml(与 src 同级):

server:
  port: 3000
  host: localhost

spring:
  moon:
    application:
      name: my-app
      scanBasePackages: []  # 可选,默认扫描 src 目录

database:
  url: postgresql://user:password@localhost:5432/dbname

resources/application-dev.yml:

server:
  port: 3000
  host: localhost

spring:
  moon:
    application:
      name: my-app-dev

resources/application-prod.yml:

server:
  port: 8080
  host: 0.0.0.0

spring:
  moon:
    application:
      name: my-app-prod

配置优先级

配置优先级(从高到低):

  1. 环境变量(SPRING_MOON_SERVER_PORT, DATABASE_URL 等)
  2. application-{profile}.yml(环境特定配置)
  3. application.yml(基础配置)
  4. 默认配置(约定)

读取配置

在代码中读取配置:

import { environment, getConfigValue } from 'spring-moon'

// 方式 1: 使用 Environment API
const port = environment.getNumber('server.port', 3000)
const dbUrl = environment.getString('database.url')

// 方式 2: 使用 getConfigValue
const appName = getConfigValue<string>('spring.moon.application.name')

环境变量支持

支持以下环境变量:

  • SPRING_PROFILES_ACTIVE - 激活的环境(dev/prod)
  • SPRING_MOON_SERVER_PORT - 服务器端口
  • SPRING_MOON_SERVER_HOST - 服务器主机
  • DATABASE_URL - 数据库连接 URL
  • SPRING_MOON_DATABASE_URL - 数据库连接 URL(别名)
  • SPRING_MOON_APPLICATION_NAME - 应用名称

模块系统

使用模块来组织和管理组件:

const userModule = Module.create({
  components: [UserMapper, UserService, UserController],
})

const emailModule = Module.create({
  components: [EmailService, EmailController],
})

const appModule = Module.create({
  imports: [userModule, emailModule],
  components: [AppController],
})

请求上下文

管理请求级别的数据和状态:

const context = appModule.getContext()

// 开始请求
const requestContext = context.startRequest('req-123')

// 存储请求数据
context.setRequestData('userId', 123)
context.setRequestData('permissions', ['read', 'write'])

// 获取请求数据
const userId = context.getRequestData<number>('userId')

// 结束请求(清理资源)
context.endRequest()

事务管理

简单的事务管理支持:

import { TransactionManager } from 'spring-moon'

const txManager = new TransactionManager()

async function transferMoney(fromId: number, toId: number, amount: number) {
  const tx = await txManager.begin()

  try {
    // 添加操作到事务
    txManager.addOperation(tx.id, {
      type: 'debit',
      data: { accountId: fromId, amount },
      rollback: async () => {
        // 回滚逻辑
        await creditAccount(fromId, amount)
      },
    })

    txManager.addOperation(tx.id, {
      type: 'credit',
      data: { accountId: toId, amount },
      rollback: async () => {
        await debitAccount(toId, amount)
      },
    })

    // 提交事务
    await txManager.commit(tx.id)
  } catch (error) {
    // 回滚事务
    await txManager.rollback(tx.id)
    throw error
  }
}

HTTP 过滤器

HTTP 过滤器作用于最外层 HTTP 请求链路,围绕整个 handleRequest 执行。适用于日志记录、CORS 处理、全局鉴权、统一 header 处理等场景。

import { Filter, HttpFilter, Request, Response } from 'spring-moon'

@Filter({ order: 0, patterns: ['/api/**'] })
class LoggingFilter implements HttpFilter {
  order = 0
  patterns = ['/api/**']

  async doFilter(req: Request, res: Response, next: () => Promise<void>): Promise<void> {
    const startTime = Date.now()
    const method = req.method ?? 'GET'
    const url = req.url ?? '/'

    console.log(`📥 ${method} ${url} - Start`)

    await next()

    const duration = Date.now() - startTime
    console.log(`📤 ${method} ${url} - End (${duration}ms)`)
  }
}

@Filter({ order: 1, patterns: ['/api/**'], methods: ['POST', 'PUT', 'PATCH'] })
class BodySizeLimitFilter implements HttpFilter {
  order = 1
  patterns = ['/api/**']
  methods = ['POST', 'PUT', 'PATCH']

  async doFilter(req: Request, res: Response, next: () => Promise<void>): Promise<void> {
    const contentLength = parseInt(req.headers['content-length'] || '0', 10)
    const maxSize = 10 * 1024 * 1024 // 10MB

    if (contentLength > maxSize) {
      res.status(413).json({ error: 'Payload Too Large' })
      return
    }

    await next()
  }
}

过滤器选项说明:

  • order: 执行顺序,数值越小越先执行(默认:0)
  • patterns: 路径匹配模式
    • 精确匹配:'/api/users'
    • 前缀匹配:'/api/**'(匹配所有以 /api/ 开头的路径)
  • methods: HTTP 方法限定(大写),如 ['GET', 'POST']。不指定则匹配所有方法

处理器拦截器

处理器拦截器作用于"路由匹配 + 控制器方法调用"阶段,可以拦截控制器方法的执行,适用于权限验证、返回值包装、异常处理等场景。

import { Interceptor, HandlerInterceptor, HandlerContext, Request, Response } from 'spring-moon'

@Interceptor({ order: 0, patterns: ['/admin/**'], methods: ['GET', 'POST'] })
class AuthInterceptor implements HandlerInterceptor {
  order = 0
  patterns = ['/admin/**']
  methods = ['GET', 'POST']

  async preHandle(req: Request, res: Response, handlerCtx: HandlerContext): Promise<boolean> {
    const token = req.headers['x-auth-token'] as string

    if (!token || token !== 'secret-token') {
      res.status(403).json({ error: 'Forbidden', message: 'Invalid authentication token' })
      return false // 返回 false 中断后续处理
    }

    // 可以在这里设置请求上下文数据
    console.log(`✅ Authenticated request to ${handlerCtx.controllerName}.${handlerCtx.methodName}`)
    return true // 返回 true 或 void 继续处理
  }

  postHandle(req: Request, res: Response, handlerCtx: HandlerContext, result: any): any {
    // 包装返回值
    return {
      success: true,
      data: result,
      timestamp: new Date().toISOString(),
    }
  }

  async afterCompletion(req: Request, res: Response, handlerCtx: HandlerContext, error?: Error): Promise<void> {
    if (error) {
      console.error(`❌ Error in ${handlerCtx.controllerName}.${handlerCtx.methodName}:`, error.message)
    } else {
      console.log(`✅ Completed ${handlerCtx.controllerName}.${handlerCtx.methodName}`)
    }
  }
}

@Interceptor({ patterns: ['/api/**'] })
class ResponseTimeInterceptor implements HandlerInterceptor {
  patterns = ['/api/**']

  async preHandle(req: Request, res: Response, handlerCtx: HandlerContext): Promise<void> {
    // 在请求对象上存储开始时间
    ;(req as any).startTime = Date.now()
  }

  postHandle(req: Request, res: Response, handlerCtx: HandlerContext, result: any): any {
    const duration = Date.now() - ((req as any).startTime || Date.now())
    // 在响应头中添加处理时间
    res.setHeader('X-Response-Time', `${duration}ms`)
    return result
  }
}

拦截器方法说明:

  • preHandle: 在控制器方法调用之前执行
    • 返回 false 表示中断后续处理(不调用 controller)
    • 返回 truevoid 继续处理
  • postHandle: 在控制器方法调用之后、响应写入之前执行
    • 可以修改返回值:返回新值将覆盖原返回值
    • 返回 undefined 则保留原值
  • afterCompletion: 在整个请求完成后执行(无论成功或异常)
    • 按拦截器顺序的逆序执行
    • 适合做清理工作、日志记录等

执行顺序:

HTTP Request
  ↓
Filter Chain (按 order 顺序执行)
  ↓
Route Matching
  ↓
Interceptor.preHandle (按 order 顺序执行)
  ↓
Controller Method
  ↓
Interceptor.postHandle (按 order 顺序执行)
  ↓
Write Response
  ↓
Interceptor.afterCompletion (按 order 逆序执行)
  ↓
HTTP Response

🛠️ CLI 工具

使用 spring-moon-cli 快速创建项目:

# 安装 CLI
npm install -g spring-moon-cli

# 创建新项目
spring-moon create my-app

# 进入项目目录
cd my-app

# 安装依赖
npm install

# 构建项目
npm run build

# 运行项目
npm start

📖 API 文档

装饰器

  • @Component(name?) - 通用组件
  • @Controller(path?) - 控制器
  • @Service(name?) - 服务
  • @Mapper(name?) - 数据访问层映射器(推荐)
  • @Repository(name?) - 数据访问层(已废弃,请使用 @Mapper)
  • @Configuration(name?) - 配置类
  • @Filter(options?) - HTTP 过滤器
  • @Interceptor(options?) - 处理器拦截器
  • @Injectable(token?) - 可注入组件
  • @Inject(token) - 依赖注入
  • @Autowired - 自动装配

核心类

  • Container - 依赖注入容器
  • Module - 模块管理
  • ApplicationContext - 应用上下文
  • TransactionManager - 事务管理器

🤝 贡献

欢迎贡献代码!请查看 贡献指南

📄 许可证

MIT License - 查看 LICENSE 文件了解详情。

🔗 相关链接