ioserver 2.1.0 โ†’ 2.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.
package/README.md CHANGED
@@ -1,266 +1,424 @@
1
- # ๐Ÿš€ IOServer
1
+ # IOServer
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/ioserver.svg)](https://badge.fury.io/js/ioserver)
4
4
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0)
5
- [![Node.js CI](https://github.com/x42en/IOServer/workflows/Node.js%20CI/badge.svg)](https://github.com/x42en/IOServer/actions)
5
+ [![CI Build and Test](https://github.com/x42en/IOServer/actions/workflows/build.yml/badge.svg)](https://github.com/x42en/IOServer/actions)
6
6
  [![codecov](https://codecov.io/gh/x42en/IOServer/branch/main/graph/badge.svg)](https://codecov.io/gh/x42en/IOServer)
7
- [![TypeScript](https://img.shields.io/badge/TypeScript-4.9+-blue.svg)](https://www.typescriptlang.org/)
8
-
9
- **A powerful, production-ready framework for building real-time applications with HTTP and WebSocket support.**
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
8
+
9
+ A TypeScript framework for building real-time applications, combining [Fastify](https://fastify.dev/) (HTTP) and [Socket.IO](https://socket.io/) (WebSocket) behind a single unified API.
10
+
11
+ ## Overview
12
+
13
+ IOServer structures your application around five component types โ€” Services, Controllers, Managers, Watchers, and Middlewares โ€” each with a well-defined responsibility. Components are registered on the IOServer instance before startup; the framework wires routing, CORS, and Socket.IO transport automatically.
14
+
15
+ It is designed to be small, explicit, and easily testable:
16
+
17
+ - No magic decorators or code generation
18
+ - Route definitions are plain JSON files, kept separate from handler logic
19
+ - Managers are injectable singletons available to every component via `AppHandle`
20
+ - All base classes expose a minimal surface; you only override what you need
21
+
22
+ ## Architecture
23
+
24
+ ```mermaid
25
+ graph TB
26
+ subgraph "Clients"
27
+ HTTP[HTTP Clients]
28
+ WS[WebSocket Clients]
29
+ end
30
+
31
+ subgraph "IOServer"
32
+ direction TB
33
+ Fastify[Fastify HTTP layer]
34
+ SocketIO[Socket.IO layer]
35
+
36
+ subgraph "Components"
37
+ MW[Middlewares]
38
+ CTL[Controllers]
39
+ SVC[Services]
40
+ MGR[Managers]
41
+ WCH[Watchers]
42
+ end
43
+ end
44
+
45
+ HTTP -->|REST requests| Fastify
46
+ WS -->|WS upgrade| SocketIO
47
+
48
+ Fastify --> MW
49
+ SocketIO --> MW
50
+ MW --> CTL
51
+ MW --> SVC
52
+ CTL --> MGR
53
+ SVC --> MGR
54
+ WCH --> MGR
55
+ ```
10
56
 
11
- IOServer combines the speed of Fastify with the real-time capabilities of Socket.IO, providing a unified architecture for modern web applications. Built with TypeScript and designed for scalability, it offers a clean separation of concerns through services, controllers, managers, and watchers.
57
+ ## Key Features
12
58
 
13
- ## โœจ Features
59
+ - **Unified HTTP + WebSocket** โ€” Fastify v5 and Socket.IO v4 share the same port and TLS configuration
60
+ - **Component model** โ€” Five explicit roles (Service, Controller, Manager, Watcher, Middleware) keep business logic isolated and testable
61
+ - **JSON route files** โ€” HTTP routes are declared in `.json` files; no annotations or meta-programming required
62
+ - **Injectable managers** โ€” Singleton managers are exposed to all components through a typed `AppHandle`, avoiding global state
63
+ - **TypeScript native** โ€” Ships with declaration files; strict mode compatible
64
+ - **CORS built-in** โ€” Pass a standard Fastify CORS options object; applied to both HTTP and Socket.IO handshake
65
+ - **Configurable transports** โ€” Choose `websocket`, `polling`, or both for Socket.IO
66
+ - **SPA fallback** โ€” Optional static file serving with single-page application fallback routing
14
67
 
15
- - ๐Ÿš„ **High Performance** - Built on Fastify for maximum HTTP throughput
16
- - โšก **Real-time Communication** - Integrated Socket.IO for WebSocket connections
17
- - ๐Ÿ—๏ธ **Modular Architecture** - Clean separation with Services, Controllers, Managers, and Watchers
18
- - ๐Ÿ”’ **Security First** - Built-in CORS, error handling, and validation
19
- - ๐Ÿ“ **TypeScript Native** - Full type safety and IntelliSense support
20
- - ๐Ÿงช **Fully Tested** - Comprehensive test suite with 95%+ coverage
21
- - ๐Ÿ”ง **Configuration Driven** - JSON-based routing and flexible configuration
22
- - ๐Ÿ“ฆ **Production Ready** - Memory leak detection, performance monitoring, and error handling
68
+ ## Requirements
23
69
 
24
- ## ๐Ÿš€ Quick Start
70
+ - Node.js 18+
71
+ - TypeScript 5.0+
72
+ - pnpm (recommended) or npm / yarn
25
73
 
26
- ### Installation
74
+ ## Installation
27
75
 
28
76
  ```bash
29
77
  npm install ioserver
30
78
  # or
31
- yarn add ioserver
79
+ pnpm add ioserver
32
80
  ```
33
81
 
34
- ### Basic Usage
82
+ ## Quick Start
35
83
 
36
84
  ```typescript
37
- import { IOServer, BaseService, BaseController } from 'ioserver';
85
+ import { IOServer, BaseService, BaseController, BaseManager } from 'ioserver';
38
86
 
39
- // Create a service for real-time functionality
87
+ // --- Manager: shared state ---
88
+ class AppManager extends BaseManager {
89
+ private count = 0;
90
+ increment() { this.count++; }
91
+ getCount() { return this.count; }
92
+ }
93
+
94
+ // --- Service: WebSocket events ---
40
95
  class ChatService extends BaseService {
41
- async sendMessage(socket: any, data: any, callback?: Function) {
42
- // Handle real-time messaging
43
- socket.broadcast.emit('new_message', data);
44
- if (callback) callback({ status: 'success' });
96
+ async sendMessage(socket: any, data: { text: string }, callback?: Function) {
97
+ const mgr = this.app.getManager('app') as AppManager;
98
+ mgr.increment();
99
+ socket.broadcast.emit('message', { text: data.text, total: mgr.getCount() });
100
+ if (callback) callback({ status: 'ok' });
45
101
  }
46
102
  }
47
103
 
48
- // Create a controller for HTTP endpoints
49
- class ApiController extends BaseController {
50
- async getStatus(request: any, reply: any) {
51
- reply.send({ status: 'OK', timestamp: Date.now() });
104
+ // --- Controller: HTTP endpoints ---
105
+ class StatsController extends BaseController {
106
+ async getStats(request: any, reply: any) {
107
+ const mgr = this.app.getManager('app') as AppManager;
108
+ reply.send({ messages: mgr.getCount() });
52
109
  }
53
110
  }
54
111
 
55
- // Initialize and configure server
56
- const server = new IOServer({
57
- host: 'localhost',
58
- port: 3000,
59
- cors: {
60
- origin: ['http://localhost:3000'],
61
- methods: ['GET', 'POST'],
62
- },
63
- });
112
+ // --- Bootstrap ---
113
+ const server = new IOServer({ host: 'localhost', port: 3000 });
64
114
 
65
- // Register components
115
+ server.addManager({ name: 'app', manager: AppManager });
66
116
  server.addService({ name: 'chat', service: ChatService });
67
- server.addController({ name: 'api', controller: ApiController });
117
+ server.addController({ name: 'stats', controller: StatsController });
68
118
 
69
- // Start server
70
119
  await server.start();
71
- console.log('๐Ÿš€ Server running at http://localhost:3000');
72
120
  ```
73
121
 
74
- ## ๐Ÿ—๏ธ Architecture
122
+ > Managers must be registered **before** Services and Controllers so that `AppHandle` references are already populated at startup.
75
123
 
76
- IOServer provides four core component types for building scalable applications:
124
+ ## Components
77
125
 
78
- ### ๐Ÿ“ก **Services** - Real-time Logic
126
+ ### Services โ€” WebSocket event handlers
79
127
 
80
- Handle WebSocket connections and real-time events.
128
+ A Service groups Socket.IO event handlers. Each public method of the class is automatically bound to the Socket.IO event `<method_name>`.
81
129
 
82
130
  ```typescript
83
- class NotificationService extends BaseService {
84
- async notify(socket: any, data: any, callback?: Function) {
85
- // Real-time notification logic
86
- socket.emit('notification', { message: data.message });
87
- if (callback) callback({ delivered: true });
131
+ import { BaseService } from 'ioserver';
132
+ import type { Socket } from 'socket.io';
133
+
134
+ class RoomService extends BaseService {
135
+ async join(socket: Socket, data: { room: string }, callback?: Function) {
136
+ socket.join(data.room);
137
+ socket.to(data.room).emit('user_joined', { id: socket.id });
138
+ if (callback) callback({ joined: data.room });
139
+ }
140
+
141
+ async leave(socket: Socket, data: { room: string }) {
142
+ socket.leave(data.room);
88
143
  }
89
144
  }
145
+
146
+ server.addService({ name: 'room', service: RoomService });
90
147
  ```
91
148
 
92
- ### ๐ŸŒ **Controllers** - HTTP Endpoints
149
+ Registration options:
150
+
151
+ | Option | Type | Description |
152
+ |---|---|---|
153
+ | `name` | `string` | Namespace name (used as Socket.IO namespace `/name`) |
154
+ | `service` | `typeof BaseService` | Service class (not an instance) |
155
+ | `middlewares` | `BaseMiddleware[]` | Optional middleware chain for this namespace |
93
156
 
94
- Handle HTTP requests with automatic route mapping from JSON configuration.
157
+ ### Controllers โ€” HTTP route handlers
158
+
159
+ A Controller groups Fastify route handlers. Routes are mapped through a JSON file located in the `routes/` directory (or the path set in `options.routes`).
95
160
 
96
161
  ```typescript
162
+ import { BaseController } from 'ioserver';
163
+ import type { FastifyRequest, FastifyReply } from 'fastify';
164
+
97
165
  class UserController extends BaseController {
98
- async getUser(request: any, reply: any) {
99
- const userId = request.params.id;
100
- reply.send({ id: userId, name: 'John Doe' });
166
+ async getUser(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
167
+ reply.send({ id: request.params.id });
168
+ }
169
+
170
+ async createUser(request: FastifyRequest<{ Body: { name: string } }>, reply: FastifyReply) {
171
+ reply.code(201).send({ id: crypto.randomUUID(), name: request.body.name });
101
172
  }
102
173
  }
174
+
175
+ server.addController({ name: 'user', controller: UserController });
103
176
  ```
104
177
 
105
- ### ๐Ÿ”ง **Managers** - Shared Logic
178
+ Corresponding route file `routes/user.json`:
106
179
 
107
- Provide shared functionality across services and controllers.
180
+ ```json
181
+ [
182
+ { "method": "GET", "url": "/users/:id", "handler": "getUser" },
183
+ { "method": "POST", "url": "/users", "handler": "createUser" }
184
+ ]
185
+ ```
186
+
187
+ Registration options:
188
+
189
+ | Option | Type | Description |
190
+ |---|---|---|
191
+ | `name` | `string` | Must match the JSON route file basename (`routes/<name>.json`) |
192
+ | `controller` | `typeof BaseController` | Controller class (not an instance) |
193
+ | `middlewares` | `BaseMiddleware[]` | Optional middleware chain for all routes of this controller |
194
+
195
+ ### Managers โ€” Injectable singletons
196
+
197
+ Managers hold shared state and business logic. They are instantiated once and exposed to every Service, Controller, and Watcher through `this.app`.
108
198
 
109
199
  ```typescript
110
- class DatabaseManager extends BaseManager {
111
- async query(sql: string, params: any[]) {
112
- // Database operations
113
- return await this.db.query(sql, params);
114
- }
200
+ import { BaseManager } from 'ioserver';
201
+
202
+ class CacheManager extends BaseManager {
203
+ private store = new Map<string, unknown>();
204
+
205
+ set(key: string, value: unknown) { this.store.set(key, value); }
206
+ get(key: string) { return this.store.get(key); }
207
+ has(key: string) { return this.store.has(key); }
115
208
  }
209
+
210
+ server.addManager({ name: 'cache', manager: CacheManager });
211
+
212
+ // In any other component:
213
+ const cache = this.app.getManager('cache') as CacheManager;
214
+ cache.set('session:42', { userId: 42 });
116
215
  ```
117
216
 
118
- ### ๐Ÿ‘€ **Watchers** - Background Tasks
217
+ The optional `start()` method is called automatically by the framework after all components are registered and before the server begins accepting connections.
218
+
219
+ ### Watchers โ€” Background tasks
119
220
 
120
- Handle background processes, monitoring, and scheduled tasks.
221
+ Watchers run independent background loops. Both `watch()` and `stop()` must be implemented.
121
222
 
122
223
  ```typescript
123
- class HealthWatcher extends BaseWatcher {
224
+ import { BaseWatcher } from 'ioserver';
225
+
226
+ class CleanupWatcher extends BaseWatcher {
227
+ private timer: ReturnType<typeof setInterval> | null = null;
228
+
124
229
  async watch() {
125
- setInterval(() => {
126
- // Monitor system health
127
- this.checkSystemHealth();
128
- }, 30000);
230
+ this.timer = setInterval(async () => {
231
+ const cache = this.app.getManager('cache') as CacheManager;
232
+ // periodic cleanup logic
233
+ }, 60_000);
234
+ }
235
+
236
+ stop() {
237
+ if (this.timer) {
238
+ clearInterval(this.timer);
239
+ this.timer = null;
240
+ }
129
241
  }
130
242
  }
243
+
244
+ server.addWatcher({ name: 'cleanup', watcher: CleanupWatcher });
245
+ ```
246
+
247
+ ### Middlewares โ€” Request and connection guards
248
+
249
+ Middlewares intercept HTTP requests (Fastify `preHandler`) and Socket.IO connections before they reach Controllers or Services.
250
+
251
+ ```typescript
252
+ import { BaseMiddleware } from 'ioserver';
253
+ import type { FastifyRequest, FastifyReply } from 'fastify';
254
+ import type { Socket } from 'socket.io';
255
+
256
+ class AuthMiddleware extends BaseMiddleware {
257
+ // HTTP guard
258
+ async handle(request: FastifyRequest, reply: FastifyReply, next: Function) {
259
+ const token = request.headers.authorization?.split(' ')[1];
260
+ if (!token || !this.verify(token)) {
261
+ return reply.code(401).send({ error: 'Unauthorized' });
262
+ }
263
+ next();
264
+ }
265
+
266
+ // WebSocket guard
267
+ async handleSocket(socket: Socket, next: Function) {
268
+ const token = socket.handshake.auth?.token;
269
+ if (!token || !this.verify(token)) {
270
+ return next(new Error('Unauthorized'));
271
+ }
272
+ next();
273
+ }
274
+
275
+ private verify(token: string) { /* JWT verification */ return true; }
276
+ }
277
+
278
+ // Apply to a specific controller or service
279
+ server.addController({ name: 'admin', controller: AdminController, middlewares: [AuthMiddleware] });
131
280
  ```
132
281
 
133
- ## ๐Ÿ“‹ Configuration
282
+ ## Configuration
134
283
 
135
- ### Server Options
284
+ ```typescript
285
+ const server = new IOServer(options);
286
+ ```
287
+
288
+ | Option | Type | Default | Description |
289
+ |---|---|---|---|
290
+ | `host` | `string` | `'localhost'` | Bind address |
291
+ | `port` | `number` | `8080` | Listen port |
292
+ | `verbose` | `string` | `'ERROR'` | Log level (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
293
+ | `cookie` | `boolean` | `false` | Enable Socket.IO cookies |
294
+ | `mode` | `string \| string[]` | `['websocket','polling']` | Socket.IO transport(s) |
295
+ | `cors` | `object` | `undefined` | Fastify CORS options (applied to HTTP and Socket.IO) |
296
+ | `routes` | `string` | `'./routes'` | Directory containing JSON route files |
297
+ | `rootDir` | `string` | `'.'` | Root directory for static file serving |
298
+ | `spaFallback` | `boolean` | `false` | Serve `index.html` for unmatched routes (SPA mode) |
299
+
300
+ ### CORS example
136
301
 
137
302
  ```typescript
138
303
  const server = new IOServer({
139
- host: 'localhost', // Server host
140
- port: 3000, // Server port
141
- verbose: 'INFO', // Log level
142
- routes: './routes', // Route definitions directory
304
+ host: '0.0.0.0',
305
+ port: 8080,
143
306
  cors: {
144
- // CORS configuration
145
- origin: ['http://localhost:3000'],
307
+ origin: ['https://app.example.com'],
146
308
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
147
309
  credentials: true,
148
310
  },
149
- mode: ['websocket', 'polling'], // Socket.IO transport modes
150
311
  });
151
312
  ```
152
313
 
153
- ### Route Configuration
154
-
155
- Define HTTP routes in JSON files (e.g., `routes/api.json`):
156
-
157
- ```json
158
- [
159
- {
160
- "method": "GET",
161
- "url": "/users/:id",
162
- "handler": "getUser"
163
- },
164
- {
165
- "method": "POST",
166
- "url": "/users",
167
- "handler": "createUser"
168
- }
169
- ]
170
- ```
171
-
172
- ## ๐Ÿงช Testing
173
-
174
- IOServer includes comprehensive testing utilities and examples:
314
+ ## Testing
175
315
 
176
316
  ```bash
177
317
  # Run all tests
178
- npm test
318
+ pnpm test
179
319
 
180
- # Test categories
181
- npm run test:unit # Unit tests
182
- npm run test:integration # Integration tests
183
- npm run test:e2e # End-to-end tests
184
- npm run test:performance # Performance tests
320
+ # With coverage report
321
+ pnpm run test:coverage
185
322
 
186
- # Coverage report
187
- npm run test:coverage
323
+ # Isolated suites
324
+ pnpm run test:unit
325
+ pnpm run test:integration
326
+ pnpm run test:e2e
327
+ pnpm run test:performance
188
328
  ```
189
329
 
190
- ## ๐Ÿ“š Examples
330
+ Coverage targets: 90% statements, 85% branches, 90% functions.
191
331
 
192
- ### Real-time Chat Application
332
+ ## Examples
193
333
 
194
- A complete chat application example is included in the `examples/` directory, showcasing:
334
+ ### Simple server
195
335
 
196
- - User authentication and management
197
- - Real-time messaging
198
- - Room-based conversations
199
- - Typing indicators
200
- - Connection management
201
- - API endpoints for statistics
336
+ `examples/simple.ts` โ€” all five component types in a single file, useful as a project template:
202
337
 
203
338
  ```bash
204
- cd examples/chat-app
205
- npm install
206
- npm start
339
+ pnpm run dev:simple
207
340
  ```
208
341
 
209
- Visit `http://localhost:8080` to see the chat application in action.
210
-
211
- ## ๐Ÿ”ง API Reference
342
+ ### Chat application
212
343
 
213
- ### Core Classes
344
+ `examples/chat-app/` โ€” a complete multi-room chat server with:
214
345
 
215
- - **`IOServer`** - Main server class
216
- - **`BaseService`** - Base class for WebSocket services
217
- - **`BaseController`** - Base class for HTTP controllers
218
- - **`BaseManager`** - Base class for shared logic managers
219
- - **`BaseWatcher`** - Base class for background watchers
346
+ - `RoomService` โ€” join/leave/message Socket.IO events
347
+ - `ChatController` โ€” REST endpoints for room history and statistics
348
+ - `StatsManager` โ€” shared counters accessible from both layers
349
+ - `ChatWatcher` โ€” periodic inactive-room cleanup
220
350
 
221
- ### Key Methods
222
-
223
- ```typescript
224
- // Server management
225
- server.addService(options: ServiceOptions)
226
- server.addController(options: ControllerOptions)
227
- server.addManager(options: ManagerOptions)
228
- server.addWatcher(options: WatcherOptions)
229
- server.start(): Promise<void>
230
- server.stop(): Promise<void>
231
-
232
- // Real-time messaging
233
- server.sendTo(options: SendToOptions): boolean
351
+ ```bash
352
+ pnpm run dev:chat
353
+ # or
354
+ cd examples/chat-app && ts-node app.ts
234
355
  ```
235
356
 
236
- ## ๐Ÿค Contributing
357
+ Connect at `http://localhost:8080`.
237
358
 
238
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
359
+ ## Project Organization
239
360
 
240
- 1. Fork the repository
241
- 2. Create a feature branch: `git checkout -b feature/amazing-feature`
242
- 3. Commit your changes: `git commit -m 'Add amazing feature'`
243
- 4. Push to the branch: `git push origin feature/amazing-feature`
244
- 5. Open a Pull Request
361
+ ```
362
+ ioserver/
363
+ โ”œโ”€โ”€ src/
364
+ โ”‚ โ”œโ”€โ”€ IOServer.ts # Main class โ€” startup, registration, routing
365
+ โ”‚ โ”œโ”€โ”€ BaseClasses.ts # BaseService, BaseController, BaseManager,
366
+ โ”‚ โ”‚ # BaseWatcher, BaseMiddleware
367
+ โ”‚ โ”œโ”€โ”€ IOServerError.ts # Error hierarchy
368
+ โ”‚ โ””โ”€โ”€ index.ts # Public exports
369
+ โ”œโ”€โ”€ examples/
370
+ โ”‚ โ”œโ”€โ”€ simple.ts # Minimal example (all component types)
371
+ โ”‚ โ””โ”€โ”€ chat-app/ # Full chat application
372
+ โ”œโ”€โ”€ tests/
373
+ โ”‚ โ”œโ”€โ”€ unit/
374
+ โ”‚ โ”œโ”€โ”€ integration/
375
+ โ”‚ โ”œโ”€โ”€ e2e/
376
+ โ”‚ โ””โ”€โ”€ performance/
377
+ โ”œโ”€โ”€ docs-site/ # Nuxt/Docus documentation site
378
+ โ”œโ”€โ”€ tsconfig.json
379
+ โ””โ”€โ”€ package.json
380
+ ```
245
381
 
246
- ## ๐Ÿ“„ License
382
+ ## Docker Deployment
383
+
384
+ ```dockerfile
385
+ FROM node:24-alpine AS builder
386
+ WORKDIR /app
387
+ COPY package*.json ./
388
+ RUN npm ci
389
+ COPY . .
390
+ RUN npm run build
391
+
392
+ FROM node:24-alpine
393
+ WORKDIR /app
394
+ COPY --from=builder /app/dist ./dist
395
+ COPY --from=builder /app/node_modules ./node_modules
396
+ COPY --from=builder /app/package.json .
397
+ EXPOSE 8080
398
+ CMD ["node", "dist/index.js"]
399
+ ```
247
400
 
248
- This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details.
401
+ ```yaml
402
+ # compose.yml
403
+ services:
404
+ app:
405
+ build: .
406
+ ports:
407
+ - "8080:8080"
408
+ environment:
409
+ NODE_ENV: production
410
+ restart: unless-stopped
411
+ ```
249
412
 
250
- ## ๐Ÿ™ Acknowledgments
413
+ ## Related Projects
251
414
 
252
- - Built with [Fastify](https://www.fastify.io/) for high-performance HTTP
253
- - Powered by [Socket.IO](https://socket.io/) for real-time communication
254
- - Inspired by modern microservice architectures
415
+ - [uPKI CA Server](https://github.com/circle-rd/upki-ca) โ€” Certificate Authority built on this framework pattern
416
+ - [uPKI RA Server](https://github.com/circle-rd/upki-ra) โ€” Registration Authority built on this framework pattern
255
417
 
256
- ## ๐Ÿ“ž Support
418
+ ## Contributing
257
419
 
258
- - ๐Ÿ“š [Documentation](https://github.com/x42en/IOServer/wiki)
259
- - ๐Ÿ› [Issue Tracker](https://github.com/x42en/IOServer/issues)
260
- - ๐Ÿ’ฌ [Discussions](https://github.com/x42en/IOServer/discussions)
420
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, component rules, test strategy, and commit conventions.
261
421
 
262
- ---
422
+ ## License
263
423
 
264
- <div align="center">
265
- <strong>Built with โค๏ธ for the Node.js community</strong>
266
- </div>
424
+ Apache-2.0 โ€” see [LICENSE](LICENSE).
@@ -5,7 +5,7 @@
5
5
  * for Services, Controllers, Managers, Watchers, and Middlewares in the IOServer framework.
6
6
  *
7
7
  * @author Ben Mz <0x42en@users.noreply.github.com>
8
- * @version 2.0.6
8
+ * @version 2.1.1
9
9
  * @since 1.0.0
10
10
  */
11
11
  import { AppHandle } from './IOServer';
@@ -6,7 +6,7 @@
6
6
  * for Services, Controllers, Managers, Watchers, and Middlewares in the IOServer framework.
7
7
  *
8
8
  * @author Ben Mz <0x42en@users.noreply.github.com>
9
- * @version 2.0.6
9
+ * @version 2.1.1
10
10
  * @since 1.0.0
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -4,7 +4,7 @@
4
4
  * Services, Controllers, Managers, and Watchers.
5
5
  *
6
6
  * @author Ben Mz <0x42en@users.noreply.github.com>
7
- * @version 2.0.6
7
+ * @version 2.1.1
8
8
  * @since 1.0.0
9
9
  */
10
10
  import { FastifyInstance } from 'fastify';
package/dist/IOServer.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Services, Controllers, Managers, and Watchers.
6
6
  *
7
7
  * @author Ben Mz <0x42en@users.noreply.github.com>
8
- * @version 2.0.6
8
+ * @version 2.1.1
9
9
  * @since 1.0.0
10
10
  */
11
11
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -697,7 +697,7 @@ class IOServer {
697
697
  }
698
698
  }
699
699
  exports.IOServer = IOServer;
700
- IOServer.VERSION = '2.1.0';
700
+ IOServer.VERSION = '2.1.1';
701
701
  IOServer.DEFAULT_PORT = 8080;
702
702
  IOServer.DEFAULT_HOST = 'localhost';
703
703
  IOServer.LOG_LEVELS = [
@@ -6,7 +6,7 @@
6
6
  * and API error responses.
7
7
  *
8
8
  * @author Ben Mz <0x42en@users.noreply.github.com>
9
- * @version 2.0.6
9
+ * @version 2.1.1
10
10
  * @since 1.0.0
11
11
  */
12
12
  /**
@@ -7,7 +7,7 @@
7
7
  * and API error responses.
8
8
  *
9
9
  * @author Ben Mz <0x42en@users.noreply.github.com>
10
- * @version 2.0.6
10
+ * @version 2.1.1
11
11
  * @since 1.0.0
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  * - Production-ready with security best practices
13
13
  *
14
14
  * @author Ben Mz <0x42en@users.noreply.github.com>
15
- * @version 2.0.6
15
+ * @version 2.1.1
16
16
  * @since 1.0.0
17
17
  *
18
18
  * @example
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * - Production-ready with security best practices
14
14
  *
15
15
  * @author Ben Mz <0x42en@users.noreply.github.com>
16
- * @version 2.0.6
16
+ * @version 2.1.1
17
17
  * @since 1.0.0
18
18
  *
19
19
  * @example
package/package.json CHANGED
@@ -1,9 +1,31 @@
1
1
  {
2
2
  "name": "ioserver",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Damn simple Fastify & Socket.io server framework with TypeScript support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "build:watch": "tsc --watch",
10
+ "dev": "ts-node",
11
+ "dev:chat": "ts-node examples/chat-app/app.ts",
12
+ "dev:simple": "ts-node examples/simple.ts",
13
+ "test": "jest",
14
+ "test:watch": "jest --watch",
15
+ "test:coverage": "jest --coverage",
16
+ "test:unit": "jest --testPathPattern=unit",
17
+ "test:integration": "jest --testPathPattern=integration",
18
+ "test:e2e": "jest --testPathPattern=e2e",
19
+ "test:performance": "jest --testPathPattern=performance",
20
+ "lint": "eslint .",
21
+ "lint:fix": "eslint . --fix",
22
+ "docs:build": "cd docs && make html",
23
+ "docs:api": "typedoc --options typedoc.json",
24
+ "docs:serve": "cd docs/build/html && python -m http.server 8000",
25
+ "gpr-setup": "node scripts/gpr.js",
26
+ "gpr-restore": "node scripts/gpr-restore.js",
27
+ "prepublishOnly": "npm run build && npm run test"
28
+ },
7
29
  "keywords": [
8
30
  "socket.io",
9
31
  "fastify",
@@ -33,49 +55,28 @@
33
55
  },
34
56
  "dependencies": {
35
57
  "@fastify/cors": "^10.1.0",
36
- "@fastify/sensible": "^6.0.3",
58
+ "@fastify/sensible": "^6.0.4",
37
59
  "@fastify/static": "^9.0.0",
38
- "fastify": "^5.3.3",
39
- "socket.io": "^4.8.1"
60
+ "fastify": "^5.7.4",
61
+ "socket.io": "^4.8.3"
40
62
  },
41
63
  "devDependencies": {
42
- "@eslint/js": "^9.28.0",
64
+ "@eslint/js": "^9.39.3",
43
65
  "@types/jest": "^29.5.14",
44
- "@types/node": "^22.15.30",
66
+ "@types/node": "^22.19.12",
45
67
  "@types/supertest": "^6.0.3",
46
- "@typescript-eslint/eslint-plugin": "^8.33.1",
47
- "@typescript-eslint/parser": "^8.33.1",
48
- "eslint": "^9.28.0",
68
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
69
+ "@typescript-eslint/parser": "^8.56.1",
70
+ "eslint": "^9.39.3",
49
71
  "jest": "^29.7.0",
50
- "socket.io-client": "^4.8.1",
51
- "supertest": "^7.1.1",
52
- "ts-jest": "^29.3.4",
72
+ "socket.io-client": "^4.8.3",
73
+ "supertest": "^7.2.2",
74
+ "ts-jest": "^29.4.6",
53
75
  "ts-node": "^10.9.2",
54
- "typedoc": "^0.28.5",
55
- "typescript": "^5.8.3"
76
+ "typedoc": "^0.28.17",
77
+ "typescript": "^5.9.3"
56
78
  },
57
79
  "peerDependencies": {
58
80
  "typescript": ">=5.0.0"
59
- },
60
- "scripts": {
61
- "build": "tsc",
62
- "build:watch": "tsc --watch",
63
- "dev": "ts-node",
64
- "dev:chat": "ts-node examples/chat-app/app.ts",
65
- "dev:simple": "ts-node examples/simple-example.ts",
66
- "test": "jest",
67
- "test:watch": "jest --watch",
68
- "test:coverage": "jest --coverage",
69
- "test:unit": "jest --testPathPattern=unit",
70
- "test:integration": "jest --testPathPattern=integration",
71
- "test:e2e": "jest --testPathPattern=e2e",
72
- "test:performance": "jest --testPathPattern=performance",
73
- "lint": "eslint .",
74
- "lint:fix": "eslint . --fix",
75
- "docs:build": "cd docs && make html",
76
- "docs:api": "typedoc --options typedoc.json",
77
- "docs:serve": "cd docs/build/html && python -m http.server 8000",
78
- "gpr-setup": "node scripts/gpr.js",
79
- "gpr-restore": "node scripts/gpr-restore.js"
80
81
  }
81
- }
82
+ }