immortal-js 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +577 -0
  3. package/docs/CHANGELOG.md +21 -0
  4. package/docs/CONTRIBUTING.md +41 -0
  5. package/docs/api/chaos.md +179 -0
  6. package/docs/api/dashboard.md +109 -0
  7. package/docs/api/isolation.md +191 -0
  8. package/docs/api/lifecycle.md +187 -0
  9. package/docs/api/monitoring.md +313 -0
  10. package/docs/api/plugins.md +217 -0
  11. package/docs/api/recovery.md +267 -0
  12. package/docs/api/safe-zone.md +236 -0
  13. package/docs/api/supervision.md +285 -0
  14. package/docs/guides/configuration.md +168 -0
  15. package/docs/guides/express.md +171 -0
  16. package/docs/guides/fastify.md +188 -0
  17. package/docs/guides/koa.md +102 -0
  18. package/docs/guides/nestjs.md +182 -0
  19. package/docs/guides/testing.md +91 -0
  20. package/examples/express-basic/index.ts +462 -0
  21. package/examples/express-basic/package.json +21 -0
  22. package/examples/express-basic/tsconfig.json +24 -0
  23. package/examples/fastify-microservice/index.ts +342 -0
  24. package/examples/fastify-microservice/package.json +22 -0
  25. package/examples/fastify-microservice/tsconfig.json +24 -0
  26. package/examples/invoice-service/data/invoices.db +0 -0
  27. package/examples/invoice-service/data/invoices.db-shm +0 -0
  28. package/examples/invoice-service/data/invoices.db-wal +0 -0
  29. package/examples/invoice-service/package.json +25 -0
  30. package/examples/invoice-service/public/index.html +5025 -0
  31. package/examples/invoice-service/src/db.ts +608 -0
  32. package/examples/invoice-service/src/pdf.ts +358 -0
  33. package/examples/invoice-service/src/server.ts +527 -0
  34. package/examples/invoice-service/src/store.ts +159 -0
  35. package/examples/invoice-service/src/types.ts +193 -0
  36. package/examples/invoice-service/tsconfig.json +23 -0
  37. package/examples/nestjs-enterprise/app.module.ts +561 -0
  38. package/examples/nestjs-enterprise/main.ts +67 -0
  39. package/examples/nestjs-enterprise/package.json +26 -0
  40. package/examples/nestjs-enterprise/tsconfig.json +27 -0
  41. package/immortal-js-1.0.0.tgz +0 -0
  42. package/package.json +33 -0
  43. package/packages/adapter-express/package.json +34 -0
  44. package/packages/adapter-express/src/index.ts +349 -0
  45. package/packages/adapter-express/tsconfig.json +14 -0
  46. package/packages/adapter-fastify/package.json +56 -0
  47. package/packages/adapter-fastify/src/plugin.ts +226 -0
  48. package/packages/adapter-fastify/tsconfig.json +14 -0
  49. package/packages/adapter-koa/package.json +55 -0
  50. package/packages/adapter-koa/src/index.ts +207 -0
  51. package/packages/adapter-koa/tsconfig.json +14 -0
  52. package/packages/adapter-nestjs/package.json +61 -0
  53. package/packages/adapter-nestjs/src/immortal.module.ts +313 -0
  54. package/packages/adapter-nestjs/src/index.ts +14 -0
  55. package/packages/adapter-nestjs/tsconfig.json +16 -0
  56. package/packages/core/package.json +56 -0
  57. package/packages/core/src/chaos/ChaosEngine.ts +249 -0
  58. package/packages/core/src/config/defaults.ts +200 -0
  59. package/packages/core/src/config/schema.ts +199 -0
  60. package/packages/core/src/event-bus.ts +168 -0
  61. package/packages/core/src/index.ts +164 -0
  62. package/packages/core/src/isolation/BulkheadPool.ts +279 -0
  63. package/packages/core/src/isolation/WorkerSandbox.ts +306 -0
  64. package/packages/core/src/isolation/index.ts +8 -0
  65. package/packages/core/src/lifecycle/GracefulShutdown.ts +161 -0
  66. package/packages/core/src/logger.ts +104 -0
  67. package/packages/core/src/monitoring/DiagnosticsChannel.ts +248 -0
  68. package/packages/core/src/monitoring/HealthMonitor.ts +191 -0
  69. package/packages/core/src/monitoring/MemoryLeakGuard.ts +340 -0
  70. package/packages/core/src/monitoring/MetricsCollector.ts +219 -0
  71. package/packages/core/src/monitoring/index.ts +10 -0
  72. package/packages/core/src/plugins/BuiltinPlugins.ts +269 -0
  73. package/packages/core/src/recovery/CircuitBreaker.ts +334 -0
  74. package/packages/core/src/recovery/FallbackCache.ts +328 -0
  75. package/packages/core/src/recovery/RetryEngine.ts +225 -0
  76. package/packages/core/src/recovery/Timeout.ts +97 -0
  77. package/packages/core/src/recovery/index.ts +11 -0
  78. package/packages/core/src/runtime.ts +242 -0
  79. package/packages/core/src/safe-zone/AsyncBoundary.ts +114 -0
  80. package/packages/core/src/safe-zone/ErrorTrap.ts +347 -0
  81. package/packages/core/src/safe-zone/SafeWrapper.ts +317 -0
  82. package/packages/core/src/safe-zone/index.ts +23 -0
  83. package/packages/core/src/supervision/ClusterManager.ts +243 -0
  84. package/packages/core/src/supervision/RestartStrategy.ts +68 -0
  85. package/packages/core/src/supervision/Supervisor.ts +311 -0
  86. package/packages/core/src/supervision/index.ts +11 -0
  87. package/packages/core/src/types.ts +470 -0
  88. package/packages/core/test/bulkhead.test.ts +310 -0
  89. package/packages/core/test/circuit-breaker.test.ts +153 -0
  90. package/packages/core/test/memory-guard.test.ts +213 -0
  91. package/packages/core/test/retry.test.ts +110 -0
  92. package/packages/core/test/safe-zone.test.ts +271 -0
  93. package/packages/core/test/supervisor.test.ts +310 -0
  94. package/packages/core/tsconfig.json +13 -0
  95. package/packages/dashboard/package.json +56 -0
  96. package/packages/dashboard/server/DashboardServer.ts +454 -0
  97. package/packages/dashboard/tsconfig.json +14 -0
  98. package/tsconfig.json +25 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Immortal.js Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,577 @@
1
+ # Immortal.js
2
+
3
+ > **Production-grade resilience framework for Node.js** — five composable layers that make your services impossible to kill.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@immortal/core)](https://www.npmjs.com/package/@immortal/core)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-blue)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green)](./LICENSE)
8
+ [![Tests](https://img.shields.io/badge/tests-102%20passing-brightgreen)](#testing)
9
+
10
+ ---
11
+
12
+ ## What is Immortal.js?
13
+
14
+ Immortal.js is a **monorepo** of battle-tested resilience primitives for Node.js microservices. It implements a strict five-layer architecture:
15
+
16
+ ```
17
+ ┌──────────────────────────────────────────────────────┐
18
+ │ Layer 5 · Observability (Metrics, Health, Logs) │
19
+ ├──────────────────────────────────────────────────────┤
20
+ │ Layer 4 · Supervision (Cluster, Process restart) │
21
+ ├──────────────────────────────────────────────────────┤
22
+ │ Layer 3 · Isolation (Bulkhead, Worker threads) │
23
+ ├──────────────────────────────────────────────────────┤
24
+ │ Layer 2 · Recovery (Retry, Circuit Breaker) │
25
+ ├──────────────────────────────────────────────────────┤
26
+ │ Layer 1 · Containment (Safe Zone, Error Trap) │
27
+ └──────────────────────────────────────────────────────┘
28
+ ```
29
+
30
+ Each layer is independently usable; together they provide defense-in-depth against every class of production failure.
31
+
32
+ ---
33
+
34
+ ## Packages
35
+
36
+ | Package | Description | Version |
37
+ |---------|-------------|---------|
38
+ | [`@immortal/core`](./packages/core) | Core resilience primitives | `1.0.0` |
39
+ | [`@immortal/fastify`](./packages/adapter-fastify) | Fastify integration plugin | `1.0.0` |
40
+ | [`@immortal/nestjs`](./packages/adapter-nestjs) | NestJS module + decorators | `1.0.0` |
41
+ | [`@immortal/koa`](./packages/adapter-koa) | Koa middleware | `1.0.0` |
42
+ | [`@immortal/dashboard`](./packages/dashboard) | Real-time health dashboard | `1.0.0` |
43
+
44
+ ---
45
+
46
+ ## Quick Start
47
+
48
+ ```bash
49
+ npm install @immortal/core
50
+ ```
51
+
52
+ ```typescript
53
+ import { createImmortal, withRetry, CircuitBreaker } from '@immortal/core';
54
+
55
+ // 1. Initialize the runtime
56
+ const immortal = await createImmortal({
57
+ logger: { level: 'info' },
58
+ healthMonitor: { enabled: true },
59
+ gracefulShutdown: { enabled: true, timeoutMs: 30_000 },
60
+ });
61
+
62
+ // 2. Add a circuit breaker around any I/O call
63
+ const breaker = new CircuitBreaker('payment-service', {
64
+ threshold: 5,
65
+ timeout: 60_000,
66
+ halfOpenRequests: 2,
67
+ });
68
+
69
+ const result = await breaker.run(async () => {
70
+ return await paymentApi.charge(amount);
71
+ });
72
+
73
+ // 3. Retry with exponential backoff
74
+ const data = await withRetry(
75
+ () => fetch('https://api.example.com/data'),
76
+ { maxAttempts: 3, baseDelayMs: 200, backoffFactor: 2 }
77
+ );
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Installation
83
+
84
+ ### npm workspaces (monorepo)
85
+
86
+ ```bash
87
+ git clone https://github.com/Brah-Timo/immortal-js.git
88
+ cd immortal-js
89
+ npm install
90
+ npm test
91
+ ```
92
+
93
+ ### Single package
94
+
95
+ ```bash
96
+ npm install @immortal/core
97
+ ```
98
+
99
+ ### With framework adapter
100
+
101
+ ```bash
102
+ # Fastify
103
+ npm install @immortal/core @immortal/fastify fastify
104
+
105
+ # NestJS
106
+ npm install @immortal/core @immortal/nestjs @nestjs/core @nestjs/common reflect-metadata
107
+
108
+ # Koa
109
+ npm install @immortal/core @immortal/koa koa
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Core API
115
+
116
+ ### Layer 1 — Containment (Safe Zone)
117
+
118
+ Catches all unhandled errors at process and request boundaries.
119
+
120
+ ```typescript
121
+ import { AsyncBoundary, asyncBoundary, ErrorTrap, classifyError } from '@immortal/core';
122
+
123
+ // Classify errors for routing
124
+ const kind = classifyError(error);
125
+ // → 'operational' | 'programming' | 'transient' | 'external' | 'unknown'
126
+
127
+ // Wrap a handler with automatic boundary context
128
+ const safeFn = asyncBoundary(myHandler, { fallback: () => defaultResponse });
129
+
130
+ // Static boundary methods
131
+ AsyncBoundary.run(async () => {
132
+ const ctx = AsyncBoundary.getContext(); // trace ID, request ID, etc.
133
+ });
134
+
135
+ // Global error trap (uncaught exceptions + unhandled rejections)
136
+ const trap = new ErrorTrap(bus);
137
+ trap.install();
138
+ ```
139
+
140
+ ### Layer 2 — Recovery
141
+
142
+ **Retry Engine** with exponential backoff and jitter:
143
+
144
+ ```typescript
145
+ import { withRetry, withTimeout, calculateBackoff } from '@immortal/core';
146
+
147
+ const result = await withRetry(operation, {
148
+ maxAttempts: 5,
149
+ baseDelayMs: 100,
150
+ backoffFactor: 2,
151
+ jitter: true,
152
+ retryOn: (err) => err.code === 'ECONNRESET',
153
+ });
154
+
155
+ const bounded = await withTimeout(operation, 5_000, 'payment-charge');
156
+ ```
157
+
158
+ **Circuit Breaker** with half-open probing:
159
+
160
+ ```typescript
161
+ import { CircuitBreaker, CircuitBreakerRegistry } from '@immortal/core';
162
+
163
+ const cb = new CircuitBreaker('db', {
164
+ threshold: 5, // failures before opening
165
+ timeout: 30_000, // ms before trying half-open
166
+ halfOpenRequests: 3,
167
+ });
168
+
169
+ // States: 'closed' | 'open' | 'half-open'
170
+ const state = cb.getCurrentState();
171
+
172
+ // Force state (testing)
173
+ cb.forceState('open');
174
+
175
+ // Registry for multi-service management
176
+ const registry = CircuitBreakerRegistry.getInstance();
177
+ registry.get('db').getCurrentState();
178
+ ```
179
+
180
+ **Fallback Cache** — serve stale on failure:
181
+
182
+ ```typescript
183
+ import { RouteFallbackCache } from '@immortal/core';
184
+
185
+ const cache = new RouteFallbackCache({ maxEntries: 500, ttlMs: 60_000 });
186
+ cache.set('GET /products/42', productData, { ttlMs: 300_000 });
187
+
188
+ const stale = cache.get('GET /products/42');
189
+ ```
190
+
191
+ ### Layer 3 — Isolation
192
+
193
+ **Bulkhead Pool** — limit concurrency per service:
194
+
195
+ ```typescript
196
+ import { BulkheadPool, BulkheadRegistry } from '@immortal/core';
197
+
198
+ const pool = new BulkheadPool('database', {
199
+ maxConcurrent: 10,
200
+ maxQueueSize: 50,
201
+ defaultTimeoutMs: 5_000,
202
+ });
203
+
204
+ const result = await pool.run(async () => db.query(sql), 'high', 3_000);
205
+
206
+ const status = pool.getStatus();
207
+ // → { name, active, queued, maxConcurrent, maxQueueSize, rejected, totalExecuted }
208
+ ```
209
+
210
+ **Worker Sandbox** — run untrusted code in a thread:
211
+
212
+ ```typescript
213
+ import { WorkerSandbox } from '@immortal/core';
214
+
215
+ const sandbox = new WorkerSandbox({ timeoutMs: 5_000, memoryLimitMb: 64 });
216
+ const result = await sandbox.execute(`return input * 2`, { input: 21 });
217
+ // → 42
218
+ ```
219
+
220
+ ### Layer 4 — Supervision
221
+
222
+ **Supervisor** — manages named async processes with automatic restart:
223
+
224
+ ```typescript
225
+ import { Supervisor } from '@immortal/core';
226
+
227
+ const supervisor = new Supervisor({
228
+ config: { maxRestartsInWindow: 5, windowMs: 60_000, baseRestartDelayMs: 1_000 },
229
+ onEscalation: (id) => alertTeam(`Worker ${id} is broken!`),
230
+ });
231
+
232
+ supervisor.register('http-server', {
233
+ spawnFn: () => startHttpServer(),
234
+ terminate: (instance) => instance.close(),
235
+ });
236
+
237
+ // Get all worker states
238
+ const statuses = supervisor.getWorkerStatuses();
239
+ // → [{ id, state, restartCount, uptime, pid?, lastRestartTime? }]
240
+
241
+ await supervisor.stop('http-server');
242
+ await supervisor.stopAll();
243
+ ```
244
+
245
+ **Cluster Manager** — multi-core process management:
246
+
247
+ ```typescript
248
+ import { ClusterManager } from '@immortal/core';
249
+
250
+ if (ClusterManager.isPrimary()) {
251
+ const mgr = new ClusterManager({
252
+ workerCount: 4,
253
+ onEscalation: (id) => console.error(`Worker ${id} escalated`),
254
+ });
255
+ await mgr.start();
256
+ // Zero-downtime rolling restart
257
+ await mgr.rollingRestart();
258
+ } else {
259
+ await startApp();
260
+ }
261
+ ```
262
+
263
+ ### Layer 5 — Observability
264
+
265
+ **Metrics Collector** — system metrics snapshot:
266
+
267
+ ```typescript
268
+ import { MetricsCollector } from '@immortal/core';
269
+
270
+ const collector = new MetricsCollector();
271
+ const snapshot = collector.getSnapshot();
272
+ // → { timestamp, eventLoopLag, memory, cpu, handles, requests, circuits, bulkheads, workers }
273
+ ```
274
+
275
+ **Health Monitor** — periodic health checks:
276
+
277
+ ```typescript
278
+ import { HealthMonitor } from '@immortal/core';
279
+
280
+ const monitor = new HealthMonitor(
281
+ { checkIntervalMs: 30_000, eventLoopLagCriticalMs: 100 },
282
+ bus,
283
+ metricsCollector
284
+ );
285
+ monitor.start();
286
+ ```
287
+
288
+ **Memory Leak Guard** — detect and react to memory growth:
289
+
290
+ ```typescript
291
+ import { MemoryLeakGuard } from '@immortal/core';
292
+
293
+ const guard = new MemoryLeakGuard({
294
+ checkIntervalMs: 30_000,
295
+ warningThresholdMb: 400,
296
+ restartThresholdMb: 600,
297
+ growthWindowCount: 5,
298
+ }, bus);
299
+
300
+ guard.start();
301
+ ```
302
+
303
+ **Diagnostics Channel** — OpenTelemetry-compatible tracing:
304
+
305
+ ```typescript
306
+ import { DiagnosticsChannel } from '@immortal/core';
307
+
308
+ const dc = new DiagnosticsChannel({ otlpEndpoint: 'http://otel-collector:4318' });
309
+ dc.recordRequest({ route: '/api/users', method: 'GET', statusCode: 200, durationMs: 45 });
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Plugins
315
+
316
+ Immortal.js has a first-class plugin system:
317
+
318
+ ```typescript
319
+ import {
320
+ createImmortal,
321
+ ConsoleLogPlugin,
322
+ RequestTracingPlugin,
323
+ createAnomalyDetectionPlugin,
324
+ createSlackAlertPlugin,
325
+ } from '@immortal/core';
326
+
327
+ const immortal = await createImmortal({
328
+ plugins: [
329
+ ConsoleLogPlugin,
330
+ RequestTracingPlugin,
331
+ createAnomalyDetectionPlugin({ threshold: 0.1 }),
332
+ createSlackAlertPlugin({ webhookUrl: process.env.SLACK_WEBHOOK! }),
333
+ ],
334
+ });
335
+ ```
336
+
337
+ **Built-in plugins:**
338
+
339
+ | Plugin | Description |
340
+ |--------|-------------|
341
+ | `ConsoleLogPlugin` | Structured JSON logging to stdout |
342
+ | `RequestTracingPlugin` | Request ID propagation via AsyncLocalStorage |
343
+ | `createAnomalyDetectionPlugin` | Statistical anomaly detection on metrics |
344
+ | `createSlackAlertPlugin` | Slack webhook notifications for critical events |
345
+
346
+ **Custom plugins:**
347
+
348
+ ```typescript
349
+ import type { ImmortalPlugin } from '@immortal/core';
350
+
351
+ const myPlugin: ImmortalPlugin = {
352
+ name: 'my-plugin',
353
+ async onInit(ctx) {
354
+ ctx.logger.info('Plugin initialized', { config: ctx.config });
355
+ },
356
+ async onShutdown(signal) {
357
+ // cleanup
358
+ },
359
+ };
360
+ ```
361
+
362
+ ---
363
+
364
+ ## Chaos Engineering
365
+
366
+ Test your resilience in staging:
367
+
368
+ ```typescript
369
+ import { ChaosEngine } from '@immortal/core';
370
+
371
+ const chaos = new ChaosEngine();
372
+
373
+ // Inject latency into specific routes
374
+ chaos.addFault({
375
+ type: 'latency',
376
+ probability: 0.1, // 10% of requests
377
+ minMs: 100,
378
+ maxMs: 2000,
379
+ targetRoutes: ['/api/orders'],
380
+ });
381
+
382
+ // Random errors
383
+ chaos.addFault({
384
+ type: 'error',
385
+ probability: 0.05, // 5% error rate
386
+ errorMessage: 'Chaos: simulated service failure',
387
+ });
388
+
389
+ // Wrap a handler
390
+ const chaosHandler = chaos.wrapHandler(originalHandler);
391
+
392
+ // Enable/disable at runtime
393
+ chaos.enable();
394
+ chaos.disable();
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Framework Integrations
400
+
401
+ ### Fastify
402
+
403
+ ```typescript
404
+ import Fastify from 'fastify';
405
+ import immortalPlugin from '@immortal/fastify';
406
+
407
+ const app = Fastify();
408
+ await app.register(immortalPlugin, {
409
+ circuitBreakers: true,
410
+ bulkheads: true,
411
+ metrics: true,
412
+ gracefulShutdown: true,
413
+ });
414
+ ```
415
+
416
+ See [examples/fastify-microservice](./examples/fastify-microservice/index.ts) for a full example.
417
+
418
+ ### NestJS
419
+
420
+ ```typescript
421
+ import { Module } from '@nestjs/common';
422
+ import { ImmortalModule } from '@immortal/nestjs';
423
+
424
+ @Module({
425
+ imports: [
426
+ ImmortalModule.forRoot({
427
+ logger: { level: 'info' },
428
+ gracefulShutdown: { enabled: true },
429
+ }),
430
+ ],
431
+ })
432
+ export class AppModule {}
433
+ ```
434
+
435
+ **Decorators:**
436
+
437
+ ```typescript
438
+ import { Bulkhead, Circuit, Retry } from '@immortal/nestjs';
439
+
440
+ @Injectable()
441
+ export class OrdersService {
442
+ @Bulkhead({ pool: 'orders', maxConcurrent: 5 })
443
+ @Circuit({ name: 'order-db', threshold: 3 })
444
+ @Retry({ maxAttempts: 2 })
445
+ async createOrder(dto: CreateOrderDto) {
446
+ return this.db.orders.create(dto);
447
+ }
448
+ }
449
+ ```
450
+
451
+ See [examples/nestjs-enterprise](./examples/nestjs-enterprise/app.module.ts) for a full example.
452
+
453
+ ### Koa
454
+
455
+ ```typescript
456
+ import Koa from 'koa';
457
+ import { immortalMiddleware } from '@immortal/koa';
458
+
459
+ const app = new Koa();
460
+ app.use(immortalMiddleware({ circuitBreakers: true, metrics: true }));
461
+ ```
462
+
463
+ ---
464
+
465
+ ## Configuration Reference
466
+
467
+ ```typescript
468
+ interface ImmortalConfig {
469
+ logger?: {
470
+ level?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
471
+ transport?: 'console' | 'json' | 'pretty';
472
+ prefix?: string;
473
+ };
474
+ healthMonitor?: {
475
+ enabled?: boolean;
476
+ checkIntervalMs?: number;
477
+ eventLoopLagWarningMs?: number;
478
+ eventLoopLagCriticalMs?: number;
479
+ heapUsageWarningPercent?: number;
480
+ heapUsageCriticalPercent?: number;
481
+ };
482
+ memoryGuard?: {
483
+ enabled?: boolean;
484
+ checkIntervalMs?: number;
485
+ warningThresholdMb?: number;
486
+ restartThresholdMb?: number;
487
+ growthWindowCount?: number;
488
+ adaptive?: boolean;
489
+ };
490
+ gracefulShutdown?: {
491
+ enabled?: boolean;
492
+ timeoutMs?: number;
493
+ signals?: NodeJS.Signals[];
494
+ };
495
+ chaos?: {
496
+ enabled?: boolean;
497
+ };
498
+ plugins?: ImmortalPlugin[];
499
+ }
500
+ ```
501
+
502
+ ---
503
+
504
+ ## Testing
505
+
506
+ ```bash
507
+ # All tests
508
+ npm test --workspaces --if-present
509
+
510
+ # Core package only
511
+ cd packages/core && npm test
512
+
513
+ # Watch mode
514
+ cd packages/core && npm test -- --watch
515
+
516
+ # Coverage
517
+ cd packages/core && npm test -- --coverage
518
+ ```
519
+
520
+ **102 tests across 6 test suites** — all passing.
521
+
522
+ ---
523
+
524
+ ## Project Structure
525
+
526
+ ```
527
+ immortal/
528
+ ├── packages/
529
+ │ ├── core/ # Main resilience library
530
+ │ │ ├── src/
531
+ │ │ │ ├── safe-zone/ # Layer 1: Containment
532
+ │ │ │ ├── recovery/ # Layer 2: Retry, CircuitBreaker, FallbackCache
533
+ │ │ │ ├── isolation/ # Layer 3: BulkheadPool, WorkerSandbox
534
+ │ │ │ ├── supervision/ # Layer 4: Supervisor, ClusterManager
535
+ │ │ │ ├── monitoring/ # Layer 5: Metrics, Health, MemoryGuard
536
+ │ │ │ ├── lifecycle/ # GracefulShutdown
537
+ │ │ │ ├── chaos/ # ChaosEngine
538
+ │ │ │ ├── plugins/ # Built-in plugins
539
+ │ │ │ ├── config/ # Defaults & validation
540
+ │ │ │ ├── event-bus.ts # Typed internal event bus
541
+ │ │ │ ├── logger.ts # Structured logger
542
+ │ │ │ ├── runtime.ts # ImmortalRuntime orchestrator
543
+ │ │ │ ├── types.ts # All TypeScript interfaces
544
+ │ │ │ └── index.ts # Public API surface
545
+ │ │ └── test/ # Vitest test suites
546
+ │ ├── adapter-fastify/ # Fastify plugin
547
+ │ ├── adapter-nestjs/ # NestJS module
548
+ │ ├── adapter-koa/ # Koa middleware
549
+ │ └── dashboard/ # Real-time dashboard
550
+ ├── examples/
551
+ │ ├── fastify-microservice/ # Complete Fastify example
552
+ │ └── nestjs-enterprise/ # Complete NestJS example
553
+ ├── docs/
554
+ │ ├── api/ # Per-module API docs
555
+ │ └── guides/ # Integration guides
556
+ ├── package.json # npm workspaces root
557
+ ├── tsconfig.json # TypeScript 5.4+ strict config
558
+ └── LICENSE # MIT
559
+ ```
560
+
561
+ ---
562
+
563
+ ## Contributing
564
+
565
+ See [docs/CONTRIBUTING.md](./docs/CONTRIBUTING.md).
566
+
567
+ ---
568
+
569
+ ## Changelog
570
+
571
+ See [docs/CHANGELOG.md](./docs/CHANGELOG.md).
572
+
573
+ ---
574
+
575
+ ## License
576
+
577
+ MIT © Immortal.js Contributors — see [LICENSE](./LICENSE).
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to Immortal.js will be documented in this file.
4
+
5
+ ## [1.0.0] — 2026-07-25
6
+
7
+ ### Added
8
+ - **Layer 1 (Containment)**: `AsyncBoundary`, `asyncBoundary`, `ErrorTrap`, `classifyError`, `serializeError`, `ImmortalError`, `createSafeZone`
9
+ - **Layer 2 (Recovery)**: `withRetry`, `withTimeout`, `calculateBackoff`, `CircuitBreaker`, `CircuitBreakerRegistry`, `RouteFallbackCache`
10
+ - **Layer 3 (Isolation)**: `BulkheadPool`, `BulkheadRegistry`, `WorkerSandbox`, `BulkheadRejectedError`
11
+ - **Layer 4 (Supervision)**: `Supervisor`, `ClusterManager`, `computeRestartDecision`
12
+ - **Layer 5 (Observability)**: `MetricsCollector`, `HealthMonitor`, `MemoryLeakGuard`, `DiagnosticsChannel`
13
+ - **Lifecycle**: `GracefulShutdown`, `createImmortal`, `getImmortal`, `ImmortalRuntime`
14
+ - **Chaos**: `ChaosEngine` with latency, error, and worker-kill fault types
15
+ - **Plugins**: `ConsoleLogPlugin`, `RequestTracingPlugin`, `createAnomalyDetectionPlugin`, `createSlackAlertPlugin`
16
+ - **Event bus**: `ImmortalEventBus` with typed events, history, and wildcard subscriptions
17
+ - **Packages**: `@immortal/fastify`, `@immortal/nestjs`, `@immortal/koa`, `@immortal/dashboard`
18
+ - **Examples**: `fastify-microservice`, `nestjs-enterprise`
19
+ - **Docs**: Full API reference and integration guides
20
+ - **Tests**: 102 tests across 6 suites, all passing
21
+ - **TypeScript**: Strict mode with `exactOptionalPropertyTypes`, `noUncheckedIndexedAccess`, `noImplicitOverride`
@@ -0,0 +1,41 @@
1
+ # Contributing to Immortal.js
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/your-org/immortal-js.git
7
+ cd immortal-js
8
+ npm install
9
+ ```
10
+
11
+ ## Development
12
+
13
+ ```bash
14
+ # TypeScript check
15
+ ./node_modules/.bin/tsc --noEmit --project packages/core/tsconfig.json
16
+
17
+ # Run tests
18
+ npm test --workspaces --if-present
19
+
20
+ # Watch mode
21
+ cd packages/core && npm test -- --watch
22
+ ```
23
+
24
+ ## Pull Request checklist
25
+
26
+ - [ ] `tsc --noEmit` passes with zero errors
27
+ - [ ] All existing tests pass
28
+ - [ ] New functionality has tests
29
+ - [ ] Public API changes are documented in `docs/`
30
+ - [ ] `docs/CHANGELOG.md` entry added
31
+
32
+ ## Code style
33
+
34
+ - TypeScript strict mode — all five flags in `tsconfig.json` must be satisfied
35
+ - No `any` without a comment explaining why
36
+ - `exactOptionalPropertyTypes`: use `if (x !== undefined) obj.field = x` instead of direct assignment
37
+ - `delete obj.field` to clear optional fields instead of `= undefined`
38
+
39
+ ## License
40
+
41
+ By contributing, you agree your contributions are licensed under MIT.