@smounters/imperium 1.1.0 → 1.1.2

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.
Files changed (66) hide show
  1. package/README.md +40 -199
  2. package/dist/core/app-tokens.d.ts +1 -1
  3. package/dist/core/application.d.ts +2 -2
  4. package/dist/core/application.js +2 -2
  5. package/dist/core/container.d.ts +2 -2
  6. package/dist/core/container.js +10 -12
  7. package/dist/core/index.d.ts +5 -5
  8. package/dist/core/index.js +4 -4
  9. package/dist/core/logger.d.ts +1 -1
  10. package/dist/core/reflector.d.ts +1 -1
  11. package/dist/core/reflector.js +1 -1
  12. package/dist/core/server.d.ts +2 -2
  13. package/dist/core/server.js +8 -7
  14. package/dist/decorators/di.decorators.d.ts +1 -1
  15. package/dist/decorators/filters.decorators.d.ts +1 -1
  16. package/dist/decorators/filters.decorators.js +2 -2
  17. package/dist/decorators/guards.decorators.d.ts +1 -1
  18. package/dist/decorators/guards.decorators.js +1 -1
  19. package/dist/decorators/http.decorators.js +1 -1
  20. package/dist/decorators/index.d.ts +9 -9
  21. package/dist/decorators/index.js +9 -9
  22. package/dist/decorators/interceptors.decorators.d.ts +1 -1
  23. package/dist/decorators/interceptors.decorators.js +1 -1
  24. package/dist/decorators/metadata.decorators.d.ts +1 -1
  25. package/dist/decorators/pipes.decorators.d.ts +1 -1
  26. package/dist/decorators/pipes.decorators.js +1 -1
  27. package/dist/decorators/rpc.decorators.d.ts +1 -1
  28. package/dist/decorators/rpc.decorators.js +1 -1
  29. package/dist/decorators/ws.decorators.js +1 -1
  30. package/dist/http/adapter.d.ts +2 -2
  31. package/dist/http/adapter.js +5 -5
  32. package/dist/http/index.d.ts +3 -3
  33. package/dist/http/index.js +3 -3
  34. package/dist/http/router-builder.d.ts +1 -1
  35. package/dist/http/router-builder.js +2 -2
  36. package/dist/http/utils.d.ts +1 -1
  37. package/dist/http/utils.js +5 -5
  38. package/dist/pipes/index.d.ts +1 -1
  39. package/dist/pipes/index.js +1 -1
  40. package/dist/pipes/zod.pipe.d.ts +1 -1
  41. package/dist/rpc/adapter.d.ts +2 -2
  42. package/dist/rpc/adapter.js +5 -5
  43. package/dist/rpc/index.d.ts +4 -4
  44. package/dist/rpc/index.js +4 -4
  45. package/dist/rpc/router-builder.d.ts +1 -1
  46. package/dist/rpc/router-builder.js +3 -3
  47. package/dist/rpc/streaming-adapter.d.ts +2 -2
  48. package/dist/rpc/streaming-adapter.js +5 -5
  49. package/dist/rpc/utils.d.ts +1 -1
  50. package/dist/rpc/utils.js +5 -5
  51. package/dist/services/config.service.js +2 -2
  52. package/dist/services/index.d.ts +2 -2
  53. package/dist/services/index.js +2 -2
  54. package/dist/services/logger.service.d.ts +1 -1
  55. package/dist/services/logger.service.js +2 -2
  56. package/dist/types.d.ts +5 -6
  57. package/dist/validation/app-config.js +1 -1
  58. package/dist/validation/index.d.ts +2 -2
  59. package/dist/validation/index.js +2 -2
  60. package/dist/ws/adapter.d.ts +2 -2
  61. package/dist/ws/adapter.js +8 -7
  62. package/dist/ws/index.d.ts +3 -3
  63. package/dist/ws/index.js +2 -2
  64. package/dist/ws/router-builder.d.ts +1 -1
  65. package/dist/ws/router-builder.js +2 -2
  66. package/package.json +9 -3
package/README.md CHANGED
@@ -1,41 +1,24 @@
1
1
  # @smounters/imperium
2
2
 
3
- `@smounters/imperium` is **inspired by NestJS** and provides a modular DI-first runtime for TypeScript services using Fastify + ConnectRPC + WebSocket.
3
+ NestJS-inspired modular DI framework for TypeScript services. Unified HTTP + ConnectRPC + WebSocket server on a single Fastify instance.
4
4
 
5
- It is designed for teams that want Nest-like architecture but with explicit control over runtime wiring and exported API surface.
5
+ ## Features
6
6
 
7
- ## Key Features
7
+ - **Module system** with `@Module`, `@Injectable`, guards, pipes, interceptors, filters
8
+ - **HTTP controllers** with `@HttpController`, `@Get`, `@Post`, `@Body`, `@Query`, `@Param`
9
+ - **ConnectRPC** with `@RpcService`, `@RpcMethod` (unary + server streaming)
10
+ - **WebSocket gateway** with `@WsGateway`, `@WsHandler`, message routing, lifecycle hooks
11
+ - **Request-scoped DI** via AsyncLocalStorage (tsyringe-based)
12
+ - **Typed config** via Zod + `ConfigService`
13
+ - **Structured logging** via tslog + `LoggerService`
8
14
 
9
- - Nest-like modules and decorators (`@Module`, `@Injectable`, guards/pipes/interceptors/filters).
10
- - Unified HTTP + RPC + WebSocket server on one Fastify instance.
11
- - Server streaming RPC via `async function*` (delivered as SSE in browsers).
12
- - WebSocket gateway with message routing, lifecycle hooks, and guards at connection time.
13
- - Request-scoped handler execution.
14
- - Typed runtime config via `zod` + `ConfigService`.
15
- - Built-in `LoggerService` (tslog-based).
16
- - Global enhancer tokens (`APP_GUARD`, `APP_PIPE`, `APP_INTERCEPTOR`, `APP_FILTER`).
17
- - Multi-provider array injection (`InjectAll`) and manual array resolution (`resolveAll`).
18
-
19
- ## Public Imports
20
-
21
- Root import is intentionally disabled.
22
-
23
- Use subpaths only:
24
-
25
- - `@smounters/imperium/core`
26
- - `@smounters/imperium/decorators`
27
- - `@smounters/imperium/services`
28
- - `@smounters/imperium/pipes`
29
- - `@smounters/imperium/validation`
30
- - `@smounters/imperium/ws`
31
-
32
- ## Installation
15
+ ## Install
33
16
 
34
17
  ```bash
35
- pnpm add @smounters/imperium reflect-metadata tsyringe fastify @connectrpc/connect @connectrpc/connect-fastify zod
18
+ pnpm add @smounters/imperium reflect-metadata tsyringe fastify @connectrpc/connect @connectrpc/connect-fastify zod tslog
36
19
  ```
37
20
 
38
- TypeScript requirements:
21
+ TypeScript config requires:
39
22
 
40
23
  ```json
41
24
  {
@@ -46,220 +29,78 @@ TypeScript requirements:
46
29
  }
47
30
  ```
48
31
 
49
- Entry point must import metadata:
50
-
51
- ```ts
52
- import "reflect-metadata";
53
- ```
54
-
55
32
  ## Quick Start
56
33
 
57
34
  ```ts
58
35
  import "reflect-metadata";
59
-
60
36
  import { Application } from "@smounters/imperium/core";
61
37
  import { Body, HttpController, Injectable, Module, Post } from "@smounters/imperium/decorators";
62
38
 
63
39
  @Injectable()
64
- class AuthService {
65
- signIn(email: string) {
66
- return { ok: true, email };
40
+ class GreetService {
41
+ greet(name: string) {
42
+ return { message: `Hello, ${name}` };
67
43
  }
68
44
  }
69
45
 
70
- @HttpController("/auth")
71
- class AuthHttpController {
72
- constructor(private readonly authService: AuthService) {}
46
+ @HttpController("/api")
47
+ class ApiController {
48
+ constructor(private readonly greetService: GreetService) {}
73
49
 
74
- @Post("/sign-in")
75
- signIn(@Body("email") email: string) {
76
- return this.authService.signIn(email);
50
+ @Post("/greet")
51
+ greet(@Body("name") name: string) {
52
+ return this.greetService.greet(name);
77
53
  }
78
54
  }
79
55
 
80
56
  @Module({
81
- providers: [AuthService],
82
- httpControllers: [AuthHttpController],
57
+ providers: [GreetService],
58
+ httpControllers: [ApiController],
83
59
  })
84
60
  class AppModule {}
85
61
 
86
- const app = new Application(AppModule, {
87
- host: "0.0.0.0",
88
- accessLogs: true,
89
- });
90
-
91
- await app.start({ port: 3000 });
92
- ```
93
-
94
- ## Recommended Bootstrap Flow
95
-
96
- ```ts
97
- import { Application } from "@smounters/imperium/core";
98
- import { ConfigService, LoggerService } from "@smounters/imperium/services";
99
- import { appConfigSchema, type AppConfig } from "@smounters/imperium/validation";
100
-
101
- const app = new Application(AppModule, {
102
- host: "0.0.0.0",
103
- accessLogs: true,
104
- });
105
-
106
- app.configureConfig(appConfigSchema, process.env);
107
-
108
- const config = app.resolve(ConfigService<AppConfig>).getAll();
109
-
110
- app.configureLogger({
111
- name: "backend",
112
- minLevel: 3,
113
- });
114
-
115
- await app.start({
116
- port: config.APP_PORT,
117
- prefix: config.APP_GLOBAL_PREFIX,
118
- });
119
-
120
- app.resolve(LoggerService).info({ event: "app.started", port: config.APP_PORT });
62
+ await new Application(AppModule).start({ port: 3000 });
121
63
  ```
122
64
 
123
- If your app needs extra config fields, extend the exported base schema:
124
-
125
- ```ts
126
- import { appConfigSchema } from "@smounters/imperium/validation";
127
- import { z } from "zod";
128
-
129
- const projectConfigSchema = appConfigSchema.extend({
130
- REDIS_URL: z.url(),
131
- });
132
- ```
133
-
134
- ## Multi Providers
135
-
136
- ```ts
137
- import { InjectAll, Injectable, Module } from "@smounters/imperium/decorators";
138
-
139
- const AML_RULES = Symbol("AML_RULES");
140
-
141
- @Module({
142
- providers: [
143
- { provide: AML_RULES, multi: true, useClass: SanctionsRule },
144
- { provide: AML_RULES, multi: true, useClass: MixerRule },
145
- { provide: AML_RULES, multi: true, useClass: FreshAddressRule },
146
- ],
147
- exports: [AML_RULES],
148
- })
149
- class AmlModule {}
150
-
151
- @Injectable()
152
- class AmlEngine {
153
- constructor(@InjectAll(AML_RULES) private readonly rules: AmlRule[]) {}
154
- }
155
- ```
156
-
157
- Manual resolution is also available:
158
-
159
- ```ts
160
- const rules = app.resolveAll<AmlRule>(AML_RULES);
161
- ```
162
-
163
- ## HTTP and RPC
164
-
165
- Use decorators from `@smounters/imperium/decorators`:
166
-
167
- - HTTP: `HttpController`, `Get`, `Post`, `Put`, `Patch`, `Delete`, `Body`, `Query`, `Param`, `Header`, `Req`, `Res`
168
- - RPC: `RpcService`, `RpcMethod`, `RpcData`, `RpcContext`, `RpcHeaders`, `RpcHeader`, `RpcAbortSignal`
169
- - WebSocket: `WsGateway`, `WsHandler`, `WsConnection`, `WsMessage`, `WsRequest`
170
-
171
- Imperium auto-detects registered HTTP/RPC/WebSocket handlers and serves all protocols from one server.
172
-
173
65
  ## WebSocket
174
66
 
175
67
  ```ts
176
- import { WsGateway, WsHandler, WsConnection, WsMessage, Module } from "@smounters/imperium/decorators";
68
+ import { WsGateway, WsHandler, WsConnection, WsMessage } from "@smounters/imperium/decorators";
177
69
  import type { WsGatewayLifecycle } from "@smounters/imperium/ws";
178
70
  import type { WebSocket } from "@fastify/websocket";
179
71
 
180
72
  @WsGateway("/ws")
181
- class ChatGateway implements WsGatewayLifecycle {
73
+ class EventsGateway implements WsGatewayLifecycle {
182
74
  private clients = new Set<WebSocket>();
183
75
 
184
76
  onConnection(socket: WebSocket) { this.clients.add(socket); }
185
77
  onDisconnect(socket: WebSocket) { this.clients.delete(socket); }
186
78
 
187
- @WsHandler("message")
188
- onMessage(@WsConnection() ws: WebSocket, @WsMessage() data: { text: string }) {
189
- const msg = JSON.stringify({ type: "message", data });
190
- for (const client of this.clients) {
191
- if (client.readyState === 1) client.send(msg);
192
- }
79
+ @WsHandler("ping")
80
+ onPing(@WsConnection() ws: WebSocket) {
81
+ ws.send(JSON.stringify({ type: "pong" }));
193
82
  }
194
83
  }
195
-
196
- @Module({ providers: [ChatGateway] })
197
- class AppModule {}
198
84
  ```
199
85
 
200
86
  Requires optional peer dependency: `pnpm add @fastify/websocket`
201
87
 
202
- ## Services
203
-
204
- From `@smounters/imperium/services`:
205
-
206
- - `ConfigService`
207
- - `LoggerService`
208
-
209
- ## Pipes and Validation
210
-
211
- - `ZodPipe` from `@smounters/imperium/pipes`
212
- - validation helpers from `@smounters/imperium/validation`
213
- - `appConfigSchema`
214
- - `AppConfig`
215
- - `booleanSchema`
216
- - `numberSchema`
217
- - `nativeEnumSchema`
218
- - `stringArraySchema`
219
- - `enumArraySchema`
220
-
221
- ## Error Classes
222
-
223
- From `@smounters/imperium/core`:
88
+ ## Import Paths
224
89
 
225
- - `HttpException`
226
- - `BadRequestException`
227
- - `UnauthorizedException`
228
- - `ForbiddenException`
229
- - `NotFoundException`
230
- - `InternalServerErrorException`
90
+ No root import. Use subpaths:
231
91
 
232
- ## Documentation
233
-
234
- Full docs (VitePress) are located in:
235
-
236
- - `docs`
237
-
238
- Local docs commands:
239
-
240
- ```bash
241
- pnpm run docs:dev
242
- pnpm run docs:build
243
- ```
244
-
245
- GitHub Pages deployment is configured via `.github/workflows/publish.yml`.
246
-
247
- ## Publish to npm
248
-
249
- ```bash
250
- pnpm install
251
- pnpm run typecheck
252
- pnpm run build
253
- pnpm publish --access public --no-git-checks
92
+ ```ts
93
+ import { Application } from "@smounters/imperium/core";
94
+ import { Module, Injectable, HttpController, Get } from "@smounters/imperium/decorators";
95
+ import { ConfigService, LoggerService } from "@smounters/imperium/services";
96
+ import { ZodPipe } from "@smounters/imperium/pipes";
97
+ import { appConfigSchema } from "@smounters/imperium/validation";
98
+ import { registerWsGateways } from "@smounters/imperium/ws";
254
99
  ```
255
100
 
256
- Automated npm publishing workflow:
257
-
258
- - `.github/workflows/publish.yml`
259
-
260
- Required secret:
101
+ ## Documentation
261
102
 
262
- - `NPM_TOKEN`
103
+ Full guide and API reference: **[smounters.github.io/imperium](https://smounters.github.io/imperium/)**
263
104
 
264
105
  ## License
265
106
 
@@ -1,4 +1,4 @@
1
- import type { ExceptionFilterLike, GuardLike, InjectionToken, InterceptorLike, PipeLike } from "../types";
1
+ import type { ExceptionFilterLike, GuardLike, InjectionToken, InterceptorLike, PipeLike } from "../types.js";
2
2
  export declare const APP_GUARD: InjectionToken<GuardLike>;
3
3
  export declare const APP_INTERCEPTOR: InjectionToken<InterceptorLike>;
4
4
  export declare const APP_PIPE: InjectionToken<PipeLike>;
@@ -1,7 +1,7 @@
1
1
  import type { FastifyInstance } from "fastify";
2
- import type { InjectionToken, LoggerOptions, ModuleImport, ServerOptions } from "../types";
2
+ import type { InjectionToken, LoggerOptions, ModuleImport, ServerOptions } from "../types.js";
3
3
  import type { ZodType, output } from "zod";
4
- import { AppContainer } from "./container";
4
+ import { AppContainer } from "./container.js";
5
5
  export declare class Application {
6
6
  private static readonly DEFAULT_SHUTDOWN_SIGNALS;
7
7
  private static readonly DEFAULT_SHUTDOWN_TIMEOUT_MS;
@@ -1,5 +1,5 @@
1
- import { AppContainer } from "./container";
2
- import { startServer } from "./server";
1
+ import { AppContainer } from "./container.js";
2
+ import { startServer } from "./server.js";
3
3
  export class Application {
4
4
  static { this.DEFAULT_SHUTDOWN_SIGNALS = ["SIGINT", "SIGTERM"]; }
5
5
  static { this.DEFAULT_SHUTDOWN_TIMEOUT_MS = 15_000; }
@@ -1,8 +1,8 @@
1
1
  import "reflect-metadata";
2
2
  import { type DependencyContainer } from "tsyringe";
3
- import type { Constructor, ExceptionFilterLike, GuardLike, InjectionToken, InterceptorLike, LoggerOptions, ModuleImport, PipeLike } from "../types";
3
+ import type { Constructor, ExceptionFilterLike, GuardLike, InjectionToken, InterceptorLike, LoggerOptions, ModuleImport, PipeLike } from "../types.js";
4
4
  import type { ZodType, output } from "zod";
5
- import { type AppLogger } from "./logger";
5
+ import { type AppLogger } from "./logger.js";
6
6
  export declare class AppContainer {
7
7
  private readonly root;
8
8
  private readonly loadedModules;
@@ -1,13 +1,13 @@
1
1
  import "reflect-metadata";
2
2
  import { container, Lifecycle } from "tsyringe";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
- import { MODULE_KEY } from "../decorators/di.decorators";
5
- import { WS_GATEWAY_KEY } from "../decorators/ws.decorators";
6
- import { ConfigService, LoggerService } from "../services";
7
- import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens";
8
- import { CONFIG_TOKEN } from "./config";
9
- import { createLogger, LOGGER_TOKEN } from "./logger";
10
- import { Reflector } from "./reflector";
4
+ import { MODULE_KEY } from "../decorators/di.decorators.js";
5
+ import { WS_GATEWAY_KEY } from "../decorators/ws.decorators.js";
6
+ import { ConfigService, LoggerService } from "../services/index.js";
7
+ import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens.js";
8
+ import { CONFIG_TOKEN } from "./config.js";
9
+ import { createLogger, LOGGER_TOKEN } from "./logger.js";
10
+ import { Reflector } from "./reflector.js";
11
11
  function isDynamicModule(value) {
12
12
  return typeof value === "object" && value !== null && "module" in value && typeof value.module === "function";
13
13
  }
@@ -229,7 +229,7 @@ export class AppContainer {
229
229
  return provider.useValue;
230
230
  }
231
231
  if ("useFactory" in provider) {
232
- return provider.useFactory(moduleRef.container);
232
+ return (provider).useFactory(moduleRef.container);
233
233
  }
234
234
  if ("useExisting" in provider) {
235
235
  return moduleRef.container.resolve(provider.useExisting);
@@ -281,7 +281,7 @@ export class AppContainer {
281
281
  }
282
282
  if ("useFactory" in provider) {
283
283
  moduleRef.container.register(provider.provide, {
284
- useFactory: (dc) => provider.useFactory(dc),
284
+ useFactory: (dc) => (provider).useFactory(dc),
285
285
  });
286
286
  return;
287
287
  }
@@ -467,9 +467,7 @@ export class AppContainer {
467
467
  }
468
468
  loadModule(moduleImport) {
469
469
  const moduleRef = this.loadModuleRef(moduleImport);
470
- if (!this.rootModuleRef) {
471
- this.rootModuleRef = moduleRef;
472
- }
470
+ this.rootModuleRef ??= moduleRef;
473
471
  }
474
472
  resolve(token) {
475
473
  if (this.root.isRegistered(token, false)) {
@@ -1,5 +1,5 @@
1
- export { Application } from "./application";
2
- export { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens";
3
- export { BadRequestException, ForbiddenException, HttpException, InternalServerErrorException, NotFoundException, UnauthorizedException, } from "./errors";
4
- export { Reflector } from "./reflector";
5
- export type * from "../types";
1
+ export { Application } from "./application.js";
2
+ export { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens.js";
3
+ export { BadRequestException, ForbiddenException, HttpException, InternalServerErrorException, NotFoundException, UnauthorizedException, } from "./errors.js";
4
+ export { Reflector } from "./reflector.js";
5
+ export type * from "../types.js";
@@ -1,4 +1,4 @@
1
- export { Application } from "./application";
2
- export { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens";
3
- export { BadRequestException, ForbiddenException, HttpException, InternalServerErrorException, NotFoundException, UnauthorizedException, } from "./errors";
4
- export { Reflector } from "./reflector";
1
+ export { Application } from "./application.js";
2
+ export { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from "./app-tokens.js";
3
+ export { BadRequestException, ForbiddenException, HttpException, InternalServerErrorException, NotFoundException, UnauthorizedException, } from "./errors.js";
4
+ export { Reflector } from "./reflector.js";
@@ -1,5 +1,5 @@
1
1
  import { Logger } from "tslog";
2
- import type { LoggerOptions } from "../types";
2
+ import type { LoggerOptions } from "../types.js";
3
3
  type LoggerPayload = Record<string, unknown>;
4
4
  export type AppLogger = Logger<LoggerPayload>;
5
5
  export declare const LOGGER_TOKEN: unique symbol;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import type { MetadataKey } from "../types";
2
+ import type { MetadataKey } from "../types.js";
3
3
  type MetadataTarget = object | Function | undefined;
4
4
  export declare class Reflector {
5
5
  get<T = unknown>(metadataKey: MetadataKey, target: MetadataTarget): T | undefined;
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import "reflect-metadata";
8
- import { Injectable } from "../decorators/di.decorators";
8
+ import { Injectable } from "../decorators/di.decorators.js";
9
9
  let Reflector = class Reflector {
10
10
  get(metadataKey, target) {
11
11
  if (!target) {
@@ -1,7 +1,7 @@
1
1
  import "reflect-metadata";
2
2
  import { type FastifyInstance } from "fastify";
3
- import type { ServerOptions } from "../types";
4
- import { AppContainer } from "./container";
3
+ import type { ServerOptions } from "../types.js";
4
+ import { AppContainer } from "./container.js";
5
5
  type LegacyServerOptions = ServerOptions & {
6
6
  di: AppContainer;
7
7
  };
@@ -2,12 +2,12 @@ import "reflect-metadata";
2
2
  import { fastifyConnectPlugin } from "@connectrpc/connect-fastify";
3
3
  import fastifyCors from "@fastify/cors";
4
4
  import Fastify from "fastify";
5
- import { HTTP_ROUTES_KEY } from "../decorators/http.decorators";
6
- import { RPC_METHODS_KEY, RPC_SERVICE_KEY } from "../decorators/rpc.decorators";
7
- import { registerHttpRoutes } from "../http";
8
- import { buildConnectRoutes } from "../rpc";
9
- import { registerWsGateways } from "../ws";
10
- import { AppContainer } from "./container";
5
+ import { HTTP_ROUTES_KEY } from "../decorators/http.decorators.js";
6
+ import { RPC_METHODS_KEY, RPC_SERVICE_KEY } from "../decorators/rpc.decorators.js";
7
+ import { registerHttpRoutes } from "../http/index.js";
8
+ import { buildConnectRoutes } from "../rpc/index.js";
9
+ import { registerWsGateways } from "../ws/index.js";
10
+ import { AppContainer } from "./container.js";
11
11
  function normalizePrefix(prefix) {
12
12
  if (!prefix) {
13
13
  return "";
@@ -179,9 +179,10 @@ export async function startServer(diOrOptions, options) {
179
179
  const corsConfig = resolveCors(cors);
180
180
  const effectiveHttpPrefix = mergePrefixes(prefix, httpPrefix);
181
181
  const effectiveRpcPrefix = mergePrefixes(prefix, rpcPrefix);
182
- server.addHook("onRequest", async (req) => {
182
+ server.addHook("onRequest", (req, _reply, done) => {
183
183
  const request = req;
184
184
  request.requestStartAt = Date.now();
185
+ done();
185
186
  });
186
187
  server.addHook("onResponse", async (req, reply) => {
187
188
  const request = req;
@@ -1,6 +1,6 @@
1
1
  import "reflect-metadata";
2
2
  import { inject, injectAll, injectable, Lifecycle } from "tsyringe";
3
- import type { InjectionToken, ModuleMeta } from "../types";
3
+ import type { InjectionToken, ModuleMeta } from "../types.js";
4
4
  export declare const MODULE_KEY: unique symbol;
5
5
  export declare function Module(meta: ModuleMeta): ClassDecorator;
6
6
  export declare const Injectable: typeof injectable;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import type { Constructor, ExceptionFilterLike } from "../types";
2
+ import type { Constructor, ExceptionFilterLike } from "../types.js";
3
3
  export declare const FILTERS_KEY: unique symbol;
4
4
  export declare const CATCH_EXCEPTIONS_KEY: unique symbol;
5
5
  export declare function UseFilters(...filters: ExceptionFilterLike[]): ClassDecorator & MethodDecorator;
@@ -1,6 +1,6 @@
1
1
  import "reflect-metadata";
2
- import { Injectable } from "./di.decorators";
3
- import { appendArrayMetadata } from "./metadata.decorators";
2
+ import { Injectable } from "./di.decorators.js";
3
+ import { appendArrayMetadata } from "./metadata.decorators.js";
4
4
  export const FILTERS_KEY = Symbol("filters");
5
5
  export const CATCH_EXCEPTIONS_KEY = Symbol("filter:exceptions");
6
6
  export function UseFilters(...filters) {
@@ -1,4 +1,4 @@
1
1
  import "reflect-metadata";
2
- import type { GuardLike } from "../types";
2
+ import type { GuardLike } from "../types.js";
3
3
  export declare const GUARDS_KEY: unique symbol;
4
4
  export declare function UseGuards(...guards: GuardLike[]): ClassDecorator & MethodDecorator;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { appendArrayMetadata } from "./metadata.decorators";
2
+ import { appendArrayMetadata } from "./metadata.decorators.js";
3
3
  export const GUARDS_KEY = Symbol("guards");
4
4
  export function UseGuards(...guards) {
5
5
  return (target, propertyKey) => {
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { Injectable } from "./di.decorators";
2
+ import { Injectable } from "./di.decorators.js";
3
3
  export const HTTP_ROUTES_KEY = Symbol("http:routes");
4
4
  export const HTTP_CONTROLLER_KEY = Symbol("http:controller");
5
5
  export const PARAMS_KEY = Symbol("http:params");
@@ -1,9 +1,9 @@
1
- export { Inject, InjectAll, Injectable, Module, Optional, Scope } from "./di.decorators";
2
- export { Catch, UseFilters } from "./filters.decorators";
3
- export { UseGuards } from "./guards.decorators";
4
- export { Body, Delete, Get, Header, HttpController, Param, Patch, Post, Put, Query, Req, Res } from "./http.decorators";
5
- export { UseInterceptors } from "./interceptors.decorators";
6
- export { SetMetadata } from "./metadata.decorators";
7
- export { UsePipes } from "./pipes.decorators";
8
- export { RpcAbortSignal, RpcContext, RpcData, RpcHeader, RpcHeaders, RpcMethod, RpcService } from "./rpc.decorators";
9
- export { WsConnection, WsGateway, WsHandler, WsMessage, WsRequest } from "./ws.decorators";
1
+ export { Inject, InjectAll, Injectable, Module, Optional, Scope } from "./di.decorators.js";
2
+ export { Catch, UseFilters } from "./filters.decorators.js";
3
+ export { UseGuards } from "./guards.decorators.js";
4
+ export { Body, Delete, Get, Header, HttpController, Param, Patch, Post, Put, Query, Req, Res } from "./http.decorators.js";
5
+ export { UseInterceptors } from "./interceptors.decorators.js";
6
+ export { SetMetadata } from "./metadata.decorators.js";
7
+ export { UsePipes } from "./pipes.decorators.js";
8
+ export { RpcAbortSignal, RpcContext, RpcData, RpcHeader, RpcHeaders, RpcMethod, RpcService } from "./rpc.decorators.js";
9
+ export { WsConnection, WsGateway, WsHandler, WsMessage, WsRequest } from "./ws.decorators.js";
@@ -1,9 +1,9 @@
1
- export { Inject, InjectAll, Injectable, Module, Optional, Scope } from "./di.decorators";
2
- export { Catch, UseFilters } from "./filters.decorators";
3
- export { UseGuards } from "./guards.decorators";
4
- export { Body, Delete, Get, Header, HttpController, Param, Patch, Post, Put, Query, Req, Res } from "./http.decorators";
5
- export { UseInterceptors } from "./interceptors.decorators";
6
- export { SetMetadata } from "./metadata.decorators";
7
- export { UsePipes } from "./pipes.decorators";
8
- export { RpcAbortSignal, RpcContext, RpcData, RpcHeader, RpcHeaders, RpcMethod, RpcService } from "./rpc.decorators";
9
- export { WsConnection, WsGateway, WsHandler, WsMessage, WsRequest } from "./ws.decorators";
1
+ export { Inject, InjectAll, Injectable, Module, Optional, Scope } from "./di.decorators.js";
2
+ export { Catch, UseFilters } from "./filters.decorators.js";
3
+ export { UseGuards } from "./guards.decorators.js";
4
+ export { Body, Delete, Get, Header, HttpController, Param, Patch, Post, Put, Query, Req, Res } from "./http.decorators.js";
5
+ export { UseInterceptors } from "./interceptors.decorators.js";
6
+ export { SetMetadata } from "./metadata.decorators.js";
7
+ export { UsePipes } from "./pipes.decorators.js";
8
+ export { RpcAbortSignal, RpcContext, RpcData, RpcHeader, RpcHeaders, RpcMethod, RpcService } from "./rpc.decorators.js";
9
+ export { WsConnection, WsGateway, WsHandler, WsMessage, WsRequest } from "./ws.decorators.js";
@@ -1,4 +1,4 @@
1
1
  import "reflect-metadata";
2
- import type { InterceptorLike } from "../types";
2
+ import type { InterceptorLike } from "../types.js";
3
3
  export declare const INTERCEPTORS_KEY: unique symbol;
4
4
  export declare function UseInterceptors(...inters: InterceptorLike[]): ClassDecorator & MethodDecorator;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { appendArrayMetadata } from "./metadata.decorators";
2
+ import { appendArrayMetadata } from "./metadata.decorators.js";
3
3
  export const INTERCEPTORS_KEY = Symbol("interceptors");
4
4
  export function UseInterceptors(...inters) {
5
5
  return (target, propertyKey) => {
@@ -1,4 +1,4 @@
1
1
  import "reflect-metadata";
2
- import type { MetadataKey } from "../types";
2
+ import type { MetadataKey } from "../types.js";
3
3
  export declare function SetMetadata<T = unknown>(metadataKey: MetadataKey, metadataValue: T): ClassDecorator & MethodDecorator;
4
4
  export declare function appendArrayMetadata<T>(metadataKey: MetadataKey, values: readonly T[], target: object, propertyKey?: string | symbol): void;
@@ -1,4 +1,4 @@
1
1
  import "reflect-metadata";
2
- import type { PipeLike } from "../types";
2
+ import type { PipeLike } from "../types.js";
3
3
  export declare const PIPES_KEY: unique symbol;
4
4
  export declare function UsePipes(...pipes: PipeLike[]): ClassDecorator & MethodDecorator;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { appendArrayMetadata } from "./metadata.decorators";
2
+ import { appendArrayMetadata } from "./metadata.decorators.js";
3
3
  export const PIPES_KEY = Symbol("pipes");
4
4
  export function UsePipes(...pipes) {
5
5
  return (target, propertyKey) => {
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import type { RpcMethodDescriptor, RpcServiceDescriptor } from "../core/types";
2
+ import type { RpcMethodDescriptor, RpcServiceDescriptor } from "../core/types.js";
3
3
  export declare const RPC_SERVICE_KEY: unique symbol;
4
4
  export declare const RPC_METHODS_KEY: unique symbol;
5
5
  export declare const RPC_PARAMS_KEY: unique symbol;
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { Injectable } from "./di.decorators";
2
+ import { Injectable } from "./di.decorators.js";
3
3
  export const RPC_SERVICE_KEY = Symbol("rpc:service");
4
4
  export const RPC_METHODS_KEY = Symbol("rpc:methods");
5
5
  export const RPC_PARAMS_KEY = Symbol("rpc:params");
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { Injectable } from "./di.decorators";
2
+ import { Injectable } from "./di.decorators.js";
3
3
  export const WS_GATEWAY_KEY = Symbol("ws:gateway");
4
4
  export const WS_HANDLERS_KEY = Symbol("ws:handlers");
5
5
  export const WS_PARAMS_KEY = Symbol("ws:params");
@@ -1,4 +1,4 @@
1
1
  import type { FastifyReply, FastifyRequest } from "fastify";
2
- import type { AppContainer } from "../core/container";
3
- import type { Constructor } from "../types";
2
+ import type { AppContainer } from "../core/container.js";
3
+ import type { Constructor } from "../types.js";
4
4
  export declare function createHttpHandler<TController extends Record<string, unknown>>(app: AppContainer, controller: Constructor<TController>, methodName: keyof TController & string): (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
@@ -1,8 +1,8 @@
1
- import { LoggerService } from "../services";
2
- import { ForbiddenException, toHttpError } from "../core/errors";
3
- import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators";
4
- import { PARAMS_KEY } from "../decorators/http.decorators";
5
- import { collectFiltersForHttp, collectGuardsForHttp, collectInterceptorsForHttp, collectPipesForHttp } from "./utils";
1
+ import { LoggerService } from "../services/index.js";
2
+ import { ForbiddenException, toHttpError } from "../core/errors.js";
3
+ import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators.js";
4
+ import { PARAMS_KEY } from "../decorators/http.decorators.js";
5
+ import { collectFiltersForHttp, collectGuardsForHttp, collectInterceptorsForHttp, collectPipesForHttp } from "./utils.js";
6
6
  function logHttpError(app, scope, details, error) {
7
7
  try {
8
8
  scope.resolve(LoggerService).error(details, error);
@@ -1,3 +1,3 @@
1
- export * from "./adapter";
2
- export * from "./router-builder";
3
- export * from "./utils";
1
+ export * from "./adapter.js";
2
+ export * from "./router-builder.js";
3
+ export * from "./utils.js";
@@ -1,3 +1,3 @@
1
- export * from "./adapter";
2
- export * from "./router-builder";
3
- export * from "./utils";
1
+ export * from "./adapter.js";
2
+ export * from "./router-builder.js";
3
+ export * from "./utils.js";
@@ -1,4 +1,4 @@
1
1
  import type { FastifyInstance } from "fastify";
2
2
  import "reflect-metadata";
3
- import type { AppContainer } from "../core/container";
3
+ import type { AppContainer } from "../core/container.js";
4
4
  export declare function registerHttpRoutes(server: FastifyInstance, di: AppContainer, globalPrefix?: string): void;
@@ -1,6 +1,6 @@
1
1
  import "reflect-metadata";
2
- import { HTTP_CONTROLLER_KEY, HTTP_ROUTES_KEY } from "../decorators/http.decorators";
3
- import { createHttpHandler } from "./adapter";
2
+ import { HTTP_CONTROLLER_KEY, HTTP_ROUTES_KEY } from "../decorators/http.decorators.js";
3
+ import { createHttpHandler } from "./adapter.js";
4
4
  function joinUrlPath(...segments) {
5
5
  const parts = segments
6
6
  .map((segment) => segment.trim())
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import type { Constructor, ExceptionFilterLike, GuardLike, InterceptorLike, PipeLike } from "../types";
2
+ import type { Constructor, ExceptionFilterLike, GuardLike, InterceptorLike, PipeLike } from "../types.js";
3
3
  export declare function collectGuardsForHttp(controller: Constructor, method: string, global: GuardLike[]): GuardLike[];
4
4
  export declare function collectInterceptorsForHttp(controller: Constructor, method: string, global: InterceptorLike[]): InterceptorLike[];
5
5
  export declare function collectPipesForHttp(controller: Constructor, method: string, global: PipeLike[]): PipeLike[];
@@ -1,9 +1,9 @@
1
1
  import "reflect-metadata";
2
- import { Reflector } from "../core/reflector";
3
- import { FILTERS_KEY } from "../decorators/filters.decorators";
4
- import { GUARDS_KEY } from "../decorators/guards.decorators";
5
- import { INTERCEPTORS_KEY } from "../decorators/interceptors.decorators";
6
- import { PIPES_KEY } from "../decorators/pipes.decorators";
2
+ import { Reflector } from "../core/reflector.js";
3
+ import { FILTERS_KEY } from "../decorators/filters.decorators.js";
4
+ import { GUARDS_KEY } from "../decorators/guards.decorators.js";
5
+ import { INTERCEPTORS_KEY } from "../decorators/interceptors.decorators.js";
6
+ import { PIPES_KEY } from "../decorators/pipes.decorators.js";
7
7
  const reflector = new Reflector();
8
8
  function enhancerKey(value) {
9
9
  if (typeof value === "function") {
@@ -1 +1 @@
1
- export * from "./zod.pipe";
1
+ export * from "./zod.pipe.js";
@@ -1 +1 @@
1
- export * from "./zod.pipe";
1
+ export * from "./zod.pipe.js";
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { PipeTransform } from "../types";
2
+ import type { PipeTransform } from "../types.js";
3
3
  export declare class ZodPipe<TSchema extends z.ZodType> implements PipeTransform<unknown, z.infer<TSchema>> {
4
4
  private schema;
5
5
  constructor(schema: TSchema);
@@ -1,7 +1,7 @@
1
1
  import type { HandlerContext } from "@connectrpc/connect";
2
2
  import "reflect-metadata";
3
- import type { AppContainer } from "../core/container";
4
- import type { Constructor } from "../types";
3
+ import type { AppContainer } from "../core/container.js";
4
+ import type { Constructor } from "../types.js";
5
5
  type RpcResponse = Record<string, unknown>;
6
6
  export declare function createRpcHandler<TController extends Record<string, unknown>>(app: AppContainer, controller: Constructor<TController>, methodName: keyof TController & string): (req: unknown, context: HandlerContext) => Promise<RpcResponse>;
7
7
  export {};
@@ -1,9 +1,9 @@
1
1
  import "reflect-metadata";
2
- import { ForbiddenException, toConnectError } from "../core/errors";
3
- import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators";
4
- import { RPC_PARAMS_KEY } from "../decorators/rpc.decorators";
5
- import { LoggerService } from "../services";
6
- import { collectFiltersForRpc, collectGuardsForRpc, collectInterceptorsForRpc, collectPipesForRpc } from "./utils";
2
+ import { ForbiddenException, toConnectError } from "../core/errors.js";
3
+ import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators.js";
4
+ import { RPC_PARAMS_KEY } from "../decorators/rpc.decorators.js";
5
+ import { LoggerService } from "../services/index.js";
6
+ import { collectFiltersForRpc, collectGuardsForRpc, collectInterceptorsForRpc, collectPipesForRpc } from "./utils.js";
7
7
  function logRpcError(app, scope, details, error) {
8
8
  try {
9
9
  scope.resolve(LoggerService).error(details, error);
@@ -1,4 +1,4 @@
1
- export * from "./adapter";
2
- export * from "./streaming-adapter";
3
- export * from "./router-builder";
4
- export * from "./utils";
1
+ export * from "./adapter.js";
2
+ export * from "./streaming-adapter.js";
3
+ export * from "./router-builder.js";
4
+ export * from "./utils.js";
package/dist/rpc/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export * from "./adapter";
2
- export * from "./streaming-adapter";
3
- export * from "./router-builder";
4
- export * from "./utils";
1
+ export * from "./adapter.js";
2
+ export * from "./streaming-adapter.js";
3
+ export * from "./router-builder.js";
4
+ export * from "./utils.js";
@@ -1,4 +1,4 @@
1
1
  import type { ConnectRouter } from "@connectrpc/connect";
2
2
  import "reflect-metadata";
3
- import type { AppContainer } from "../core/container";
3
+ import type { AppContainer } from "../core/container.js";
4
4
  export declare function buildConnectRoutes(di: AppContainer): (router: ConnectRouter) => void;
@@ -1,7 +1,7 @@
1
1
  import "reflect-metadata";
2
- import { RPC_METHODS_KEY, RPC_SERVICE_KEY } from "../decorators/rpc.decorators";
3
- import { createRpcHandler } from "./adapter";
4
- import { createStreamingRpcHandler } from "./streaming-adapter";
2
+ import { RPC_METHODS_KEY, RPC_SERVICE_KEY } from "../decorators/rpc.decorators.js";
3
+ import { createRpcHandler } from "./adapter.js";
4
+ import { createStreamingRpcHandler } from "./streaming-adapter.js";
5
5
  export function buildConnectRoutes(di) {
6
6
  return (router) => {
7
7
  for (const ctrl of di.getControllers()) {
@@ -1,5 +1,5 @@
1
1
  import type { HandlerContext } from "@connectrpc/connect";
2
2
  import "reflect-metadata";
3
- import type { AppContainer } from "../core/container";
4
- import type { Constructor } from "../types";
3
+ import type { AppContainer } from "../core/container.js";
4
+ import type { Constructor } from "../types.js";
5
5
  export declare function createStreamingRpcHandler<TController extends Record<string, unknown>>(app: AppContainer, controller: Constructor<TController>, methodName: keyof TController & string): (req: unknown, context: HandlerContext) => AsyncIterable<unknown>;
@@ -1,9 +1,9 @@
1
1
  import "reflect-metadata";
2
- import { ForbiddenException, toConnectError } from "../core/errors";
3
- import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators";
4
- import { RPC_PARAMS_KEY } from "../decorators/rpc.decorators";
5
- import { LoggerService } from "../services";
6
- import { collectFiltersForRpc, collectGuardsForRpc, collectPipesForRpc } from "./utils";
2
+ import { ForbiddenException, toConnectError } from "../core/errors.js";
3
+ import { CATCH_EXCEPTIONS_KEY } from "../decorators/filters.decorators.js";
4
+ import { RPC_PARAMS_KEY } from "../decorators/rpc.decorators.js";
5
+ import { LoggerService } from "../services/index.js";
6
+ import { collectFiltersForRpc, collectGuardsForRpc, collectPipesForRpc } from "./utils.js";
7
7
  function logRpcError(app, scope, details, error) {
8
8
  try {
9
9
  scope.resolve(LoggerService).error(details, error);
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- import type { Constructor, ExceptionFilterLike, GuardLike, InterceptorLike, PipeLike } from "../types";
2
+ import type { Constructor, ExceptionFilterLike, GuardLike, InterceptorLike, PipeLike } from "../types.js";
3
3
  export declare function collectGuardsForRpc(controller: Constructor, method: string, global: GuardLike[]): GuardLike[];
4
4
  export declare function collectInterceptorsForRpc(controller: Constructor, method: string, global: InterceptorLike[]): InterceptorLike[];
5
5
  export declare function collectPipesForRpc(controller: Constructor, method: string, global: PipeLike[]): PipeLike[];
package/dist/rpc/utils.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import "reflect-metadata";
2
- import { Reflector } from "../core/reflector";
3
- import { FILTERS_KEY } from "../decorators/filters.decorators";
4
- import { GUARDS_KEY } from "../decorators/guards.decorators";
5
- import { INTERCEPTORS_KEY } from "../decorators/interceptors.decorators";
6
- import { PIPES_KEY } from "../decorators/pipes.decorators";
2
+ import { Reflector } from "../core/reflector.js";
3
+ import { FILTERS_KEY } from "../decorators/filters.decorators.js";
4
+ import { GUARDS_KEY } from "../decorators/guards.decorators.js";
5
+ import { INTERCEPTORS_KEY } from "../decorators/interceptors.decorators.js";
6
+ import { PIPES_KEY } from "../decorators/pipes.decorators.js";
7
7
  const reflector = new Reflector();
8
8
  function enhancerKey(value) {
9
9
  if (typeof value === "function") {
@@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- import { CONFIG_TOKEN } from "../core/config";
14
- import { Inject, Injectable } from "../decorators";
13
+ import { CONFIG_TOKEN } from "../core/config.js";
14
+ import { Inject, Injectable } from "../decorators/index.js";
15
15
  let ConfigService = class ConfigService {
16
16
  constructor(config) {
17
17
  this.config = config;
@@ -1,2 +1,2 @@
1
- export * from "./config.service";
2
- export * from "./logger.service";
1
+ export * from "./config.service.js";
2
+ export * from "./logger.service.js";
@@ -1,2 +1,2 @@
1
- export * from "./config.service";
2
- export * from "./logger.service";
1
+ export * from "./config.service.js";
2
+ export * from "./logger.service.js";
@@ -1,4 +1,4 @@
1
- import { type AppLogger } from "../core/logger";
1
+ import { type AppLogger } from "../core/logger.js";
2
2
  export declare class LoggerService {
3
3
  private readonly logger;
4
4
  constructor(logger: AppLogger);
@@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- import { LOGGER_TOKEN } from "../core/logger";
14
- import { Inject, Injectable } from "../decorators";
13
+ import { LOGGER_TOKEN } from "../core/logger.js";
14
+ import { Inject, Injectable } from "../decorators/index.js";
15
15
  let LoggerService = class LoggerService {
16
16
  constructor(logger) {
17
17
  this.logger = logger;
package/dist/types.d.ts CHANGED
@@ -39,8 +39,7 @@ interface BaseModuleMeta {
39
39
  exports?: InjectionToken[];
40
40
  global?: boolean;
41
41
  }
42
- export interface ModuleMeta extends BaseModuleMeta {
43
- }
42
+ export type ModuleMeta = BaseModuleMeta;
44
43
  export interface DynamicModule extends BaseModuleMeta {
45
44
  module: Constructor;
46
45
  id?: string;
@@ -70,9 +69,9 @@ export interface RpcArgumentsHost {
70
69
  getContext<T = unknown>(): T | undefined;
71
70
  }
72
71
  export interface WsArgumentsHost {
73
- getSocket<T = unknown>(): T | undefined;
72
+ getSocket(): unknown;
74
73
  getRequest(): FastifyRequest | undefined;
75
- getMessage<T = unknown>(): T | undefined;
74
+ getMessage(): unknown;
76
75
  }
77
76
  export interface BaseContext {
78
77
  type: ContextType;
@@ -115,7 +114,7 @@ export interface PipeTransform<TIn = unknown, TOut = unknown> {
115
114
  }
116
115
  export type PipeLike = Constructor<PipeTransform> | PipeTransform;
117
116
  export interface ExceptionFilter<T = unknown> {
118
- catch(exception: T, ctx: BaseContext): Promise<unknown> | unknown;
117
+ catch(exception: T, ctx: BaseContext): unknown;
119
118
  }
120
119
  export type ExceptionFilterLike = Constructor<ExceptionFilter> | ExceptionFilter;
121
120
  export interface ConfigServiceOptions<TSchema extends ZodType = ZodType> {
@@ -124,7 +123,7 @@ export interface ConfigServiceOptions<TSchema extends ZodType = ZodType> {
124
123
  }
125
124
  export interface CorsOptions {
126
125
  enabled?: boolean;
127
- origin?: string | boolean | RegExp | Array<string | boolean | RegExp>;
126
+ origin?: string | boolean | RegExp | (string | boolean | RegExp)[];
128
127
  credentials?: boolean;
129
128
  exposedHeaders?: string | string[];
130
129
  allowedHeaders?: string | string[];
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { booleanSchema, numberSchema, stringArraySchema } from "./common";
2
+ import { booleanSchema, numberSchema, stringArraySchema } from "./common.js";
3
3
  const LOG_LEVELS = ["silly", "trace", "debug", "info", "warn", "error", "fatal"];
4
4
  const LOG_TYPES = ["pretty", "json"];
5
5
  export const appConfigSchema = z.object({
@@ -1,2 +1,2 @@
1
- export * from "./app-config";
2
- export * from "./common";
1
+ export * from "./app-config.js";
2
+ export * from "./common.js";
@@ -1,2 +1,2 @@
1
- export * from "./app-config";
2
- export * from "./common";
1
+ export * from "./app-config.js";
2
+ export * from "./common.js";
@@ -1,6 +1,6 @@
1
1
  import type { FastifyRequest } from "fastify";
2
2
  import type { WebSocket } from "@fastify/websocket";
3
3
  import "reflect-metadata";
4
- import type { AppContainer } from "../core/container";
5
- import type { Constructor } from "../types";
4
+ import type { AppContainer } from "../core/container.js";
5
+ import type { Constructor } from "../types.js";
6
6
  export declare function handleWsConnection(app: AppContainer, gateway: Constructor, socket: WebSocket, request: FastifyRequest): void;
@@ -1,8 +1,8 @@
1
1
  import "reflect-metadata";
2
- import { GUARDS_KEY } from "../decorators/guards.decorators";
3
- import { WS_HANDLERS_KEY, WS_PARAMS_KEY } from "../decorators/ws.decorators";
4
- import { Reflector } from "../core/reflector";
5
- import { LoggerService } from "../services";
2
+ import { GUARDS_KEY } from "../decorators/guards.decorators.js";
3
+ import { WS_HANDLERS_KEY, WS_PARAMS_KEY } from "../decorators/ws.decorators.js";
4
+ import { Reflector } from "../core/reflector.js";
5
+ import { LoggerService } from "../services/index.js";
6
6
  const reflector = new Reflector();
7
7
  function collectGuardsForWs(gateway, app) {
8
8
  const classGuards = (reflector.get(GUARDS_KEY, gateway) ?? []);
@@ -104,9 +104,9 @@ export function handleWsConnection(app, gateway, socket, request) {
104
104
  }
105
105
  // Route messages to handlers
106
106
  socket.on("message", (raw) => {
107
- (async () => {
107
+ void (async () => {
108
108
  try {
109
- const msg = JSON.parse(raw.toString());
109
+ const msg = JSON.parse(String(raw));
110
110
  const handler = handlers.find((h) => h.messageType === msg.type);
111
111
  if (!handler) {
112
112
  return;
@@ -125,7 +125,7 @@ export function handleWsConnection(app, gateway, socket, request) {
125
125
  });
126
126
  // Cleanup on disconnect
127
127
  socket.on("close", () => {
128
- (async () => {
128
+ void (async () => {
129
129
  try {
130
130
  if (typeof instance.onDisconnect === "function") {
131
131
  await instance.onDisconnect(socket);
@@ -162,6 +162,7 @@ export function handleWsConnection(app, gateway, socket, request) {
162
162
  catch {
163
163
  // socket may already be closed
164
164
  }
165
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
165
166
  app.disposeRequestScope(scope).catch(() => { });
166
167
  });
167
168
  }
@@ -1,3 +1,3 @@
1
- export { handleWsConnection } from "./adapter";
2
- export { registerWsGateways } from "./router-builder";
3
- export type { WsGatewayLifecycle, WsGatewayMeta, WsHandlerMeta, WsParamMeta, WsParamSource } from "./types";
1
+ export { handleWsConnection } from "./adapter.js";
2
+ export { registerWsGateways } from "./router-builder.js";
3
+ export type { WsGatewayLifecycle, WsGatewayMeta, WsHandlerMeta, WsParamMeta, WsParamSource } from "./types.js";
package/dist/ws/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { handleWsConnection } from "./adapter";
2
- export { registerWsGateways } from "./router-builder";
1
+ export { handleWsConnection } from "./adapter.js";
2
+ export { registerWsGateways } from "./router-builder.js";
@@ -1,4 +1,4 @@
1
1
  import type { FastifyInstance } from "fastify";
2
2
  import "reflect-metadata";
3
- import type { AppContainer } from "../core/container";
3
+ import type { AppContainer } from "../core/container.js";
4
4
  export declare function registerWsGateways(server: FastifyInstance, app: AppContainer): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import "reflect-metadata";
2
- import { WS_GATEWAY_KEY } from "../decorators/ws.decorators";
3
- import { handleWsConnection } from "./adapter";
2
+ import { WS_GATEWAY_KEY } from "../decorators/ws.decorators.js";
3
+ import { handleWsConnection } from "./adapter.js";
4
4
  export async function registerWsGateways(server, app) {
5
5
  const gateways = app.getWsGateways();
6
6
  if (gateways.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smounters/imperium",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "NestJS-like modular DI container with unified HTTP + Connect RPC server for TypeScript",
5
5
  "keywords": [
6
6
  "di",
@@ -64,6 +64,8 @@
64
64
  "lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
65
65
  "format": "prettier . --write",
66
66
  "format:check": "prettier . --check",
67
+ "test": "vitest run",
68
+ "test:watch": "vitest",
67
69
  "clean": "rm -rf dist",
68
70
  "docs:dev": "pnpm exec vitepress dev docs",
69
71
  "docs:build": "pnpm exec vitepress build docs",
@@ -91,11 +93,11 @@
91
93
  "devDependencies": {
92
94
  "@connectrpc/connect": "^2.1.1",
93
95
  "@connectrpc/connect-fastify": "^2.1.1",
96
+ "@eslint/js": "^10.0.1",
94
97
  "@fastify/cors": "^11.2.0",
95
98
  "@fastify/websocket": "^11.2.0",
96
99
  "@types/node": "^25.5.0",
97
- "@typescript-eslint/eslint-plugin": "^8.57.2",
98
- "@typescript-eslint/parser": "^8.57.2",
100
+ "@types/ws": "^8.18.1",
99
101
  "eslint": "^10.1.0",
100
102
  "eslint-config-prettier": "^10.1.8",
101
103
  "fastify": "^5.8.4",
@@ -104,7 +106,11 @@
104
106
  "tslog": "^4.10.2",
105
107
  "tsyringe": "^4.10.0",
106
108
  "typescript": "^5.9.3",
109
+ "typescript-eslint": "^8.57.2",
110
+ "vite": "^8.0.3",
107
111
  "vitepress": "^1.6.4",
112
+ "vitest": "^4.1.2",
113
+ "ws": "^8.20.0",
108
114
  "zod": "^4.3.6"
109
115
  }
110
116
  }