@nextrush/dev
Development server and build tools with multi-runtime support
Development server and production build tooling for NextRush applications.
The Problem
Modern TypeScript tooling is fragmented:
- Development: tsx, ts-node, nodemon — different tools for different needs
- Building: esbuild, tsup, tsc — each with trade-offs
- Watch mode: Custom configuration for each tool
- Decorator metadata: Most fast bundlers strip it
Worse, fast bundlers like esbuild and tsup break dependency injection:
// Your code
@Service()
class UserService {
constructor(private db: Database) {} // DI needs to know this is 'Database'
}
// After esbuild
let UserService = class {
constructor(db) {}
};
// No type info! DI can't resolve 'Database'You end up choosing: slow tsc builds or broken DI.
Why This Package Exists
@nextrush/dev provides unified development and build tooling:
| Feature | What You Get |
|---|---|
| Single command | nextrush dev / nextrush build |
| Multi-runtime | Node.js, Bun, Deno |
| Decorator metadata | Always emitted for DI |
| Fast builds | SWC-powered compilation |
| Sensible defaults | Works out of the box |
Mental Model
Think of @nextrush/dev as a smart wrapper that:
- Detects which runtime you're using
- Selects the appropriate tool for that runtime
- Ensures decorator metadata is always emitted
Installation
$ pnpm add @nextrush/dev
Quick Start
Development Server
# Auto-detects entry and runtime
npx nextrush dev
# Specify entry file
npx nextrush dev ./src/app.ts
# Custom port
npx nextrush dev --port 4000Production Build
# Build with defaults
npx nextrush build
# With options
npx nextrush build --minify --outDir distCLI Reference
nextrush dev
Start a development server with hot reload.
nextrush dev [entry] [options]Arguments:
| Argument | Default | Description |
|---|---|---|
entry | Auto-detected | Entry file path |
Options:
Dev Options
| Property | Type | Description |
|---|---|---|
--port, -p | number= 3000 | Server port |
--watch, -w | string= 'src' | Additional path to watch (repeatable) |
--inspect | boolean= false | Enable Node.js inspector |
--inspect-port | number= 9229 | Inspector port |
--no-clear | boolean | Don't clear screen on start |
--verbose, -v | boolean= false | Verbose output |
Entry File Resolution:
If no entry specified, searches for (in order):
package.json→mainormodulefield (convertsdist/→src/,.js→.ts)src/index.tssrc/main.tssrc/app.tssrc/server.tsindex.tsmain.tsapp.tsserver.ts
Examples:
# Basic usage
nextrush dev
# Custom entry
nextrush dev src/server.ts
# Custom port
nextrush dev --port 8080
# Enable debugger
nextrush dev --inspect
# Watch additional paths
nextrush dev --watch ./src --watch ./confignextrush build
Create a production build with decorator metadata preserved.
nextrush build [entry] [options]Arguments:
| Argument | Default | Description |
|---|---|---|
entry | Auto-detected | Entry file path |
Options:
Build Options
| Property | Type | Description |
|---|---|---|
--outDir, -o | string= 'dist' | Output directory |
--target, -t | 'es2020' | 'es2021' | 'es2022' | 'esnext'= 'es2022' | Target ES version |
--sourcemap | boolean= true | Generate source maps |
--no-sourcemap | boolean | Disable source maps |
--minify, -m | boolean= false | Minify output |
--no-decorator-metadata | boolean | Skip decorator metadata emission |
--no-clean | boolean | Don't clean output directory |
--verbose, -v | boolean= false | Verbose output |
Examples:
# Basic build
nextrush build
# Custom entry and output
nextrush build ./src/index.ts --outDir build
# Production build with minification
nextrush build --minify
# Target a specific ES version
nextrush build --target esnext --no-sourcemapOutput Structure:
dist/
├── index.js # Compiled JavaScript
├── index.js.map # Source map
├── index.d.ts # Type declarations
└── ...Multi-Runtime Support
Node.js
npx nextrush dev
npx nextrush buildDevelopment tools:
@swc-node/register: SWC-powered ESM loader with decorator metadata support- Hot reload via Node.js native
--watch - Startup validation of
tsconfig.jsonfor decorator flags
Build tools:
@swc/core: Fast compilation with decorator metadata
Bun
bun nextrush dev
bun nextrush buildDevelopment:
- Native TypeScript support
- Native watch mode
- No additional tools needed
Build:
Bun.build(): Native bundler with metadata support
Deno
deno run -A nextrush dev
deno run -A nextrush buildDevelopment:
- Native TypeScript support
- Native watch mode with
deno run --watch - Uses
--allow-net --allow-read --allow-envpermission flags
Build:
npm:@swc/core: SWC via npm specifier
Runtime Compatibility Matrix
| Feature | Node.js | Bun | Deno |
|---|---|---|---|
| Dev server | ✅ | ✅ | ✅ |
| Hot reload | ✅ | ✅ | ✅ |
| Production build | ✅ | ✅ | ✅ |
| Decorator metadata | ✅ | ✅ | ✅ |
| Source maps | ✅ | ✅ | ✅ |
| Type declarations | ✅ | ✅ | ✅ |
Programmatic API
For advanced use cases, import functions directly:
import { dev, build } from '@nextrush/dev';
// Start dev server
await dev('./src/index.ts', { port: 3000 });
// Run production build
await build('./src/index.ts', { outDir: 'dist', minify: true });dev(entry?, options?)
Start development server programmatically.
import { dev, type DevOptions } from '@nextrush/dev';
await dev('./src/index.ts', { port: 3000 });DevOptions
| Property | Type | Description |
|---|---|---|
port? | number= 3000 | Server port |
watch? | string[] | Paths to watch for changes |
build(entry?, options?)
Run production build programmatically.
import { build, type BuildOptions } from '@nextrush/dev';
await build('./src/index.ts', { outDir: 'dist', minify: true });BuildOptions
| Property | Type | Description |
|---|---|---|
outDir? | string= 'dist' | Output directory |
minify? | boolean= false | Minify output |
sourcemap? | boolean= true | Generate source maps |
Runtime Detection
import {
detectRuntime,
isNode,
isBun,
isDeno,
getRuntimeInfo,
type Runtime,
type RuntimeInfo,
} from '@nextrush/dev';
// Check current runtime
const runtime: Runtime = detectRuntime();
console.log(runtime); // 'node' | 'bun' | 'deno'
// Runtime guards
if (isNode()) {
console.log('Running on Node.js');
}
// Detailed info
const info: RuntimeInfo = getRuntimeInfo();
console.log(info.version); // '22.0.0'Configuration
tsconfig.json
Ensure decorator metadata is enabled:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler"
}
}package.json Scripts
{
"scripts": {
"dev": "nextrush dev",
"build": "nextrush build",
"start": "node dist/index.js"
}
}Common Patterns
Development with Controllers
// src/index.ts
// reflect-metadata is auto-imported by the nextrush meta-package
import { createApp, createRouter, listen } from 'nextrush';
import { controllersPlugin } from 'nextrush/class';
const app = createApp();
const router = createRouter();
// Auto-discovers all @Controller classes in ./src (any file name, any depth)
await app.plugin(
controllersPlugin({
router,
root: './src',
prefix: '/api',
})
);
app.route('/', router);
await listen(app, 3000);Start development:
nextrush dev
# → Watching for file changes...
# → Server running on http://localhost:3000Production Deployment
# Build with minification
nextrush build --minify
# Deploy
node dist/index.jsCI/CD Pipeline
# .github/workflows/build.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: pnpm install
- run: pnpm nextrush build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/Decorator Metadata
Why It Matters
Decorator metadata enables dependency injection:
@Service()
class UserService {
constructor(
private db: DatabaseService, // DI resolves this
private logger: LoggerService // And this
) {}
}Without metadata, DI doesn't know what types to inject.
How NextRush Ensures It
Each runtime uses the appropriate tool:
| Runtime | Tool | Output |
|---|---|---|
| Node.js | @swc/core | Reflect.defineMetadata(...) |
| Bun | Bun.build() | Reflect.metadata(...) |
| Deno | npm:@swc/core | _ts_metadata(...) |
Verification
Check build output for metadata:
grep -r "metadata\|design:paramtypes" dist/Expected patterns:
Reflect.defineMetadata("design:paramtypes", ...)Reflect.metadata("design:paramtypes", ...)
Troubleshooting
"Cannot find module" in development
Cause: Module not installed or path incorrect.
# Ensure dependencies installed
pnpm install
# Check import path
# ❌ import { thing } from './module.ts'
# ✅ import { thing } from './module'Decorator metadata not working
Cause: tsconfig.json misconfigured.
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}Build output missing files
Cause: Files excluded or outside source directory.
# Check source structure
ls src/
# Ensure all files are .tsDeno build fails
Cause: npm packages not accessible.
deno run --allow-all --node-modules-dir nextrush buildAPI Exports
// CLI
export { cli, legacyDevCli } from '@nextrush/dev';
// Commands
export { dev, devCli, devHelp, type DevOptions } from '@nextrush/dev';
export { build, buildCli, buildHelp, type BuildOptions } from '@nextrush/dev';
// Runtime detection
export {
detectRuntime,
getRuntimeExecutable,
getRuntimeInfo,
isBun,
isDeno,
isNode,
type Runtime,
type RuntimeInfo,
} from '@nextrush/dev';
// Config utilities
export { findEntry, getDefaultWatchPaths, loadConfig, type NextRushConfig } from '@nextrush/dev';Package Details
| Metric | Value |
|---|---|
| Bundle | ~25 KB |
| Dependencies | @swc/core, tsx |
| Node.js | ≥20.0.0 |
| Bun | ≥1.0.0 |
| Deno | ≥2.0.0 |
See Also
nextrush— Meta package@nextrush/controllers— Controller plugin@nextrush/di— Dependency injection