@afterlink/server 1.1.1 → 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 (2) hide show
  1. package/README.md +758 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,758 @@
1
+
2
+ <div align="center">
3
+
4
+ <img width="1774" height="887" alt="AfterLink README.md File Logo" src="https://github.com/user-attachments/assets/85611f61-2080-4172-b01a-dcd5119f2fc8" />
5
+
6
+ # AfterLink
7
+
8
+ **A custom binary communication protocol for fast, reliable, real-time messaging.**
9
+ Persistent connections · Built-in Pub/Sub · Automatic Zod validation · 10-byte frame
10
+
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
12
+ [![Code of Conduct](https://img.shields.io/badge/Code%20of%20Conduct-Contributor%20Covenant-purple.svg)](./CODE_OF_CONDUCT.md)
13
+ [![Node.js 20+](https://img.shields.io/badge/Node.js-20+-green.svg)](https://nodejs.org/)
14
+ [![Version](https://img.shields.io/npm/v/afterlink.svg)](https://www.npmjs.com/package/afterlink)
15
+ [![Downloads](https://img.shields.io/npm/dt/afterlink.svg)](https://www.npmjs.com/package/afterlink)
16
+ [![TLS](https://img.shields.io/badge/TLS-1.2%2F1.3-brightgreen.svg)](./CHANGELOG.md)
17
+ [![Compression](https://img.shields.io/badge/Compression-zlib%2FBrotli-orange.svg)](./CHANGELOG.md)
18
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)
19
+
20
+ [**Docs**](https://afterlinkdocs.vercel.app) · [**npm**](https://www.npmjs.com/package/afterlink) · [**Examples**](./examples) · [**Benchmarks**](./BENCHMARKS.md) · [**Discussions**](https://github.com/AJAYMYTH/AfterLink/discussions) · [**Changelog**](./CHANGELOG.md)
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## What is AfterLink?
27
+
28
+ AfterLink is a **custom application-layer binary communication protocol** built for developers who are tired of HTTP boilerplate. It combines structured request/response, real-time pub/sub, automatic schema validation, and persistent connections — all over a compact **10-byte binary frame**.
29
+
30
+ It is faster, simpler, and more developer-friendly than HTTP for modern real-time applications. You write 5 lines of code. AfterLink handles the rest.
31
+
32
+ ---
33
+
34
+ ## Why AfterLink?
35
+
36
+ | Problem with HTTP | AfterLink Solution |
37
+ |---|---|
38
+ | Verbose text headers add overhead | **10-byte binary header** — 90% smaller |
39
+ | Stateless — every request rebuilds context | **Persistent TCP connections** with session state |
40
+ | No built-in real-time — need WebSockets separately | **Pub/Sub built-in** — same protocol, same connection |
41
+ | No schema validation — manual checks everywhere | **Automatic Zod validation** — invalid payloads rejected before your code runs |
42
+ | One connection per request (HTTP/1.1) | **Multiplexing** — hundreds of concurrent requests over one connection |
43
+ | No binary support — need base64 workarounds | **Native binary** via MessagePack serialization |
44
+ | Complex setup for REST APIs | **5 lines** to spin up a full server with routes |
45
+
46
+ ---
47
+
48
+ ## Feature Comparison
49
+
50
+ | Feature | AfterLink | HTTP/REST | WebSocket | gRPC | MQTT |
51
+ |---|---|---|---|---|---|
52
+ | **Setup complexity** | Very Easy | Easy | Medium | Hard | Medium |
53
+ | **Binary protocol** | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes |
54
+ | **TLS encryption** | ✅ Built-in | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
55
+ | **Payload compression** | ✅ zlib/Brotli | ✅ gzip | ❌ No | ✅ Yes | ❌ No |
56
+ | **Schema validation** | ✅ Built-in | ❌ No | ❌ No | Proto only | ❌ No |
57
+ | **Multiplexing** | ✅ Yes | ❌ No (HTTP/1.1) | ❌ No | ✅ Yes | ❌ No |
58
+ | **Pub/Sub** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ✅ Yes |
59
+ | **Streaming** | ✅ First-class | SSE only | Manual | ✅ Yes | ❌ No |
60
+ | **Browser support** | ✅ Yes (TCP/WS) | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
61
+ | **Auto-reconnect** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ✅ Yes |
62
+ | **Rate limiting** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ❌ No |
63
+ | **Graceful shutdown** | ✅ Built-in | ✅ Yes | ❌ No | ✅ Yes | ❌ No |
64
+ | **Built-in auth** | ✅ Yes (JWT) | ❌ No | ❌ No | Optional | Optional |
65
+ | **CLI tooling** | ✅ Yes | curl | ❌ No | Limited | Limited |
66
+ | **Header overhead** | **10 bytes** | 200–800 bytes | 2–14 bytes | 5–50 bytes | 2–5 bytes |
67
+ | **Latency (LAN)** | **< 1ms** | 5–50ms | 1–10ms | 1–5ms | 5–20ms |
68
+
69
+ ---
70
+
71
+ ## npm Packages
72
+
73
+ | Package | Description | Link |
74
+ |---|---|---|
75
+ | **`afterlink`** | Meta-package (installs all 3) | [npm](https://www.npmjs.com/package/afterlink) |
76
+ | **`@afterlink/core`** | Frame codec and MessagePack serialization | [npm](https://www.npmjs.com/package/@afterlink/core) |
77
+ | **`@afterlink/server`** | Server SDK (TCP, routing, pub/sub, middleware) | [npm](https://www.npmjs.com/package/@afterlink/server) |
78
+ | **`@afterlink/client`** | Client SDK (auto-reconnect, subscriptions) | [npm](https://www.npmjs.com/package/@afterlink/client) |
79
+
80
+ ---
81
+
82
+ ## Architecture
83
+
84
+ ```
85
+ ┌──────────────────────────────────────────────────────────────────────┐
86
+ │ AfterLink Ecosystem │
87
+ │ │
88
+ │ ┌──────────┐ ┌──────────┐ ┌────────────────────────────────┐ │
89
+ │ │ Browser │ │ Mobile │ │ IoT / Microservices │ │
90
+ │ │ (JS SDK) │ │ (Dart) │ │ (Node.js / Python) │ │
91
+ │ └────┬─────┘ └────┬─────┘ └────────────┬───────────────────┘ │
92
+ │ │ WebSocket │ TCP │ TCP │
93
+ │ └───────────────┼────────────────────────┘ │
94
+ │ │ │
95
+ │ ┌────────▼──────────┐ │
96
+ │ │ AfterLink Server │ │
97
+ │ │ │ ┌──────────────────────────┐ │
98
+ │ │ ┌──────────────┐ │ │ Your Backend │ │
99
+ │ │ │ Frame Router │──┼───▶│ (Supabase / Firebase / │ │
100
+ │ │ └──────┬───────┘ │ │ MongoDB / AWS / pg) │ │
101
+ │ │ │ │ └──────────────────────────┘ │
102
+ │ │ ┌──────▼───────┐ │ │
103
+ │ │ │ Middleware │ │ ┌──────────────────────────┐ │
104
+ │ │ └──────┬───────┘ │ │ Pub/Sub Broker │ │
105
+ │ │ │ │ │ (In-process) │ │
106
+ │ │ ┌──────▼───────┐ │ └──────────────────────────┘ │
107
+ │ │ │ Route Handler│ │ │
108
+ │ │ └──────────────┘ │ │
109
+ │ └────────────────────┘ │
110
+ └──────────────────────────────────────────────────────────────────────┘
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Quick Start
116
+
117
+ ### Installation
118
+
119
+ ```bash
120
+ # Install all packages (recommended)
121
+ npm install afterlink
122
+
123
+ # Or install individual packages
124
+ npm install @afterlink/core @afterlink/server @afterlink/client
125
+ ```
126
+
127
+ **From source:**
128
+
129
+ ```bash
130
+ git clone https://github.com/AJAYMYTH/AfterLink.git
131
+ cd AfterLink
132
+ npm install -g pnpm
133
+ pnpm install
134
+ ```
135
+
136
+ ### Hello World (5 minutes)
137
+
138
+ **Server** — `server.js`
139
+
140
+ ```js
141
+ const { Server } = require('@afterlink/server');
142
+
143
+ const server = new Server({ port: 4000 });
144
+
145
+ server.on('ping', async (req, res) => {
146
+ res.send({ message: 'pong', timestamp: Date.now() });
147
+ });
148
+
149
+ server.listen();
150
+ ```
151
+
152
+ **Client** — `client.js`
153
+
154
+ ```js
155
+ const { Client } = require('@afterlink/client');
156
+
157
+ async function main() {
158
+ const client = new Client('afterlink://localhost:4000');
159
+ await client.connect();
160
+
161
+ const result = await client.request('ping', {});
162
+ console.log(result); // { message: 'pong', timestamp: ... }
163
+
164
+ await client.disconnect();
165
+ }
166
+
167
+ main();
168
+ ```
169
+
170
+ **Run it:**
171
+
172
+ ```bash
173
+ node server.js # Terminal 1
174
+ node client.js # Terminal 2
175
+ ```
176
+
177
+ ### TLS/SSL Encryption
178
+
179
+ ```js
180
+ // Server with TLS
181
+ const { Server, generateDevCerts } = require('@afterlink/server');
182
+ const { key, cert } = await generateDevCerts({ commonName: 'my-server' });
183
+
184
+ const server = new Server({
185
+ port: 4443,
186
+ tls: { enabled: true, key, cert, rejectUnauthorized: false },
187
+ });
188
+
189
+ // Client connects via afterlinks:// scheme
190
+ const client = new Client('afterlinks://localhost:4443');
191
+ ```
192
+
193
+ ### Payload Compression
194
+
195
+ ```js
196
+ // Server enables compression
197
+ const server = new Server({
198
+ port: 4000,
199
+ compression: { enabled: true, algorithm: 'zlib', threshold: 1024 },
200
+ });
201
+
202
+ // Client opts in
203
+ const client = new Client('tcp://localhost:4000', {
204
+ compression: { enabled: true, algorithm: 'zlib' },
205
+ });
206
+ ```
207
+
208
+ ### Rate Limiting
209
+
210
+ ```js
211
+ const server = new Server({
212
+ port: 4000,
213
+ rateLimit: {
214
+ enabled: true,
215
+ requestsPerSecond: 100,
216
+ burstSize: 200,
217
+ closeAfterViolations: 10,
218
+ },
219
+ });
220
+ ```
221
+
222
+ ### Graceful Shutdown
223
+
224
+ ```js
225
+ const server = new Server({
226
+ port: 4000,
227
+ shutdown: { drainTimeout: 5000, reason: 'planned_restart' },
228
+ });
229
+
230
+ server.handleProcessSignals(); // Auto-handles SIGTERM/SIGINT
231
+ await server.listen();
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Features in Action
237
+
238
+ ### 1. Schema Validation
239
+
240
+ Invalid payloads are rejected **before** your handler runs:
241
+
242
+ ```js
243
+ const { z } = require('zod');
244
+
245
+ server.on('createUser',
246
+ async (req, res) => {
247
+ const user = await db.create(req.body);
248
+ res.send({ user });
249
+ },
250
+ z.object({
251
+ name: z.string().min(2),
252
+ email: z.string().email(),
253
+ role: z.enum(['user', 'admin']).optional(),
254
+ })
255
+ );
256
+ ```
257
+
258
+ Client receives automatic error on invalid input:
259
+
260
+ ```json
261
+ { "code": "VALIDATION_ERROR", "message": "String must contain at least 2 character(s)" }
262
+ ```
263
+
264
+ ### 2. Middleware Chain
265
+
266
+ Express-style middleware for auth, logging, and rate limiting:
267
+
268
+ ```js
269
+ server.use(async (req, next) => {
270
+ if (!req.session?.userId) throw new Error('Not authenticated');
271
+ await next();
272
+ });
273
+
274
+ server.use(async (req, next) => {
275
+ const start = Date.now();
276
+ await next();
277
+ console.log(`[${req.route}] ${Date.now() - start}ms`);
278
+ });
279
+
280
+ // Built-in rate limiting (configured via Server options)
281
+ const server = new Server({
282
+ rateLimit: { enabled: true, requestsPerSecond: 100, burstSize: 200 },
283
+ });
284
+ ```
285
+
286
+ ### 3. Real-time Pub/Sub
287
+
288
+ Broadcast to all subscribers over the same connection:
289
+
290
+ ```js
291
+ // Server: publish on event
292
+ server.on('sendMessage', async (req, res) => {
293
+ const msg = await db.save(req.body);
294
+ server.publish('chat.newMessage', msg);
295
+ res.send({ ok: true });
296
+ });
297
+
298
+ // Client: subscribe to topic
299
+ await client.subscribe('chat.newMessage', (msg) => {
300
+ console.log(`[${msg.from}] ${msg.text}`);
301
+ });
302
+ ```
303
+
304
+ ### 4. Auto-Reconnect
305
+
306
+ ```js
307
+ const client = new Client('afterlink://api.example.com', {
308
+ autoReconnect: true,
309
+ maxReconnectAttempts: 10,
310
+ reconnectDelay: 1000,
311
+ });
312
+
313
+ client.on('reconnecting', ({ attempt, delay }) => {
314
+ console.log(`Reconnecting (attempt ${attempt}) in ${delay}ms`);
315
+ });
316
+
317
+ client.on('reconnected', () => console.log('Connection restored'));
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Protocol Specification
323
+
324
+ ### Binary Frame Format
325
+
326
+ ```
327
+ 0 1 2 3
328
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
329
+ ├───────────────┼───────────────┼───────────────────────────────────┤
330
+ │ Frame Type │ Flags │ Message ID (4 bytes) │
331
+ ├───────────────┴───────────────┴───────────────────────────────────┤
332
+ │ Payload Length (4 bytes) │
333
+ ├───────────────────────────────────────────────────────────────────┤
334
+ │ Payload (MessagePack encoded) │
335
+ └───────────────────────────────────────────────────────────────────┘
336
+ ```
337
+
338
+ | Field | Size | Purpose |
339
+ |---|---|---|
340
+ | Frame Type | 1 byte | Identifies the frame (REQUEST, RESPONSE, etc.) |
341
+ | Flags | 1 byte | Compression, encryption, priority bits |
342
+ | Message ID | 4 bytes | Correlates requests with responses (multiplexing) |
343
+ | Payload Length | 4 bytes | Size of the payload in bytes |
344
+ | Payload | Variable | MessagePack-encoded data |
345
+
346
+ **Total header: 10 bytes** | **Max payload: 16 MB**
347
+
348
+ ### Frame Types
349
+
350
+ | Code | Type | Direction | Description |
351
+ |---|---|---|---|
352
+ | `0x01` | REQUEST | C → S | Client request to a named route |
353
+ | `0x02` | RESPONSE | S → C | Server response to a request |
354
+ | `0x03` | STREAM_START | S → C | Begin a streaming sequence |
355
+ | `0x04` | STREAM_DATA | S → C | A chunk of streamed data |
356
+ | `0x05` | STREAM_END | S → C | End of stream |
357
+ | `0x06` | ERROR | Both | Error response |
358
+ | `0x07` | PING | Both | Keep-alive ping |
359
+ | `0x08` | PONG | Both | Keep-alive pong |
360
+ | `0x09` | BROADCAST | S → C | Push to all clients |
361
+ | `0x0A` | SUBSCRIBE | C → S | Subscribe to a topic |
362
+ | `0x0B` | UNSUBSCRIBE | C → S | Unsubscribe from a topic |
363
+ | `0x0C` | PUBLISH | Both | Publish message to a topic |
364
+ | `0x0D` | CLOSE | Both | Graceful connection close |
365
+ | `0x0E` | CLOSE_ACK | Both | Acknowledge close |
366
+ | `0x0F` | HELLO | C → S | Initial handshake |
367
+ | `0x10` | HELLO_ACK | S → C | Handshake acknowledgment |
368
+ | `0x11` | SERVER_CLOSING | S → C | Server shutdown notification |
369
+
370
+ ### Flags Byte
371
+
372
+ | Bit | Mask | Name | Description |
373
+ |---|---|---|---|
374
+ | 0 | `0x01` | COMPRESSED | Payload is compressed (zlib/Brotli) |
375
+ | 1 | `0x02` | ENCRYPTED | Reserved for future end-to-end encryption |
376
+ | 2 | `0x04` | PRIORITY | Reserved for future priority routing |
377
+ | 3 | `0x08` | FRAGMENTED | Reserved for future frame fragmentation |
378
+ | 4–7 | — | Reserved | Must be 0 |
379
+
380
+ ### Connection Lifecycle
381
+
382
+ ```
383
+ Client Server
384
+ │ │
385
+ │──── TCP Connect ──────────────────▶│
386
+ │──── HELLO Frame ──────────────────▶│
387
+ │ { version: "AL/1.1", │
388
+ │ auth: <JWT token>, │
389
+ │ capabilities: [...], │
390
+ │ compression: "zlib" } │
391
+ │ │
392
+ │◀─── HELLO_ACK Frame ──────────────│
393
+ │ { session_id: "...", │
394
+ │ server_version: "AL/1.1", │
395
+ │ compression: "zlib", │
396
+ │ rateLimit: { rps, burst } } │
397
+ │ │
398
+ │◀──▶ REQUEST / RESPONSE frames │
399
+ │◀──▶ PUBLISH / SUBSCRIBE frames │
400
+ │◀──▶ PING / PONG keep-alive │
401
+ │ │
402
+ │──── CLOSE Frame ─────────────────▶│
403
+ │◀─── CLOSE_ACK ────────────────────│
404
+ ```
405
+
406
+ ---
407
+
408
+ ## Backend-Agnostic
409
+
410
+ AfterLink is a **communication layer**, not a database. It works with **any** backend:
411
+
412
+ | Your Backend | SDK | AfterLink Role |
413
+ |---|---|---|
414
+ | **Supabase** | `@supabase/supabase-js` | Real-time layer + auth gateway |
415
+ | **Firebase** | `firebase-admin` | Multi-client sync layer |
416
+ | **AWS** | `@aws-sdk/*` | Persistent connection manager |
417
+ | **MongoDB** | `mongodb` | Real-time change broadcasting |
418
+ | **PostgreSQL** | `pg` | Connection pooling + routing |
419
+ | **Custom REST** | `node-fetch` | Protocol upgrade layer |
420
+
421
+ Switch backends without changing any client code.
422
+
423
+ ---
424
+
425
+ ## Demos
426
+
427
+ ```bash
428
+ cd examples/demo-runner
429
+ node index.js
430
+ ```
431
+
432
+ | Demo | What it Shows |
433
+ |---|---|
434
+ | `demo-runner` | Interactive showcase — 7 demos in one |
435
+ | `demo-chat` | Real-time pub/sub chat app |
436
+ | `demo-dashboard` | Live stock price feed |
437
+ | `demo-microservice` | CRUD with Zod schema validation |
438
+ | `hello-world` | Simple ping/pong starter |
439
+ | `tls-example` | TLS server + client with dev certs |
440
+ | `compression-example` | zlib/Brotli compression demo |
441
+ | `rate-limit-shutdown-example` | Rate limiting + graceful shutdown |
442
+
443
+ ---
444
+
445
+ ## API Reference
446
+
447
+ ### Server
448
+
449
+ ```js
450
+ const server = new Server({
451
+ port: 4000,
452
+ host: '0.0.0.0',
453
+ maxConnections: 10000,
454
+ auth: { type: 'jwt', secret: process.env.JWT_SECRET },
455
+ tls: { enabled: true, key, cert, rejectUnauthorized: false },
456
+ compression: { enabled: true, algorithm: 'zlib', threshold: 1024, level: 6 },
457
+ rateLimit: { enabled: true, requestsPerSecond: 100, burstSize: 200 },
458
+ shutdown: { drainTimeout: 5000, reason: 'planned_restart' },
459
+ });
460
+
461
+ server.on('routeName', async (req, res) => { ... }, schema);
462
+ server.use(async (req, next) => { ... });
463
+ server.publish('topic', data);
464
+ server.on('closing', ({ activeConnections, activeRequests }) => { ... });
465
+ server.on('drained', ({ timedOut }) => { ... });
466
+ server.on('closed', () => { ... });
467
+ server.handleProcessSignals(); // Auto-handles SIGTERM/SIGINT
468
+ await server.listen();
469
+ await server.close(); // Graceful shutdown (async)
470
+ await server.close({ force: true }); // Force close (skip drain)
471
+ server.getConnectionCount();
472
+ server.getRouteCount();
473
+ server.isTLS();
474
+ ```
475
+
476
+ ### Client
477
+
478
+ ```js
479
+ const client = new Client('afterlinks://localhost:4000', {
480
+ timeout: 30000,
481
+ autoReconnect: true,
482
+ maxReconnectAttempts: 5,
483
+ reconnectDelay: 1000,
484
+ pingInterval: 30000,
485
+ compression: { enabled: true, algorithm: 'zlib', level: 6, threshold: 1024 },
486
+ tls: { ca: fs.readFileSync('./ca.cert'), rejectUnauthorized: true },
487
+ });
488
+
489
+ await client.connect();
490
+ const result = await client.request('route', { body });
491
+ await client.subscribe('topic', handler);
492
+ client.publish('topic', data);
493
+ client.on('server-closing', ({ drainTimeout, reason }) => { ... });
494
+ client.on('disconnected', ({ graceful }) => { ... });
495
+ await client.disconnect();
496
+ client.isConnected();
497
+ client.isTLS();
498
+ ```
499
+
500
+ ---
501
+
502
+ ## Project Structure
503
+
504
+ ```
505
+ AfterLink/
506
+ ├── packages/
507
+ │ ├── core/ # Protocol core (Frame, Serializer, Compression)
508
+ │ │ └── src/codec/ # Compression codec (zlib/Brotli)
509
+ │ ├── server/ # Server SDK (TCP, Router, Pub/Sub)
510
+ │ │ ├── src/middleware/ # Rate limiting middleware
511
+ │ │ ├── src/shutdown/ # Graceful shutdown handler
512
+ │ │ └── src/tls/ # Dev certificate generator
513
+ │ └── client/ # Client SDK (TCP, Reconnect, TLS)
514
+ ├── examples/
515
+ │ ├── demo-runner/ # Interactive showcase (7 demos)
516
+ │ ├── demo-chat/ # Real-time chat app
517
+ │ ├── demo-dashboard/ # Stock price dashboard
518
+ │ ├── demo-microservice/ # CRUD with validation
519
+ │ ├── hello-world/ # Simple ping/pong
520
+ │ ├── tls-example/ # TLS server + client demo
521
+ │ ├── compression-example/# Compression demo
522
+ │ └── rate-limit-shutdown-example/
523
+ ├── benchmarks/ # Performance benchmarks (vs WebSocket, Socket.IO)
524
+ ├── docs/ # Protocol and API documentation
525
+ ├── scripts/ # Release scripts (changelog check)
526
+ ├── CHANGELOG.md # Formal versioned changelog
527
+ ├── install.sh # Linux/macOS installer
528
+ ├── install.ps1 # Windows installer
529
+ ├── DEPLOYMENT.md # Full deployment guide
530
+ ├── SECURITY.md # Security policy
531
+ ├── BENCHMARKS.md # Benchmark results and methodology
532
+ └── README.md
533
+ ```
534
+
535
+ ---
536
+
537
+ ## Testing
538
+
539
+ ```bash
540
+ # Run all tests
541
+ pnpm test
542
+
543
+ # Individual package tests
544
+ pnpm test:core # 25 tests (Frame, Serializer, Compression)
545
+ pnpm test:server # 8 tests (Rate Limit, Shutdown)
546
+ pnpm test:client # 6 tests (Client API)
547
+
548
+ # Integration tests
549
+ node test-demos.js
550
+
551
+ # Demo showcase
552
+ cd examples/demo-runner && node index.js
553
+ ```
554
+
555
+ ---
556
+
557
+ ## Benchmarks
558
+
559
+ **Environment**: Node.js v24.14.1 · Windows 11 (x64) · 10,000 iterations · localhost
560
+
561
+ ### Latency (Request/Response)
562
+
563
+ | Library | Avg (ms) | P50 (ms) | P99 (ms) | Throughput |
564
+ |---------|----------|----------|----------|------------|
565
+ | **AfterLink** | **0.033** | **0.028** | **0.122** | **30,167 msg/s** |
566
+ | WebSocket (ws) | 0.058 | 0.037 | 0.199 | 17,054 msg/s |
567
+ | Socket.IO | 0.096 | 0.061 | 0.362 | 10,387 msg/s |
568
+
569
+ **AfterLink is 76.9% faster than WebSocket and 190.4% faster than Socket.IO.**
570
+
571
+ ### Throughput by Payload Size
572
+
573
+ | Bytes | AfterLink | WebSocket | Socket.IO |
574
+ |-------|-----------|-----------|-----------|
575
+ | 64 | 15,474 | 16,501 | 9,592 |
576
+ | 256 | 10,766 | 13,441 | 8,815 |
577
+ | 1,024 | 10,914 | 13,720 | 8,331 |
578
+ | 4,096 | 7,450 | 12,959 | 8,736 |
579
+ | 16,384 | 4,161 | 5,754 | 3,931 |
580
+
581
+ See [BENCHMARKS.md](./BENCHMARKS.md) for full methodology and memory usage data.
582
+
583
+ ---
584
+
585
+ ## Performance Targets
586
+
587
+ | Metric | Target |
588
+ |---|---|
589
+ | Requests/second (single core) | > 100,000 |
590
+ | Round-trip latency (LAN) | < 1ms p50 |
591
+ | Memory per idle connection | < 50 KB |
592
+ | Frame decode time | < 10 µs |
593
+ | Header overhead | 10 bytes |
594
+
595
+ ---
596
+
597
+ ## Security
598
+
599
+ AfterLink is secure by default. See [SECURITY.md](./SECURITY.md) for full details.
600
+
601
+ - **Supply Chain Safe:** Minimal dependencies, locked versions, no postinstall scripts
602
+ - **Protocol Hardened:** Strict frame validation, buffer limits, and MessagePack deserialization
603
+ - **TLS Encryption:** End-to-end encrypted connections with `afterlinks://` scheme
604
+ - **Dev Certificates:** `generateDevCerts()` for self-signed certs without external tools
605
+ - **Rate Limiting:** Per-connection token-bucket rate limiter prevents abuse
606
+ - **JWT Auth:** Built-in JWT validation in HELLO handshake
607
+
608
+ ```bash
609
+ pnpm audit --prod
610
+ ```
611
+
612
+ ---
613
+
614
+ ## Production Deployment
615
+
616
+ See [DEPLOYMENT.md](./DEPLOYMENT.md) for full guides.
617
+
618
+ | Platform | Setup Time | Difficulty |
619
+ |---|---|---|
620
+ | **PM2** (single server) | 2 min | Easy |
621
+ | **Docker** | 5 min | Easy |
622
+ | **Railway** | 2 min | Easy |
623
+ | **Render** | 3 min | Easy |
624
+ | **Fly.io** | 3 min | Easy |
625
+ | **AWS EC2** | 5 min | Medium |
626
+ | **Kubernetes** | 15 min | Advanced |
627
+ | **VPS + Nginx** | 10 min | Medium |
628
+
629
+ ### Quick Start with PM2
630
+
631
+ ```bash
632
+ npm install -g pm2
633
+ pm2 start server.js --name afterlink
634
+ pm2 save && pm2 startup
635
+ ```
636
+
637
+ ### Quick Start with Docker
638
+
639
+ ```dockerfile
640
+ FROM node:20-alpine
641
+ WORKDIR /app
642
+ COPY . .
643
+ RUN npm install -g pnpm && pnpm install --prod
644
+ EXPOSE 4000
645
+ CMD ["node", "server.js"]
646
+ ```
647
+
648
+ ### Environment Variables
649
+
650
+ ```env
651
+ AFTERLINK_PORT=4000
652
+ AFTERLINK_HOST=0.0.0.0
653
+ AFTERLINK_MAX_CONNECTIONS=10000
654
+ AFTERLINK_JWT_SECRET=your-secret
655
+ NODE_ENV=production
656
+ ```
657
+
658
+ ---
659
+
660
+ ## Roadmap
661
+
662
+ > The following upgrades are planned across three phases. See the [Upgrade Schedule](#upgrade-schedule) below for timeline details.
663
+
664
+ ### ~~Phase 1~~ — v1.1 · Protocol & Stability ✅ **COMPLETE**
665
+
666
+ | Feature | Description | Status |
667
+ |---|---|---|
668
+ | **TLS/SSL encryption** | End-to-end encrypted connections via `afterlinks://` | ✅ Done |
669
+ | **Payload compression** | zlib/Brotli compression on the Flags byte | ✅ Done |
670
+ | **Rate limiting middleware** | Per-connection token-bucket rate limiter | ✅ Done |
671
+ | **Graceful shutdown** | Drain active requests, `SERVER_CLOSING` frame | ✅ Done |
672
+ | **CHANGELOG.md** | Formal versioned changelog | ✅ Done |
673
+
674
+ ### Phase 2 — v1.2 · Developer Experience (Weeks 5–8)
675
+
676
+ | Feature | Description |
677
+ |---|---|
678
+ | **`afterlink` CLI tool** | `afterlink ping`, `afterlink call <route>`, `afterlink monitor` in terminal |
679
+ | **`@afterlink/browser`** | Native WebSocket transport wrapper so browsers can connect directly |
680
+ | **TypeScript types** | Full `.d.ts` type definitions for server, client, and core packages |
681
+ | **Health check endpoint** | Built-in `/__health` route returning server stats and uptime |
682
+ | **Better error codes** | Structured error taxonomy: `AUTH_FAILED`, `ROUTE_NOT_FOUND`, `TIMEOUT`, etc. |
683
+
684
+ ### Phase 3 — v2.0 · Scale & Ecosystem (Weeks 9–16)
685
+
686
+ | Feature | Description |
687
+ |---|---|
688
+ | **`@afterlink/cluster`** | Multi-process clustering with shared pub/sub via Redis adapter |
689
+ | **`@afterlink/python`** | Python client/server SDK (`pip install afterlink`) |
690
+ | **`@afterlink/dart`** | Dart/Flutter client for mobile apps |
691
+ | **Protocol v2 frame** | Extended header with routing key + priority field |
692
+ | **Metrics & observability** | Prometheus-compatible `/metrics` endpoint + OpenTelemetry tracing |
693
+ | **Playground UI** | Browser-based interactive demo at `afterlinkdocs.vercel.app/playground` |
694
+
695
+ ---
696
+
697
+ ## Upgrade Schedule
698
+
699
+ ```
700
+ May 2026 ──────────────────────────────────────────────── Aug 2026
701
+
702
+ Week 1–2 [████] ✅ TLS encryption + compression flag
703
+ Week 2–3 [████] ✅ Rate limiting middleware
704
+ Week 3–4 [████] ✅ Graceful shutdown + CHANGELOG
705
+ Week 5–6 [░░░░] CLI tool (afterlink ping/call/monitor)
706
+ Week 6–7 [░░░░] @afterlink/browser WebSocket transport
707
+ Week 7–8 [░░░░] TypeScript definitions + health check
708
+ Week 9–10 [░░░░] Redis-backed cluster pub/sub
709
+ Week 11–12 [░░░░] Python SDK
710
+ Week 13–14 [░░░░] Dart/Flutter SDK
711
+ Week 15 [░░░░] Protocol v2 frame design + migration guide
712
+ Week 16 [░░░░] Prometheus metrics + playground UI launch
713
+ ```
714
+
715
+ | Milestone | Target Date | Version | Status |
716
+ |---|---|---|---|
717
+ | TLS + compression + rate limiting + shutdown | May 2026 | v1.1.0 | ✅ Released |
718
+ | CLI tool + browser SDK + TypeScript | July 2026 | v1.2.0 | 🔄 Planned |
719
+ | Cluster + Python + Dart SDKs | August 2026 | v2.0.0 | 🔄 Planned |
720
+ | Metrics, Protocol v2, Playground | August 2026 | v2.0.0 | 🔄 Planned |
721
+
722
+ ---
723
+
724
+ ## Contributing
725
+
726
+ Contributions, issues, and feature requests are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) to get started.
727
+
728
+ Please note that this project is released with a [Contributor Code of Conduct](./CODE_OF_CONDUCT.md). By participating, you agree to uphold this code.
729
+
730
+ 1. Fork the repository
731
+ 2. Create your feature branch (`git checkout -b feature/my-feature`)
732
+ 3. Commit your changes (`git commit -m 'feat: add my feature'`)
733
+ 4. Push to the branch (`git push origin feature/my-feature`)
734
+ 5. Open a Pull Request
735
+
736
+ **Have a question?** Start a [GitHub Discussion](https://github.com/AJAYMYTH/AfterLink/discussions) — we welcome ideas, Q&A, and project showcases.
737
+
738
+ ---
739
+
740
+ ## Author
741
+
742
+ **Ajju** (Javali Ajayakumar)
743
+ Diploma in AI & ML · GTTC Magadi, Karnataka
744
+ [GitHub](https://github.com/AJAYMYTH) · [npm](https://www.npmjs.com/~ajaymyth)
745
+
746
+ ---
747
+
748
+ ## License
749
+
750
+ [MIT](./LICENSE) — Free for personal and commercial use.
751
+
752
+ ---
753
+
754
+ <div align="center">
755
+
756
+ **Built with precision. Designed for speed.**
757
+
758
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afterlink/server",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "AfterLink Protocol Server SDK - TCP server with routing, middleware, and pub/sub",
5
5
  "main": "src/index.js",
6
6
  "license": "MIT",