nextrush 3.0.5 → 4.0.0-beta.0

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
77
+ ```
78
+
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:
95
+
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`
37
99
  ```
38
100
 
39
- ## Quick Start
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
40
107
 
41
- ```typescript
108
+ ```ts
42
109
  import { createApp, createRouter, listen } from 'nextrush';
43
110
 
44
111
  const app = createApp();
@@ -50,33 +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
142
+
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
146
+
147
+ **Class-based (opt-in, via `nextrush/class`)**
148
+ - **Decorators, DI, controllers, modules, guards, interceptors, filters** - see [Class-based controllers](#class-based-controllers)
149
+
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
153
+
154
+ ## Mental model
155
+
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.
157
+
158
+ ```text
159
+ 'nextrush' ---> re-exports @nextrush/{core,router,adapter-node,errors,types}
160
+ (createApp wraps @nextrush/core's, injecting a default router)
161
+
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).
57
172
 
58
- Benchmark snapshot from a single lab machine (Intel i5-8300H, 8 cores) running Node.js v25.1.0.
59
- See https://github.com/0xTanzim/nextRush/blob/main/apps/docs/content/docs/performance/index.mdx for methodology, versions, and reproducible scripts.
173
+ ---
60
174
 
61
- | Framework | Hello World | POST JSON | Mixed Workload |
62
- | --------------- | -------------- | -------------- | -------------- |
63
- | Fastify | 48,045 RPS | 21,412 RPS | 48,493 RPS |
64
- | **NextRush v3** | **43,268 RPS** | **20,438 RPS** | **43,283 RPS** |
65
- | Hono | 37,476 RPS | 12,625 RPS | 38,759 RPS |
66
- | Koa | 34,683 RPS | 17,664 RPS | 35,566 RPS |
67
- | Express | 23,739 RPS | 14,417 RPS | 23,783 RPS |
175
+ ## Common tasks
68
176
 
69
- > Performance varies by hardware. See [Performance](https://github.com/0xTanzim/nextRush/blob/main/apps/docs/content/docs/performance/index.mdx) for methodology and numbers.
177
+ ### Build a functional app
70
178
 
71
- ## Adding Middleware
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
72
189
 
73
- Install what you need:
190
+ listen(app, 8080);
191
+ ```
192
+
193
+ ### Add middleware
74
194
 
75
195
  ```bash
76
196
  pnpm add @nextrush/cors @nextrush/body-parser
77
197
  ```
78
198
 
79
- ```typescript
199
+ ```ts
80
200
  import { createApp, listen } from 'nextrush';
81
201
  import { cors } from '@nextrush/cors';
82
202
  import { json } from '@nextrush/body-parser';
@@ -86,29 +206,57 @@ const app = createApp();
86
206
  app.use(cors());
87
207
  app.use(json());
88
208
 
89
- app.use((ctx) => {
90
- 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 });
91
213
  });
92
214
 
93
- listen(app, 3000);
215
+ listen(app, 8080);
94
216
  ```
95
217
 
96
- ## Class-Based Controllers
218
+ ### Handle errors
97
219
 
98
- Class-based APIs (decorators, DI, controllers) are available via the `nextrush/class` subpath:
220
+ ```ts
221
+ import { NotFoundError, BadRequestError } from 'nextrush';
99
222
 
100
- - `nextrush` — Functional API (`createApp`, `createRouter`, `listen`, errors, types)
101
- - `nextrush/class` Class-based API (`Controller`, `Get`, `Service`, `controllersPlugin`, etc.)
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
+ ```
229
+
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.
102
233
 
103
- The `nextrush/class` entry auto-imports `reflect-metadata`, so you can use decorators and DI without any extra setup:
234
+ ### Scaffold a project
104
235
 
105
236
  ```bash
106
- pnpm add nextrush
237
+ pnpm create nextrush my-api
238
+ cd my-api && pnpm dev
107
239
  ```
108
240
 
109
- ```typescript
110
- import { createApp, createRouter, listen } from 'nextrush';
111
- 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';
112
260
 
113
261
  @Service()
114
262
  class GreetService {
@@ -128,108 +276,227 @@ class HelloController {
128
276
  }
129
277
 
130
278
  const app = createApp();
131
- const router = createRouter();
279
+ await registerControllers(app, { root: './src' });
280
+ await listen(app, 8080);
281
+ ```
132
282
 
133
- app.plugin(controllersPlugin({ router, root: './src' }));
134
- app.route('/', router);
135
- 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
136
402
  ```
137
403
 
138
- > **`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>
139
405
 
140
- ## What's Included
406
+ <details>
407
+ <summary><strong>Decorators throw or metadata is missing at runtime</strong></summary>
141
408
 
142
- 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:
143
412
 
144
- | Package | Exports |
145
- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
146
- | `@nextrush/core` | `createApp`, `Application`, `compose` |
147
- | `@nextrush/router` | `createRouter`, `Router` |
148
- | `@nextrush/adapter-node` | `listen`, `serve`, `createHandler` |
149
- | `@nextrush/types` | `Context`, `Middleware`, `Next`, `Plugin`, `RouteHandler`, `HttpMethod`, `HttpStatus`, `ContentType` |
150
- | `@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
+ ```
151
421
 
152
- ## Available Packages
422
+ </details>
153
423
 
154
- ### Core (included in nextrush)
424
+ <details>
425
+ <summary><strong><code>app.get(...)</code> throws <code>No router configured</code></strong></summary>
155
426
 
156
- | Package | Description |
157
- | ------------------------ | ------------------------------------ |
158
- | `@nextrush/core` | Application & middleware composition |
159
- | `@nextrush/router` | High-performance radix tree router |
160
- | `@nextrush/adapter-node` | Node.js HTTP adapter |
161
- | `@nextrush/types` | Shared TypeScript types |
162
- | `@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:
163
429
 
164
- ### Middleware (install separately)
430
+ ```ts
431
+ import { createApp } from 'nextrush'; // injects a router; app.get works
432
+ ```
165
433
 
166
- | Package | Description |
167
- | ----------------------- | -------------------------------------- |
168
- | `@nextrush/body-parser` | JSON/form/text body parsing |
169
- | `@nextrush/cors` | CORS headers |
170
- | `@nextrush/helmet` | Security headers |
171
- | `@nextrush/cookies` | Cookie handling |
172
- | `@nextrush/compression` | Response compression (gzip/brotli) |
173
- | `@nextrush/rate-limit` | Rate limiting with multiple algorithms |
174
- | `@nextrush/request-id` | Request ID generation |
175
- | `@nextrush/timer` | Request timing headers |
434
+ </details>
176
435
 
177
- ### Plugins (install separately)
436
+ ## FAQ
178
437
 
179
- | Package | Description |
180
- | ----------------------- | ------------------------------- |
181
- | `@nextrush/logger` | Structured logging |
182
- | `@nextrush/static` | Static file serving |
183
- | `@nextrush/websocket` | WebSocket support with rooms |
184
- | `@nextrush/template` | Multi-engine template rendering |
185
- | `@nextrush/events` | Type-safe event emitter |
186
- | `@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.
187
440
 
188
- ### Advanced (install separately)
441
+ **Why ESM-only?**
442
+ See the [Module Format Policy](https://github.com/0xTanzim/nextRush#module-format-policy).
189
443
 
190
- | Package | Description |
191
- | ---------------------- | ------------------------------ |
192
- | `@nextrush/di` | Dependency injection container |
193
- | `@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.
194
446
 
195
- ### 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).
196
449
 
197
- | Package | Description |
198
- | ----------------- | --------------------------------------------------------- |
199
- | `@nextrush/dev` | Hot reload dev server, production builds, code generators |
200
- | `create-nextrush` | Project scaffolder — `pnpm create nextrush`, `npx create-nextrush` ([usage](https://github.com/0xTanzim/nextRush/blob/main/packages/create-nextrush/README.md)) |
450
+ ---
201
451
 
202
452
  ## Direct Package Usage
203
453
 
204
- For maximum control, skip the meta package:
454
+ For maximum control, skip the meta package's convenience wrapping:
205
455
 
206
- ```typescript
456
+ ```ts
207
457
  import { createApp } from '@nextrush/core';
208
458
  import { createRouter } from '@nextrush/router';
209
459
  import { listen } from '@nextrush/adapter-node';
210
460
  import { cors } from '@nextrush/cors';
211
461
  ```
212
462
 
213
- ## Error Handling
214
-
215
- 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.
216
465
 
217
- ```typescript
218
- import { NotFoundError, BadRequestError, HttpError } from 'nextrush';
466
+ ## Package relationships
219
467
 
220
- app.use(async (ctx) => {
221
- if (!user) throw new NotFoundError('User not found');
222
- if (!valid) throw new BadRequestError('Invalid input');
223
- });
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
224
473
  ```
225
474
 
226
- ## 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.
227
480
 
228
- ```typescript
229
- import { VERSION } from 'nextrush';
230
- console.log(VERSION); // '3.0.4'
231
- ```
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)
232
499
 
233
- ## License
500
+ ---
234
501
 
235
- 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
+ });
@@ -0,0 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ export {
5
+ __name
6
+ };
7
+ //# sourceMappingURL=chunk-7QVYU63E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}