nextrush 3.0.7 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,44 +1,111 @@
1
- # NextRush
1
+ # nextrush
2
2
 
3
- > Minimal, modular, high-performance Node.js framework
3
+ > The meta package - install this one to build a NextRush app: `createApp`, `createRouter`, `listen`, HTTP errors, and the shared types, plus an opt-in `nextrush/class` subpath for decorators and DI.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/nextrush.svg)](https://www.npmjs.com/package/nextrush)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Node.js](https://img.shields.io/badge/Node.js-≥22-339933?logo=node.js)](https://nodejs.org)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6?logo=typescript)](https://www.typescriptlang.org)
6
+ [![downloads](https://img.shields.io/npm/dm/nextrush.svg)](https://www.npmjs.com/package/nextrush)
7
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/nextrush.svg)](https://bundlephobia.com/package/nextrush)
8
+ [![types](https://img.shields.io/npm/types/nextrush.svg)](https://www.npmjs.com/package/nextrush)
9
+ [![ESM only](https://img.shields.io/badge/module-ESM--only-blue.svg)](https://nodejs.org/api/esm.html)
10
+ [![license](https://img.shields.io/npm/l/nextrush.svg)](https://github.com/0xTanzim/nextRush/blob/main/LICENSE)
9
11
 
10
- ## Why NextRush?
12
+ | | |
13
+ | --- | --- |
14
+ | **Purpose** | The single entry point for building a NextRush app - re-exports `createApp`, `createRouter`, `listen`, HTTP errors, and the shared types; `nextrush/class` adds decorators and DI as an explicit, separate install |
15
+ | **Package type** | Core (meta package) |
16
+ | **Status** | Stable [x] |
17
+ | **Included in `nextrush`?** | This *is* `nextrush` - the package everything else in the ecosystem re-exports through |
18
+ | **Support tier** | Public - core (stable, semver-guarded) - see [ADR-0005](https://github.com/0xTanzim/nextRush/blob/main/docs/adr/ADR-0005-package-tiers-sealed-surface-deprecation.md) |
19
+ | **Maintenance** | Active |
20
+ | **Runtime** | Node.js (via `@nextrush/adapter-node`) - other runtimes via their own adapter, imported directly |
21
+ | **Requires** | Node `>=22`, ESM-only, TypeScript `>=5.x` |
22
+ | **Introduced** | `v3.0.0` |
11
23
 
12
- - **Fast** — 50-60% faster than Express, competes with Fastify and Hono
13
- - **Minimal** — Core under 3,000 lines of code
14
- - **Modular** — Install only what you need
15
- - **Type-Safe** — Full TypeScript with zero `any`
16
- - **Zero Dependencies** — No external runtime dependencies in core
24
+ ## Highlights
17
25
 
18
- ## This Package
26
+ - [x] **Zero runtime dependencies on the functional path** - `createApp`/`createRouter`/`listen` pull in no third-party package
27
+ - [x] **`@nextrush/class`, `@nextrush/di`, and `reflect-metadata` are optional peers** - a plain `pnpm add nextrush` never resolves them onto disk
28
+ - [x] **ESM-only**, tree-shakable; only the `nextrush/class` subpath carries a side effect (`reflect-metadata`'s global patch)
29
+ - **Bundle:** the functional entry re-exports five workspace packages with no added weight of its own
19
30
 
20
- **`nextrush` is a meta package that re-exports the essentials:**
31
+ <details>
32
+ <summary><strong>Table of contents</strong></summary>
21
33
 
22
- - `createApp`, `Application` Create and manage application instances
23
- - `createRouter`, `Router` — Create and manage routers
24
- - `listen`, `serve`, `createHandler` — Start HTTP server (Node.js)
25
- - `compose` — Compose middleware
26
- - Error classes (`HttpError`, `NotFoundError`, `BadRequestError`, `MethodNotAllowedError`, etc.)
27
- - Error utilities (`createError`, `isHttpError`, `errorHandler`, `notFoundHandler`, `catchAsync`)
28
- - TypeScript types (`Context`, `Middleware`, `Next`, `Plugin`, `RouteHandler`, `HttpMethod`, etc.)
29
- - Constants (`VERSION`, `HttpStatus`, `ContentType`)
34
+ [The problem](#the-problem) | [When to use](#when-to-use) | [Installation](#installation) | [Quick start](#quick-start) | [Capabilities](#capabilities) | [Mental model](#mental-model) | [Common tasks](#common-tasks) | [API overview](#api-overview) | [Options](#options) | [Compatibility](#compatibility) | [Troubleshooting](#troubleshooting) | [FAQ](#faq) | [Package relationships](#package-relationships) | [Architecture](#architecture) | [Resources](#resources)
30
35
 
31
- **Middleware and plugins are installed separately.** This is intentional — you only pay for what you use.
36
+ </details>
37
+
38
+ ---
39
+
40
+ ## The problem
41
+
42
+ NextRush is deliberately split into ~35 independent packages - a router, a core engine, an adapter per runtime, a class/DI runtime, and dozens of middleware/extension packages - so that each piece can version, test, and ship on its own. That is good for the packages and bad for a first-time user: nobody wants to work out that `createApp` lives in `@nextrush/core` but needs a router from `@nextrush/router` wired in by hand, and an HTTP server from `@nextrush/adapter-node` on top, before a single request can be served.
43
+
44
+ ```ts
45
+ // TODAY, without the meta package - wiring the pieces by hand:
46
+ import { createApp } from '@nextrush/core';
47
+ import { createRouter } from '@nextrush/router';
48
+ import { listen } from '@nextrush/adapter-node';
49
+
50
+ const app = createApp({ router: createRouter() }); // router is NOT wired in for you here
51
+ listen(app, 8080);
52
+ ```
53
+
54
+ `nextrush` is that wiring, done once, correctly: its own `createApp` injects a router so `app.get(...)` works immediately, and its barrel re-exports exactly the symbols a functional app needs - nothing from the class/DI stack, so a functional-only install stays as small as the "zero-dependency core" claim promises.
55
+
56
+ ## When to use
57
+
58
+ **Use `nextrush` if:**
59
+
60
+ - You're building a NextRush application - this is the entry point every quick-start example uses
61
+ - You want `createApp` to come with a router already attached, so route shortcuts (`app.get`, `app.post`, ...) work without extra setup
62
+ - You want the class-based API (`@Controller`, `@Service`, DI) available behind one additional, explicit install (`nextrush/class`), never bundled into the functional path
63
+
64
+ **Reach for something else if:**
65
+
66
+ - You're building your own meta-package, adapter, or runtime on top of NextRush and need the raw, router-agnostic `Application` - use [`@nextrush/core`](../core) directly
67
+ - You need only route matching, with no application/lifecycle layer - use [`@nextrush/router`](../router) directly
68
+ - You're targeting Bun, Deno, or an edge runtime - `nextrush`'s `listen`/`serve` come from `@nextrush/adapter-node`; import the matching `@nextrush/adapter-{bun,deno,edge}` directly for other runtimes
69
+
70
+ ---
32
71
 
33
72
  ## Installation
34
73
 
35
74
  ```bash
36
75
  pnpm add nextrush
76
+ # npm i nextrush | yarn add nextrush | bun add nextrush
37
77
  ```
38
78
 
39
- ## Quick Start
79
+ This resolves only the functional core and its five workspace dependencies (`@nextrush/core`,
80
+ `@nextrush/router`, `@nextrush/adapter-node`, `@nextrush/errors`, `@nextrush/types`) - no class
81
+ runtime, no DI container, no `reflect-metadata`. See [Compatibility](#compatibility) for the
82
+ exact dependency footprint by usage path.
83
+
84
+ > [!NOTE]
85
+ > Scaffolding a new project? `pnpm create nextrush my-api` sets up `nextrush` (and, for
86
+ > class-based/full templates, `@nextrush/class`) for you - see
87
+ > [Scaffold a project](#scaffold-a-project) below.
88
+
89
+ ### Two intentional install steps: Runtime and Development Toolkit
90
+
91
+ `nextrush` is the **runtime** - everything you need to *serve* requests. The dev server, production
92
+ builds, and code generators live in a separate **development toolkit**, `@nextrush/dev`, installed
93
+ as a dev dependency. This split is deliberate (nothing dev-only ships to production), not a missing
94
+ bundle:
40
95
 
41
- ```typescript
96
+ ```bash
97
+ pnpm add nextrush # 1. Runtime - build and serve your app
98
+ pnpm add -D @nextrush/dev # 2. Development Toolkit - `nextrush dev` / `build` / `generate`
99
+ ```
100
+
101
+ The `nextrush` command is provided by the runtime itself, so it always resolves. If you run
102
+ `nextrush dev` before installing the toolkit, it doesn't fail with a raw "command not found" - it
103
+ prints the exact install command for your package manager and a one-line description of what the
104
+ toolkit provides. `pnpm create nextrush` adds both steps for you.
105
+
106
+ ## Quick start
107
+
108
+ ```ts
42
109
  import { createApp, createRouter, listen } from 'nextrush';
43
110
 
44
111
  const app = createApp();
@@ -50,48 +117,86 @@ router.get('/', (ctx) => {
50
117
 
51
118
  app.route('/', router);
52
119
 
53
- listen(app, 3000);
120
+ listen(app, 8080);
54
121
  ```
55
122
 
56
- ## Performance
123
+ `createApp()` here wraps `@nextrush/core`'s `createApp` and injects a default router, so
124
+ `app.get(...)` also works without the explicit `createRouter()` step above - the two forms are
125
+ equivalent; this one shows the router as its own object because most real apps mount several
126
+ feature routers with `app.route(prefix, router)`.
127
+
128
+ ## Capabilities
129
+
130
+ **Application & routing**
131
+ - **`createApp` / `Application`** - an `@nextrush/core` application with a router pre-wired
132
+ - **`createRouter` / `Router` / `endpoint`** - the segment-trie router and its route-metadata marker
133
+ - **`compose`** - the Koa-style middleware composer, re-exported standalone
134
+
135
+ **Server**
136
+ - **`listen` / `serve` / `createHandler`** - start an HTTP server on Node.js via `@nextrush/adapter-node`
137
+
138
+ **Errors**
139
+ - **The full `HttpError` hierarchy** - `BadRequestError`, `NotFoundError`, `UnauthorizedError`, and every other 4xx/5xx class
140
+ - **`createError` / `isHttpError` / `errorHandler` / `notFoundHandler`** - error factories and middleware
141
+ - **`ERROR_CODES` / `codeForStatus` / `ValidationError`** - the central error-code registry
57
142
 
58
- Benchmark snapshot from a single lab machine (Intel i5-8300H, 8 cores) running Node.js v25.9.0.
59
- Two tools available: **wrk** (C-based, process-isolated) and **autocannon** (Node.js, automatic fallback).
60
- All tests: 10s duration, 64 connections, no pipelining. See [Performance](https://github.com/0xTanzim/nextRush/blob/main/apps/docs/content/docs/performance/index.mdx) for methodology and numbers.
143
+ **Types & constants**
144
+ - **`Context`, `Middleware`, `Next`, `Extension`, `ExtensionContext`, `RouteHandler`, `RouteDefinition`, `RouteMetadata`, `HttpMethod`** - the shared contracts every NextRush package builds on
145
+ - **`HttpStatus`, `ContentType`** - HTTP constants
61
146
 
62
- ### wrk
147
+ **Class-based (opt-in, via `nextrush/class`)**
148
+ - **Decorators, DI, controllers, modules, guards, interceptors, filters** - see [Class-based controllers](#class-based-controllers)
63
149
 
64
- | Framework | Hello World | Route Params | POST JSON | Middleware Stack |
65
- | --------------- | -------------- | -------------- | -------------- | ---------------- |
66
- | Raw Node.js | 35,863 RPS | 33,326 RPS | 25,116 RPS | 30,738 RPS |
67
- | Fastify | 35,592 RPS | 32,407 RPS | 18,799 RPS | 27,968 RPS |
68
- | **NextRush v3** | **31,311 RPS** | **29,688 RPS** | **18,460 RPS** | **32,377 RPS** |
69
- | Hono | 26,438 RPS | 26,586 RPS | 10,826 RPS | 22,179 RPS |
70
- | Koa | 23,350 RPS | 21,890 RPS | 14,954 RPS | 20,972 RPS |
71
- | Express | 17,784 RPS | 17,598 RPS | 12,947 RPS | 17,356 RPS |
150
+ **Developer experience**
151
+ - **Fully typed, zero `any`** - every re-export carries its source package's exact types
152
+ - **Actionable failure on a missing peer** - importing `nextrush/class` without its peers installed throws a message naming the exact install command, not an opaque resolution error
72
153
 
73
- ### autocannon
154
+ ## Mental model
74
155
 
75
- | Framework | Hello World | Route Params | POST JSON | Middleware Stack |
76
- | --------------- | -------------- | -------------- | -------------- | ---------------- |
77
- | Raw Node.js | 36,903 RPS | 33,936 RPS | 24,936 RPS | 31,471 RPS |
78
- | Fastify | 34,063 RPS | 31,095 RPS | 18,532 RPS | 28,744 RPS |
79
- | **NextRush v3** | **31,733 RPS** | **29,534 RPS** | **19,192 RPS** | **32,220 RPS** |
80
- | Hono | 28,209 RPS | 25,966 RPS | 10,798 RPS | 22,258 RPS |
81
- | Koa | 23,845 RPS | 22,421 RPS | 15,323 RPS | 21,125 RPS |
82
- | Express | 19,496 RPS | 18,209 RPS | 13,063 RPS | 17,352 RPS |
156
+ `nextrush` is a **barrel with one behavioral addition**: its root entry re-exports the functional stack as-is, except `createApp`, which wraps `@nextrush/core`'s version to inject a default router. The `nextrush/class` subpath is a second, independent barrel that dynamically loads the optional class/DI peers and re-exports their runtime values by assignment - so a resolution failure there produces an actionable error instead of crashing at import time.
83
157
 
84
- > Performance varies by hardware. Run `apps/benchmark` on your machine.
158
+ ```text
159
+ 'nextrush' ---> re-exports @nextrush/{core,router,adapter-node,errors,types}
160
+ (createApp wraps @nextrush/core's, injecting a default router)
85
161
 
86
- ## Adding Middleware
162
+ 'nextrush/class' ---> dynamically imports reflect-metadata + @nextrush/di + @nextrush/class
163
+ (only if you import this subpath - never loaded by the root entry)
164
+ ```
165
+
166
+ **Rule:** importing `nextrush` never touches the class/DI stack. Importing `nextrush/class` is
167
+ the one and only place that stack gets loaded - and only if you've installed its peers.
168
+
169
+ > [!TIP]
170
+ > The exports-map routing between the two entries, and the dynamic-import/re-export-by-assignment
171
+ > mechanism behind `nextrush/class`, are diagrammed in [`ARCHITECTURE.md`](./ARCHITECTURE.md).
172
+
173
+ ---
174
+
175
+ ## Common tasks
87
176
 
88
- Install what you need:
177
+ ### Build a functional app
178
+
179
+ ```ts
180
+ import { createApp, createRouter, listen } from 'nextrush';
181
+
182
+ const app = createApp();
183
+ const users = createRouter();
184
+
185
+ users.get('/', (ctx) => ctx.json([]));
186
+ users.get('/:id', (ctx) => ctx.json({ id: ctx.params.id }));
187
+
188
+ app.route('/users', users); // Hono-style composition - mount a feature router at a prefix
189
+
190
+ listen(app, 8080);
191
+ ```
192
+
193
+ ### Add middleware
89
194
 
90
195
  ```bash
91
196
  pnpm add @nextrush/cors @nextrush/body-parser
92
197
  ```
93
198
 
94
- ```typescript
199
+ ```ts
95
200
  import { createApp, listen } from 'nextrush';
96
201
  import { cors } from '@nextrush/cors';
97
202
  import { json } from '@nextrush/body-parser';
@@ -101,29 +206,57 @@ const app = createApp();
101
206
  app.use(cors());
102
207
  app.use(json());
103
208
 
104
- app.use((ctx) => {
105
- ctx.json({ body: ctx.body });
209
+ app.post('/api/users', (ctx) => {
210
+ const { name, email } = ctx.body as { name: string; email: string };
211
+ ctx.status = 201;
212
+ ctx.json({ id: Date.now(), name, email });
106
213
  });
107
214
 
108
- listen(app, 3000);
215
+ listen(app, 8080);
109
216
  ```
110
217
 
111
- ## Class-Based Controllers
218
+ ### Handle errors
219
+
220
+ ```ts
221
+ import { NotFoundError, BadRequestError } from 'nextrush';
112
222
 
113
- Class-based APIs (decorators, DI, controllers) are available via the `nextrush/class` subpath:
223
+ app.get('/users/:id', async (ctx) => {
224
+ const user = await db.findUser(ctx.params.id);
225
+ if (!user) throw new NotFoundError('User not found');
226
+ ctx.json(user);
227
+ });
228
+ ```
114
229
 
115
- - `nextrush` Functional API (`createApp`, `createRouter`, `listen`, errors, types)
116
- - `nextrush/class` Class-based API (`Controller`, `Get`, `Service`, `controllersPlugin`, etc.)
230
+ Any `HttpError` subclass thrown from a handler is caught by `@nextrush/core`'s default error
231
+ path and serialized through the same contract as `errorHandler()` - no manual `try`/`catch`
232
+ needed around individual routes.
117
233
 
118
- The `nextrush/class` entry auto-imports `reflect-metadata`, so you can use decorators and DI without any extra setup:
234
+ ### Scaffold a project
119
235
 
120
236
  ```bash
121
- pnpm add nextrush
237
+ pnpm create nextrush my-api
238
+ cd my-api && pnpm dev
122
239
  ```
123
240
 
124
- ```typescript
125
- import { createApp, createRouter, listen } from 'nextrush';
126
- import { controllersPlugin, Controller, Get, Service } from 'nextrush/class';
241
+ The `create nextrush` form (with a space) installs the `create-nextrush` package - you can also
242
+ use `npx create-nextrush@latest` or `pnpm dlx create-nextrush@latest`. The interactive
243
+ scaffolder lets you choose functional, class-based, or full style, a middleware preset, and a
244
+ runtime target; class-based and full templates add `@nextrush/class` to your `package.json`
245
+ automatically. See the
246
+ [create-nextrush docs](https://github.com/0xTanzim/nextRush/tree/main/packages/create-nextrush#usage).
247
+
248
+ ## Class-Based Controllers
249
+
250
+ Class-based APIs (decorators, DI, controllers) live behind the `nextrush/class` subpath, an
251
+ explicit, optional install:
252
+
253
+ ```bash
254
+ pnpm add nextrush @nextrush/class
255
+ ```
256
+
257
+ ```ts
258
+ import { createApp, listen } from 'nextrush';
259
+ import { Controller, Get, Service, registerControllers } from 'nextrush/class';
127
260
 
128
261
  @Service()
129
262
  class GreetService {
@@ -143,108 +276,227 @@ class HelloController {
143
276
  }
144
277
 
145
278
  const app = createApp();
146
- const router = createRouter();
279
+ await registerControllers(app, { root: './src' });
280
+ await listen(app, 8080);
281
+ ```
147
282
 
148
- app.plugin(controllersPlugin({ router, root: './src' }));
149
- app.route('/', router);
150
- listen(app, 3000);
283
+ The `nextrush/class` entry auto-imports `reflect-metadata`, so decorators and DI work with no
284
+ extra setup once `@nextrush/class` is installed. `registerControllers` is a **registrar**, not a
285
+ plugin - call and `await` it directly; it reads `app.router` and `app.container` (both injected
286
+ by `nextrush`'s `createApp()`) and must resolve before `listen()`/`serve()` starts the server.
287
+
288
+ > [!IMPORTANT]
289
+ > `experimentalDecorators` and `emitDecoratorMetadata` must be enabled in `tsconfig.json` when
290
+ > using `nextrush/class`. `create-nextrush` turns them **on** for class-based and full templates
291
+ > and **omits** them for functional (routes-only) projects, where they are unnecessary.
292
+
293
+ ## API overview
294
+
295
+ The sealed public surface (ADR-0005), by entry point.
296
+
297
+ ### `nextrush` (root entry)
298
+
299
+ | Export | From | Since | Stability | Description |
300
+ | ------ | ---- | ----- | --------- | ----------- |
301
+ | `createApp` | wraps `@nextrush/core` | `3.0.0` | Stable [x] | Creates an `Application` with a default router pre-wired. |
302
+ | `Application`, `compose` | `@nextrush/core` | `3.0.0` | Stable [x] | The application class and the middleware composer. |
303
+ | `Router`, `createRouter`, `endpoint` | `@nextrush/router` | `3.0.0` | Stable [x] | Segment-trie router and its route-metadata marker. |
304
+ | `createHandler`, `listen`, `serve` | `@nextrush/adapter-node` | `3.0.0` | Stable [x] | Start an HTTP server on Node.js. |
305
+ | `HttpError`, `NextRushError`, and every 4xx/5xx class | `@nextrush/errors` | `3.0.0` | Stable [x] | `BadRequestError`, `NotFoundError`, `UnauthorizedError`, `ForbiddenError`, `ConflictError`, `MethodNotAllowedError`, `UnprocessableEntityError`, `TooManyRequestsError`, `InternalServerError`, `NotImplementedError`, `BadGatewayError`, `ServiceUnavailableError`, `GatewayTimeoutError`. |
306
+ | `createError`, `isHttpError`, `errorHandler`, `notFoundHandler` | `@nextrush/errors` | `3.0.0` | Stable [x] | Error factory and middleware. |
307
+ | `ERROR_CODES`, `codeForStatus`, `ValidationError` | `@nextrush/errors` | `3.1.0` | Stable [x] | The central error-code registry and validation error type. |
308
+ | `ContentType`, `HttpStatus` | `@nextrush/types` | `3.0.0` | Stable [x] | HTTP constants. |
309
+ | `type ApplicationOptions`, `ComposedMiddleware` | `@nextrush/core` | `3.0.0` | Stable [x] | Application-level contracts. |
310
+ | `type RouterOptions` | `@nextrush/router` | `3.0.0` | Stable [x] | Router configuration. |
311
+ | `type ServeOptions`, `ServerInstance` | `@nextrush/adapter-node` | `3.0.0` | Stable [x] | Server-start contracts. |
312
+ | `type ErrorHandlerOptions`, `HttpErrorOptions`, `ValidationIssue` | `@nextrush/errors` | `3.0.0` | Stable [x] | Error-handling contracts. |
313
+ | `type Context`, `Extension`, `ExtensionContext`, `HttpMethod`, `HttpStatusCode`, `Middleware`, `Next`, `RouteHandler`, `RouteDefinition`, `RouteMetadata`, `Runtime` | `@nextrush/types` | `3.0.0` | Stable [x] | The shared contracts every NextRush package builds on. |
314
+
315
+ This runtime surface is locked by `src/__tests__/public-surface.test.ts`; if this table ever
316
+ claims an export that test doesn't list, that's a documentation bug - please file an issue.
317
+
318
+ ### `nextrush/class` (opt-in subpath)
319
+
320
+ | Export | From | Since | Stability | Description |
321
+ | ------ | ---- | ----- | --------- | ----------- |
322
+ | `Controller`, `Get`, `Post`, `Put`, `Patch`, `Delete`, `Head`, `Options`, `All` | `@nextrush/class` | `3.0.0` | Stable [x] | Class and route decorators. |
323
+ | `Body`, `Param`, `Query`, `Header`, `Ctx`, `Req`, `Res`, `createCustomParamDecorator` | `@nextrush/class` | `3.0.0` | Stable [x] | Parameter-binding decorators. |
324
+ | `HttpCode`, `Redirect`, `SetHeader` | `@nextrush/class` | `3.0.0` | Stable [x] | Response decorators. |
325
+ | `UseGuard`, `UseInterceptor`, `Catch`, `UseFilter` | `@nextrush/class` | `3.0.0` | Stable [x] | Guards, interceptors, exception filters. |
326
+ | `isOnInit`, `isOnShutdown` | `@nextrush/class` | `3.0.0` | Stable [x] | Lifecycle-hook type guards. |
327
+ | `Module`, `getModuleMetadata`, `isModule`, `registerModule` | `@nextrush/class` | `3.1.0` | Stable [x] | Module composition and registration. |
328
+ | `registerControllers` | `@nextrush/class` | `3.0.0` | Stable [x] | Registrar - discovers and wires controllers into an app. |
329
+ | `Config`, `container`, `createContainer`, `delay`, `inject`, `Injectable`, `Optional`, `Repository`, `Service` | `@nextrush/di` | `3.0.0` | Stable [x] | The DI container surface. |
330
+ | `type ClassProvider`, `ConfigOptions`, `Container`, `FactoryProvider`, `Provider`, `Scope`, `ServiceOptions`, `Token`, `ValueProvider` | `@nextrush/di` | `3.0.0` | Stable [x] | DI contracts. |
331
+ | `type BodyOptions`, `CanActivate`, `ControllerMetadata`, `ControllerOptions`, `ControllerRouteMetadata`, `CustomParamExtractor`, `ExceptionFilter`, `GuardContext`, `GuardFn`, `HeaderOptions`, `Interceptor`, `ModuleMetadata`, `ModuleOptions`, `ModuleProvider`, `ModuleProviderConfig`, `ParamMetadata`, `ParamOptions`, `ParamSource`, `QueryOptions`, `RouteOptions`, `TransformFn`, `OnInit`, `OnShutdown`, `ControllersOptions`, `ModuleRegistrationOptions` | `@nextrush/class` | `3.0.0`-`3.1.0` | Stable [x] | Class-runtime contracts. |
332
+ | `type RouteMetadata` (from `@nextrush/class`) | `@nextrush/class` | `3.0.0` | Deprecated | Superseded by `ControllerRouteMetadata`; removed in the next major. |
333
+
334
+ Loading `nextrush/class` requires `@nextrush/class`, `@nextrush/di`, and `reflect-metadata` to be
335
+ installed - see [Compatibility](#compatibility).
336
+
337
+ ## Options
338
+
339
+ `createApp(options?)` re-exports `@nextrush/core`'s `ApplicationOptions` unchanged - see
340
+ [`@nextrush/core`'s Options](../core#options) for the full table. There is no configuration
341
+ specific to the meta package itself: it adds one behavior (a default router injected into
342
+ `options.router` when you don't pass one) and no new option.
343
+
344
+ ## Compatibility
345
+
346
+ **Requirements**
347
+
348
+ | Requirement | Version |
349
+ | ----------- | ------- |
350
+ | NextRush | `3.x` |
351
+ | Node.js | `>=22` |
352
+ | TypeScript | `>=5.x` |
353
+
354
+ **Runtimes**
355
+
356
+ | Runtime | Supported | Notes |
357
+ | ------- | --------- | ----- |
358
+ | Node.js `>=22` | [x] | Via `@nextrush/adapter-node`; ESM-only |
359
+ | Bun / Deno / Edge | Not via this package | Import `@nextrush/core` + `@nextrush/router` + the matching `@nextrush/adapter-{bun,deno,edge}` directly - `nextrush`'s `listen`/`serve` are Node-specific |
360
+
361
+ **Dependency footprint by usage path**
362
+
363
+ | Usage path | Entry point | Install | Runtime dependencies |
364
+ | ---------- | ----------- | ------- | --------------------- |
365
+ | Functional core | `createApp`, `createRouter`, `listen` from `nextrush` | `pnpm add nextrush` | `@nextrush/core`, `@nextrush/router`, `@nextrush/adapter-node`, `@nextrush/errors`, `@nextrush/types` (all hard `dependencies`) |
366
+ | Class-based / DI | `nextrush/class` | `pnpm add nextrush @nextrush/class` | Adds `@nextrush/class`, `@nextrush/di` (wraps `tsyringe@^4.10.0`), `reflect-metadata@^0.2.2` |
367
+
368
+ `@nextrush/class`, `@nextrush/di`, and `reflect-metadata` are declared as **optional
369
+ `peerDependencies`** in `package.json` (`peerDependenciesMeta.<name>.optional: true`) - a
370
+ functional-only `pnpm add nextrush` never resolves any of the three onto disk. If you import
371
+ `nextrush/class` without installing the peers, the import throws an actionable error naming the
372
+ exact install command instead of an opaque module-resolution failure.
373
+
374
+ `@nextrush/stream` and `@nextrush/runtime` ship transitively through `@nextrush/adapter-node`'s
375
+ own dependencies - they are present once `nextrush` is installed, but are not re-exported from
376
+ `nextrush` directly. Add either as a direct dependency of your own project only if you import its
377
+ API yourself rather than through the adapter.
378
+
379
+ **Integration**
380
+ - **Peer dependencies:** `@nextrush/class`, `@nextrush/di`, `reflect-metadata` - all optional, needed only for `nextrush/class`.
381
+ - **Works with:** every `@nextrush/*` middleware and extension package (installed separately - see the [package catalog](https://0xtanzim.github.io/nextRush/docs/resources/package-catalog)).
382
+ - **Incompatible with:** none.
383
+
384
+ > [!IMPORTANT]
385
+ > NextRush is **ESM-only, permanently** - no CommonJS build. On Node `>=22`, CommonJS consumers
386
+ > can `require()` this ESM package natively. See the
387
+ > [Module Format Policy](https://github.com/0xTanzim/nextRush#module-format-policy).
388
+
389
+ ---
390
+
391
+ ## Troubleshooting
392
+
393
+ <details>
394
+ <summary><strong><code>Cannot find module '@nextrush/class'</code> when importing <code>nextrush/class</code></strong></summary>
395
+
396
+ **Cause:** `@nextrush/class`, `@nextrush/di`, and `reflect-metadata` are optional peer
397
+ dependencies - a plain `pnpm add nextrush` never installs them. **Fix:** install the peer
398
+ explicitly:
399
+
400
+ ```bash
401
+ pnpm add @nextrush/class reflect-metadata
151
402
  ```
152
403
 
153
- > **`experimentalDecorators` and `emitDecoratorMetadata`** are required when you use `nextrush/class` with DI or decorators. `create-nextrush` turns them **on** for **class-based** and **full** templates, and **omits** them for **functional** (routes-only) projects where they are unnecessary.
404
+ </details>
154
405
 
155
- ## What's Included
406
+ <details>
407
+ <summary><strong>Decorators throw or metadata is missing at runtime</strong></summary>
156
408
 
157
- This meta package re-exports from:
409
+ **Cause:** `experimentalDecorators` and/or `emitDecoratorMetadata` are not enabled in
410
+ `tsconfig.json`. **Fix:** enable both - `create-nextrush` does this automatically for
411
+ class-based/full templates:
158
412
 
159
- | Package | Exports |
160
- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
161
- | `@nextrush/core` | `createApp`, `Application`, `compose` |
162
- | `@nextrush/router` | `createRouter`, `Router` |
163
- | `@nextrush/adapter-node` | `listen`, `serve`, `createHandler` |
164
- | `@nextrush/types` | `Context`, `Middleware`, `Next`, `Plugin`, `RouteHandler`, `HttpMethod`, `HttpStatus`, `ContentType` |
165
- | `@nextrush/errors` | `HttpError`, `NextRushError`, error classes (4xx/5xx), `createError`, `isHttpError`, `errorHandler`, `notFoundHandler`, `catchAsync` |
413
+ ```json
414
+ {
415
+ "compilerOptions": {
416
+ "experimentalDecorators": true,
417
+ "emitDecoratorMetadata": true
418
+ }
419
+ }
420
+ ```
166
421
 
167
- ## Available Packages
422
+ </details>
168
423
 
169
- ### Core (included in nextrush)
424
+ <details>
425
+ <summary><strong><code>app.get(...)</code> throws <code>No router configured</code></strong></summary>
170
426
 
171
- | Package | Description |
172
- | ------------------------ | ------------------------------------ |
173
- | `@nextrush/core` | Application & middleware composition |
174
- | `@nextrush/router` | High-performance radix tree router |
175
- | `@nextrush/adapter-node` | Node.js HTTP adapter |
176
- | `@nextrush/types` | Shared TypeScript types |
177
- | `@nextrush/errors` | HTTP error classes |
427
+ **Cause:** you're calling `@nextrush/core`'s own `createApp()` (router-agnostic by design)
428
+ instead of `nextrush`'s. **Fix:** import `createApp` from `nextrush`, which injects a router:
178
429
 
179
- ### Middleware (install separately)
430
+ ```ts
431
+ import { createApp } from 'nextrush'; // injects a router; app.get works
432
+ ```
180
433
 
181
- | Package | Description |
182
- | ----------------------- | -------------------------------------- |
183
- | `@nextrush/body-parser` | JSON/form/text body parsing |
184
- | `@nextrush/cors` | CORS headers |
185
- | `@nextrush/helmet` | Security headers |
186
- | `@nextrush/cookies` | Cookie handling |
187
- | `@nextrush/compression` | Response compression (gzip/brotli) |
188
- | `@nextrush/rate-limit` | Rate limiting with multiple algorithms |
189
- | `@nextrush/request-id` | Request ID generation |
190
- | `@nextrush/timer` | Request timing headers |
434
+ </details>
191
435
 
192
- ### Plugins (install separately)
436
+ ## FAQ
193
437
 
194
- | Package | Description |
195
- | ----------------------- | ------------------------------- |
196
- | `@nextrush/logger` | Structured logging |
197
- | `@nextrush/static` | Static file serving |
198
- | `@nextrush/websocket` | WebSocket support with rooms |
199
- | `@nextrush/template` | Multi-engine template rendering |
200
- | `@nextrush/events` | Type-safe event emitter |
201
- | `@nextrush/controllers` | Decorator-based controllers |
438
+ **Can I skip the meta package and use `@nextrush/core` / `@nextrush/router` / `@nextrush/adapter-node` directly?**
439
+ Yes - see [Direct package usage](#direct-package-usage) below. `nextrush` only adds the pre-wired router and the convenience barrel; nothing it re-exports is otherwise inaccessible.
202
440
 
203
- ### Advanced (install separately)
441
+ **Why ESM-only?**
442
+ See the [Module Format Policy](https://github.com/0xTanzim/nextRush#module-format-policy).
204
443
 
205
- | Package | Description |
206
- | ---------------------- | ------------------------------ |
207
- | `@nextrush/di` | Dependency injection container |
208
- | `@nextrush/decorators` | Controller & route decorators |
444
+ **Does it work on Bun / Deno / Edge?**
445
+ Not through `nextrush` itself - its `listen`/`serve` come from `@nextrush/adapter-node`. For other runtimes, import `@nextrush/core` + `@nextrush/router` + the matching `@nextrush/adapter-{bun,deno,edge}` directly; the functional API is otherwise identical, and parity across adapters is enforced by the conformance suite.
209
446
 
210
- ### Dev Tools
447
+ **Why are `@nextrush/class` and `@nextrush/di` peer dependencies instead of regular dependencies?**
448
+ So a functional-only install never downloads or resolves the class/DI stack (and its `tsyringe`/`reflect-metadata` supply-chain surface) - see [ADR-0009](https://github.com/0xTanzim/nextRush/blob/main/docs/adr/ADR-0009-framework-composition-and-functional-install-boundary.md).
211
449
 
212
- | Package | Description |
213
- | ----------------- | --------------------------------------------------------- |
214
- | `@nextrush/dev` | Hot reload dev server, production builds, code generators |
215
- | `create-nextrush` | Project scaffolder — `pnpm create nextrush`, `npx create-nextrush` ([usage](https://github.com/0xTanzim/nextRush/blob/main/packages/create-nextrush/README.md)) |
450
+ ---
216
451
 
217
452
  ## Direct Package Usage
218
453
 
219
- For maximum control, skip the meta package:
454
+ For maximum control, skip the meta package's convenience wrapping:
220
455
 
221
- ```typescript
456
+ ```ts
222
457
  import { createApp } from '@nextrush/core';
223
458
  import { createRouter } from '@nextrush/router';
224
459
  import { listen } from '@nextrush/adapter-node';
225
460
  import { cors } from '@nextrush/cors';
226
461
  ```
227
462
 
228
- ## Error Handling
229
-
230
- Built-in HTTP error classes:
463
+ `@nextrush/core`'s `createApp` does not inject a router - pass one explicitly
464
+ (`createApp({ router: createRouter() })`) if you take this path.
231
465
 
232
- ```typescript
233
- import { NotFoundError, BadRequestError, HttpError } from 'nextrush';
466
+ ## Package relationships
234
467
 
235
- app.use(async (ctx) => {
236
- if (!user) throw new NotFoundError('User not found');
237
- if (!valid) throw new BadRequestError('Invalid input');
238
- });
468
+ ```text
469
+ depends on @nextrush/core, @nextrush/router, @nextrush/adapter-node
470
+ nextrush --------------------------> @nextrush/errors, @nextrush/types
471
+ optional peer @nextrush/class, @nextrush/di, reflect-metadata
472
+ usually used next @nextrush/cors, @nextrush/body-parser, any middleware/extension
239
473
  ```
240
474
 
241
- ## Version
475
+ - **Depends on:** [`@nextrush/core`](../core), [`@nextrush/router`](../router), [`@nextrush/adapter-node`](../adapters/node), [`@nextrush/errors`](../errors), [`@nextrush/types`](../types) - hard dependencies, resolved on every install.
476
+ - **Optional peer:** [`@nextrush/class`](../class), [`@nextrush/di`](../di), `reflect-metadata` - resolved only if you install them, for `nextrush/class`.
477
+ - **Often used with:** [`create-nextrush`](https://github.com/0xTanzim/nextRush/tree/main/packages/create-nextrush) - scaffolds a project that already depends on `nextrush` correctly configured.
478
+ - **Usually used next:** any middleware package (`@nextrush/cors`, `@nextrush/body-parser`, `@nextrush/helmet`, ...) - see the [package catalog](https://0xtanzim.github.io/nextRush/docs/resources/package-catalog).
479
+ - **Alternative:** [`@nextrush/core`](../core) directly, if you're building your own meta-package or adapter and don't want the pre-wired router.
242
480
 
243
- ```typescript
244
- import { VERSION } from 'nextrush';
245
- console.log(VERSION); // '3.0.5'
246
- ```
481
+ ## Architecture
482
+
483
+ Maintaining or contributing to this package? The internal design - the exports-map routing
484
+ between the root entry and the `nextrush/class` subpath, the dynamic-import/re-export-by-
485
+ assignment mechanism that turns a missing optional peer into an actionable error, the single-DI-
486
+ instance guarantee, and the decisions and trade-offs behind them (with diagrams) - is in
487
+ **[`ARCHITECTURE.md`](./ARCHITECTURE.md)**. Design history:
488
+ [RFC-020 - framework composition integrity](https://github.com/0xTanzim/nextRush/tree/main/docs/RFC/framework-composition/020-framework-composition-integrity.md),
489
+ [ADR-0009](https://github.com/0xTanzim/nextRush/blob/main/docs/adr/ADR-0009-framework-composition-and-functional-install-boundary.md).
490
+
491
+ ## Resources
492
+
493
+ - **Learn** - [Documentation](https://0xtanzim.github.io/nextRush/docs) | [Getting started](https://0xtanzim.github.io/nextRush/docs/getting-started) | [Architecture](./ARCHITECTURE.md) | [RFCs](https://github.com/0xTanzim/nextRush/tree/main/docs/RFC)
494
+ - **Changelog** - [CHANGELOG.md](./CHANGELOG.md)
495
+ - **Migration** - [Framework composition migration guide](https://github.com/0xTanzim/nextRush/blob/main/docs/guides/migration-framework-composition.md)
496
+ - **Examples** - [create-nextrush templates](https://github.com/0xTanzim/nextRush/tree/main/packages/create-nextrush)
497
+ - **Report an issue** - [GitHub Issues](https://github.com/0xTanzim/nextRush/issues)
498
+ - **Contribute** - [CONTRIBUTING.md](https://github.com/0xTanzim/nextRush/blob/main/CONTRIBUTING.md)
247
499
 
248
- ## License
500
+ ---
249
501
 
250
- MIT © [Tanzim Hossain](https://github.com/0xTanzim)
502
+ MIT (c) [Tanzim Hossain](https://github.com/0xTanzim)
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `nextrush` meta-package launcher (ADR-0013).
4
+ *
5
+ * Delegates to the optional `@nextrush/dev` toolkit when installed, or prints an actionable
6
+ * install message when it is absent. All logic lives in `dev-cli-launcher.ts`; this file is only
7
+ * the executable entry point and never runs at install time (only on explicit `nextrush <command>`).
8
+ */
9
+ import { runDevCliLauncher } from '../dist/dev-cli-launcher.js';
10
+
11
+ runDevCliLauncher(process.argv.slice(2))
12
+ .then((code) => {
13
+ process.exit(code);
14
+ })
15
+ .catch((err) => {
16
+ // Unrelated error surfaced unchanged (not the missing-toolkit case).
17
+ console.error(err);
18
+ process.exit(1);
19
+ });