exisjs 0.7.12 → 0.7.13

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 (116) hide show
  1. package/README.md +195 -39
  2. package/dist/config/types.d.ts +2 -2
  3. package/dist/config/types.d.ts.map +1 -1
  4. package/dist/decorators/params.d.ts +21 -0
  5. package/dist/decorators/params.d.ts.map +1 -1
  6. package/dist/decorators/params.js +21 -1
  7. package/dist/decorators/params.js.map +1 -1
  8. package/dist/di/container.d.ts +15 -6
  9. package/dist/di/container.d.ts.map +1 -1
  10. package/dist/di/container.js +26 -3
  11. package/dist/di/container.js.map +1 -1
  12. package/dist/di/index.d.ts +1 -1
  13. package/dist/di/index.d.ts.map +1 -1
  14. package/dist/di/index.js.map +1 -1
  15. package/dist/di/inject.d.ts +2 -1
  16. package/dist/di/inject.d.ts.map +1 -1
  17. package/dist/di/inject.js +2 -1
  18. package/dist/di/inject.js.map +1 -1
  19. package/dist/docs/BENCHMARKS.md +4 -4
  20. package/dist/docs/content/README.md +43 -44
  21. package/dist/docs/content/boundaries.mdx +138 -61
  22. package/dist/docs/content/cli/commands.mdx +151 -128
  23. package/dist/docs/content/cli/overview.mdx +61 -47
  24. package/dist/docs/content/cli/usage.mdx +107 -30
  25. package/dist/docs/content/config.mdx +145 -158
  26. package/dist/docs/content/controllers.mdx +193 -464
  27. package/dist/docs/content/cron.mdx +183 -69
  28. package/dist/docs/content/decorators.mdx +449 -154
  29. package/dist/docs/content/errors.mdx +202 -305
  30. package/dist/docs/content/exisjs-mcp.mdx +59 -49
  31. package/dist/docs/content/installation.mdx +243 -157
  32. package/dist/docs/content/introduction.mdx +220 -48
  33. package/dist/docs/content/middleware.mdx +171 -497
  34. package/dist/docs/content/modules.mdx +141 -83
  35. package/dist/docs/content/providers.mdx +216 -180
  36. package/dist/docs/content/requests.mdx +168 -488
  37. package/dist/docs/content/responses.mdx +200 -533
  38. package/dist/docs/content/routing.mdx +235 -598
  39. package/dist/docs/content/security.mdx +233 -57
  40. package/dist/docs/content/structure.mdx +151 -240
  41. package/dist/docs/content/swagger.mdx +192 -91
  42. package/dist/docs/content/testing.mdx +205 -74
  43. package/dist/docs/content/validation.mdx +479 -341
  44. package/dist/docs/reference/README.md +34 -2
  45. package/dist/docs/reference/config.mdx +277 -75
  46. package/dist/docs/reference/context.mdx +197 -106
  47. package/dist/docs/reference/cron.mdx +266 -152
  48. package/dist/docs/reference/database.mdx +135 -53
  49. package/dist/docs/reference/decorators.mdx +234 -116
  50. package/dist/docs/reference/di.mdx +146 -112
  51. package/dist/docs/reference/error.mdx +155 -178
  52. package/dist/docs/reference/exis.mdx +141 -70
  53. package/dist/docs/reference/logger.mdx +110 -126
  54. package/dist/docs/reference/middleware.mdx +235 -158
  55. package/dist/docs/reference/plugin.mdx +136 -64
  56. package/dist/docs/reference/router.mdx +275 -293
  57. package/dist/docs/reference/sanitize.mdx +91 -87
  58. package/dist/docs/reference/swagger.mdx +280 -100
  59. package/dist/docs/reference/testing.mdx +223 -89
  60. package/dist/docs/reference/validator.mdx +194 -206
  61. package/dist/lib/start-server.js +3 -8
  62. package/dist/lib/start-server.js.map +1 -1
  63. package/dist/module/module.d.ts +6 -3
  64. package/dist/module/module.d.ts.map +1 -1
  65. package/dist/module/module.js +17 -3
  66. package/dist/module/module.js.map +1 -1
  67. package/dist/router/controller-registrar.d.ts.map +1 -1
  68. package/dist/router/controller-registrar.js +26 -4
  69. package/dist/router/controller-registrar.js.map +1 -1
  70. package/dist/server/app.d.ts +3 -1
  71. package/dist/server/app.d.ts.map +1 -1
  72. package/dist/server/app.js +24 -8
  73. package/dist/server/app.js.map +1 -1
  74. package/dist/server/request.d.ts +2 -0
  75. package/dist/server/request.d.ts.map +1 -1
  76. package/dist/server/request.js +11 -0
  77. package/dist/server/request.js.map +1 -1
  78. package/dist/swagger/generator.d.ts.map +1 -1
  79. package/dist/swagger/generator.js +130 -10
  80. package/dist/swagger/generator.js.map +1 -1
  81. package/dist/telemetry/index.d.ts +12 -0
  82. package/dist/telemetry/index.d.ts.map +1 -0
  83. package/dist/telemetry/index.js +121 -0
  84. package/dist/telemetry/index.js.map +1 -0
  85. package/dist/testing/client.d.ts +1 -0
  86. package/dist/testing/client.d.ts.map +1 -1
  87. package/dist/testing/client.js +4 -1
  88. package/dist/testing/client.js.map +1 -1
  89. package/dist/testing/index.d.ts.map +1 -1
  90. package/dist/testing/index.js +11 -4
  91. package/dist/testing/index.js.map +1 -1
  92. package/dist/validator/builder.d.ts +26 -1
  93. package/dist/validator/builder.d.ts.map +1 -1
  94. package/dist/validator/builder.js +31 -0
  95. package/dist/validator/builder.js.map +1 -1
  96. package/dist/validator/engine.d.ts +23 -0
  97. package/dist/validator/engine.d.ts.map +1 -1
  98. package/dist/validator/engine.js +228 -31
  99. package/dist/validator/engine.js.map +1 -1
  100. package/dist/validator/index.d.ts +8 -4
  101. package/dist/validator/index.d.ts.map +1 -1
  102. package/dist/validator/index.js +4 -1
  103. package/dist/validator/index.js.map +1 -1
  104. package/dist/validator/tex-types.d.ts +15 -0
  105. package/dist/validator/tex-types.d.ts.map +1 -1
  106. package/dist/validator/tex-types.js +102 -0
  107. package/dist/validator/tex-types.js.map +1 -1
  108. package/dist/validator/tex.d.ts +1 -1
  109. package/dist/validator/tex.d.ts.map +1 -1
  110. package/dist/validator/tex.js +3 -1
  111. package/dist/validator/tex.js.map +1 -1
  112. package/dist/validator/types.d.ts +1 -0
  113. package/dist/validator/types.d.ts.map +1 -1
  114. package/package.json +46 -14
  115. package/dist/docs/content/dataloader.mdx +0 -170
  116. package/dist/docs/reference/dataloader.mdx +0 -91
@@ -1,124 +1,195 @@
1
1
  ---
2
- title: "exis()"
3
- description: "API Reference for the exis() application builder."
2
+ title: "exisjs (Root API)"
3
+ description: "API Reference for the defineApp (exis) entrypoint, App instance methods, lifecycle hooks, and server bootstrap."
4
+ nextUrl: "/docs/reference/config"
5
+ nextTitle: "Config Reference"
4
6
  ---
5
7
 
6
- # Application Instance (exis)
8
+ # `exisjs` (Root API)
7
9
 
8
- The `exis()` function is the primary entry point for configuring and booting your ExisJS application. It defines your core configuration, middleware, plugins, and lifecycle hooks.
10
+ The root `exisjs` module exports the core application builder `defineApp` (aliased as `exis`), the `App` class definition, active application resolvers, response helpers, and circuit breaker utilities.
9
11
 
10
- It returns a configured `App` instance that the CLI or deployment platform will automatically discover and run. The framework's auto-discovery mechanism effortlessly handles both **Functional** and **Class-Based (OOP)** routes inside your `src/http` directory.
12
+ ---
13
+
14
+ ## Module Exports
15
+
16
+ ```typescript
17
+ import {
18
+ exis,
19
+ defineApp,
20
+ App,
21
+ getActiveApp,
22
+ defineConfig,
23
+ parseEnv,
24
+ loadEnv,
25
+ } from 'exisjs'
26
+
27
+ import type {
28
+ ExisConfig,
29
+ ExisPlugin,
30
+ ExisPluginInstance,
31
+ Logger,
32
+ CorsConfig,
33
+ LoggerConfig,
34
+ HookRequest,
35
+ HookResponse,
36
+ HookError,
37
+ HookReady,
38
+ HookClose,
39
+ } from 'exisjs'
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 1. Application Entrypoint: `exis()` / `defineApp()`
45
+
46
+ Defines an ExisJS application definition for CLI execution or programmatic booting.
47
+
48
+ ```typescript
49
+ function defineApp(options?: ExisAppOptions): ExisAppDefinition
50
+ export { defineApp as exis }
51
+ ```
11
52
 
12
- ## Usage
53
+ ### `ExisAppOptions` Interface
13
54
 
14
- ExisJS supports both Functional and Class-Based (OOP) paradigms for configuring your application entry point.
55
+ Extends `ExisConfig` with application lifecycle hooks:
15
56
 
16
- ### 1. Functional Setup
57
+ | Option | Type | Default | Description |
58
+ | :--- | :--- | :--- | :--- |
59
+ | `port` | `number` | `3000` | Port number to bind the server listener to. |
60
+ | `host` | `string` | `'0.0.0.0'` | Network address to bind the listener to. |
61
+ | `env` | `'development' \| 'production' \| 'test'` | `NODE_ENV` | Application execution environment. |
62
+ | `logger` | `boolean \| LoggerConfig` | `true` | Configures or disables the built-in Pino structured logger. |
63
+ | `helmet` | `boolean \| HelmetOptions` | `true` | Automatically injects security response headers. |
64
+ | `cors` | `boolean \| CorsConfig` | `false` | Manages Cross-Origin Resource Sharing headers and preflights. |
65
+ | `compression` | `boolean \| CompressionOptions` | `false` | Response payload compression via Gzip, Deflate, or Brotli. |
66
+ | `plugins` | `(ExisPlugin \| ExisPluginInstance)[]` | `[]` | Array of modules or plugins to initialize on boot. |
67
+ | `middlewares` | `Handler[]` | `[]` | Global middleware executed on all incoming requests. |
68
+ | `onStart` | `(app: App) => void \| Promise<void>` | `undefined` | Hook executed during startup before the listener begins accepting requests. |
69
+ | `onClose` | `(app: App) => void \| Promise<void>` | `undefined` | Hook executed during graceful shutdown. |
70
+
71
+ ---
72
+
73
+ ## 2. Dual-Paradigm Setup
74
+
75
+ ### Functional Paradigm
17
76
 
18
77
  ```typescript filename="src/http/server.ts"
19
78
  import { exis } from 'exisjs'
20
- import { cors } from 'exisjs/middleware'
21
79
 
22
80
  export default exis({
23
81
  port: 3000,
82
+ logger: true,
24
83
  helmet: true,
25
- cors: {
26
- origin: '*',
27
- },
28
- middlewares: [
29
- cors()
30
- ],
84
+ cors: { origin: '*' },
31
85
  async onStart(app) {
32
- app.log.info("Server is starting up!")
33
- }
86
+ app.log.info('Application initialized successfully')
87
+ },
88
+ async onClose(app) {
89
+ app.log.info('Graceful shutdown complete')
90
+ },
34
91
  })
35
92
  ```
36
93
 
37
94
  ---
38
95
 
39
- ### 2. Class-Based Setup (OOP)
40
-
41
- If you prefer an Object-Oriented approach, you can define your application entry point using the `@Server()` decorator.
96
+ ### Class-Based (OOP) Paradigm
42
97
 
43
98
  ```typescript filename="src/http/server.ts"
44
99
  import { Server } from 'exisjs/decorators'
45
100
  import type { App } from 'exisjs'
46
101
 
47
102
  @Server({
48
- plugins: [
49
- // You can register plugins or configuration directly in the decorator options
50
- ]
103
+ plugins: [],
51
104
  })
52
105
  export default class RootServer {
53
106
  async onStart(app: App) {
54
- app.log.info("Server is starting up!")
107
+ app.log.info('Application initialized successfully')
55
108
  }
56
-
109
+
57
110
  async onClose(app: App) {
58
- app.log.info("Server is shutting down!")
111
+ app.log.info('Graceful shutdown complete')
59
112
  }
60
113
  }
61
114
  ```
62
115
 
63
116
  ---
64
117
 
65
- ## Configuration Options
118
+ ## 3. `App` Class Methods Reference
119
+
120
+ The `App` instance coordinates dependency injection, routing, middleware pipelines, lifecycle hooks, and background cron execution.
121
+
122
+ ### Routing & Pipeline
123
+
124
+ | Method | Signature | Description |
125
+ | :--- | :--- | :--- |
126
+ | `use` | `(...handlers: (Handler \| ErrorHandler)[]): this` | Registers global request middlewares or 4-argument error handlers. |
127
+ | `get` | `(path: string, ...handlers: Handler[]): this` | Registers a `GET` route handler. |
128
+ | `post` | `(path: string, ...handlers: Handler[]): this` | Registers a `POST` route handler. |
129
+ | `put` | `(path: string, ...handlers: Handler[]): this` | Registers a `PUT` route handler. |
130
+ | `patch` | `(path: string, ...handlers: Handler[]): this` | Registers a `PATCH` route handler. |
131
+ | `delete` | `(path: string, ...handlers: Handler[]): this` | Registers a `DELETE` route handler. |
132
+ | `mount` | `(prefix: string, subRouter: Router): this` | Mounts a sub-router under a URL path prefix. |
133
+ | `getRoutes` | `(): Route[]` | Returns an array of all compiled route definitions. |
134
+
135
+ ---
136
+
137
+ ### Dependency Injection & Plugins
66
138
 
67
- The `exis()` function takes an `ExisConfig` object.
139
+ | Method | Signature | Description |
140
+ | :--- | :--- | :--- |
141
+ | `provide` | `<T>(token: ProviderToken<T>, provider: ProviderDefinition<T>): this` | Registers a dependency provider into the application container. |
142
+ | `resolve` | `<T>(token: ProviderToken<T>, requestCache?: Map<any, any>): T` | Resolves a singleton or request-scoped dependency from the container. |
143
+ | `register` | `(plugin: ExisPlugin \| ExisPluginInstance, options?: any): Promise<this>` | Registers an encapsulated plugin or module. |
144
+ | `hasPlugin` | `(name: string): boolean` | Checks whether a plugin has been registered. |
68
145
 
69
- ### `port`
70
- - **Type**: `number`
71
- - **Default**: `3000` (or `process.env.PORT`)
72
- - The port the server will listen on during development or manual instantiation.
146
+ ---
147
+
148
+ ### Lifecycle Hooks
73
149
 
74
- ### `host`
75
- - **Type**: `string`
76
- - **Default**: `'0.0.0.0'` (or `process.env.HOST`)
77
- - The host the server will bind to.
150
+ ```typescript
151
+ // Registers a hook called once the server is ready and listening
152
+ app.onReady((app: App) => void | Promise<void>)
78
153
 
79
- ### `env`
80
- - **Type**: `'development' | 'production' | 'test'`
81
- - **Default**: Auto-detected via `NODE_ENV`.
82
- - The current environment of the application.
154
+ // Registers a hook called when the server initiates graceful shutdown
155
+ app.onClose((app: App) => void | Promise<void>)
83
156
 
84
- ### `logger`
85
- - **Type**: `boolean | LoggerConfig`
86
- - **Default**: `true`
87
- - Toggles the built-in Pino logger. You can pass a custom configuration object to set the log level, redact sensitive fields, or output JSON.
157
+ // Registers a hook called on each incoming HTTP request
158
+ app.onRequest((req: Request, res: Response) => void | Promise<void>)
88
159
 
89
- ### `helmet`
90
- - **Type**: `boolean`
91
- - **Default**: `true`
92
- - Automatically applies security headers to every response. Set to `false` to disable.
160
+ // Registers a hook called after an HTTP response finishes dispatching
161
+ app.onResponse((req: Request, res: Response) => void | Promise<void>)
93
162
 
94
- ### `cors`
95
- - **Type**: `boolean | CorsConfig`
96
- - **Default**: `false`
97
- - Automatically injects CORS headers into the request pipeline. You can pass a configuration object to specify allowed origins, methods, and credentials.
163
+ // Registers a hook called whenever an unhandled error occurs
164
+ app.onError((err: Error, req: Request, res: Response) => void | Promise<void>)
165
+ ```
98
166
 
99
- ### `compression`
100
- - **Type**: `boolean`
101
- - **Default**: `true` (if applicable)
102
- - Automatically compresses HTTP responses (gzip/brotli).
167
+ ---
103
168
 
104
- ### `middlewares`
105
- - **Type**: `Handler[]`
106
- - **Default**: `[]`
107
- - An array of global middleware functions that will run on every single request.
169
+ ### Server Execution & Testing
108
170
 
109
- ### `plugins`
110
- - **Type**: `ExisPlugin[]`
111
- - **Default**: `[]`
112
- - An array of ExisJS plugins to register.
171
+ | Method | Signature | Description |
172
+ | :--- | :--- | :--- |
173
+ | `create` | `(cwd?: string): Promise<this>` | Automatically loads configuration, mounts file-system routes, connects databases, and initializes lifecycles. |
174
+ | `listen` | `(portOrOptions?: number \| ListenOptions, callback?: () => void): Server` | Binds the underlying Node.js HTTP/HTTPS server and begins listening for connections. |
175
+ | `close` | `(timeout?: number): Promise<void>` | Initiates graceful server shutdown, drains cron jobs, and destroys DI singletons. |
176
+ | `inject` | `(options: InjectOptions): Promise<TestResponse>` | Dispatches an in-memory synthetic request without binding a real network socket (ideal for unit/E2E testing). |
113
177
 
114
178
  ---
115
179
 
116
- ## Lifecycle Hooks
180
+ ## 4. `getActiveApp()`
117
181
 
118
- You can define async hooks that execute at specific stages of the application's lifecycle.
182
+ Retrieves the currently running singleton `App` instance within the active Node.js process:
119
183
 
120
- ### `onStart(app: App)`
121
- Fired after configuration is loaded but before the server starts accepting connections. This is the ideal place to connect to databases, initialize singletons, or run startup migrations.
184
+ ```typescript
185
+ function getActiveApp(): App
186
+ ```
187
+
188
+ ```typescript filename="src/services/billing.ts"
189
+ import { getActiveApp } from 'exisjs'
122
190
 
123
- ### `onClose(app: App)`
124
- Fired when the server receives a shutdown signal (e.g., `SIGINT`, `SIGTERM`). Use this to gracefully close database connections, flush analytics events, or tear down background workers.
191
+ export function processInvoice(invoiceId: string) {
192
+ const app = getActiveApp()
193
+ app.log.info({ invoiceId }, 'Processing invoice')
194
+ }
195
+ ```
@@ -1,11 +1,17 @@
1
1
  ---
2
- title: "Logger"
3
- description: "API Reference and Architecture Guide for the ExisJS structured logger (exisjs/logger)."
2
+ title: "exisjs/logger"
3
+ description: "API Reference for ExisJS structured logging, Pino integration, configureLogger, custom transports, and formatting helpers."
4
+ nextUrl: "/docs/reference/di"
5
+ nextTitle: "DI Reference"
4
6
  ---
5
7
 
6
- # Logger (`exisjs/logger`)
8
+ # `exisjs/logger`
7
9
 
8
- ExisJS includes a high-performance, zero-overhead structured logging engine powered by Pino. It provides an **industry-standard single-line terminal format** in development and **ultra-fast structured NDJSON** in production for cloud observability platforms (Datadog, Loki, CloudWatch, OpenTelemetry).
10
+ The `exisjs/logger` module provides structured logging powered by Pino. It includes a single-line terminal formatter for development, structured NDJSON output for production environments, automatic credential redaction, request-scoped loggers, and distributed tracing integration.
11
+
12
+ ---
13
+
14
+ ## Module Exports
9
15
 
10
16
  ```typescript
11
17
  import {
@@ -21,60 +27,23 @@ import {
21
27
  formatStatus,
22
28
  formatUrl,
23
29
  formatIp,
30
+ extractValidationSummary,
31
+ extractErrorMessage,
24
32
  } from 'exisjs/logger'
25
- ```
26
33
 
27
- ---
28
-
29
- ## 1. Terminal Request Logging (Development DX)
30
-
31
- When running your application in development mode (`exis dev` or `pretty: true`), ExisJS automatically formats every incoming HTTP request into a clean, concise, single-line terminal log:
32
-
33
- ```text
34
- [22:50:17] [exis] GET / 304 Not Modified 18ms
35
- [22:50:55] [exis] GET /api/v1/profile 200 OK 1.2ms 240 B
36
- [22:51:02] [exis] POST /api/v1/users 201 Created 14.5ms 1.4 KB
37
- [22:51:10] [exis] PATCH /api/v1/users/42 400 Bad Request 3.1ms 120 B
38
- └─ ⚠ Validation [body]: Field "email" must be a valid email format
39
- [22:51:15] [exis] GET /api/v1/unknown 404 Not Found 0.8ms 45 B
40
- [22:51:22] [exis] POST /api/v1/checkout 500 Internal Error 320ms 82 B
41
- └─ ✖ Error: Database connection timeout
34
+ import type { Logger, LoggerConfig } from 'exisjs/logger'
42
35
  ```
43
36
 
44
- ### Visual Features & Formatting Elements
45
-
46
- | Element | Description | Behavior / Color Coding |
47
- | :--- | :--- | :--- |
48
- | **Timestamp** | `[HH:MM:SS]` | Dimmed gray for non-intrusive readability |
49
- | **Brand Badge** | `[exis]` | Framework brand color (`\x1b[38;2;160;70;255m`), `[warn]` (yellow), `[error]` (red) |
50
- | **HTTP Method** | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `QUERY`, `SEARCH`, `OPTIONS`, `HEAD`, `WS`, `SSE`, `CONNECT`, `TRACE`, `PURGE` | Fixed-width padded badge with distinct colors (`GET`/`SEARCH` cyan, `POST` green, `PUT`/`PATCH` yellow, `DELETE`/`PURGE` red, `QUERY` blue, `OPTIONS`/`HEAD`/`WS` magenta) |
51
- | **Path & Query** | `/api/v1/items?page=1` | Path in bright white, query parameters in dimmed gray |
52
- | **Status Code** | `101 Switching Protocols`, `200 OK`, `201 Created`, `400 Bad Request`, `404 Not Found`, `500 Internal Error` | Color-coded by range: `101` magenta, `2xx` green, `3xx` cyan, `4xx` yellow, `5xx` red |
53
- | **Response Latency** | `1.2ms`, `18ms`, `1.45s` | Dynamic threshold color coding: `< 50ms` (green), `50ms - 250ms` (yellow), `> 250ms` (red) |
54
- | **Content Size** | `120 B`, `1.4 KB`, `2.8 MB` | Formatted human-readable byte sizes from `Content-Length` |
55
- | **Client IP** | `192.168.1.5` | Localhost (`127.0.0.1` / `::1`) is suppressed by default for minimal noise; remote client IPs are cleanly displayed |
56
- | **Diagnostic Sublines** | `└─ ⚠ Validation: ...` / `└─ ✖ Error: ...` | Indented warning and error summaries printed directly below failed requests |
57
-
58
37
  ---
59
38
 
60
- ## 2. Structured Logging in Production (NDJSON)
61
-
62
- In production (`NODE_ENV === 'production'` or `pretty: false`), the logger outputs single-line structured JSON (NDJSON) directly to `stdout` with zero serialization overhead:
63
-
64
- ```json
65
- {"level":30,"time":1774286390000,"pid":1234,"hostname":"prod-app-01","requestId":"req-42","method":"GET","url":"/api/v1/profile","statusCode":200,"responseTime":1.2,"contentLength":240,"ip":"10.0.0.4","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","msg":"GET /api/v1/profile"}
66
- ```
39
+ ## Global Logger Singleton (`logger`)
67
40
 
68
- ---
69
-
70
- ## 3. Global Logger Singleton (`logger`)
71
-
72
- The `logger` singleton is a high-performance proxy that can be imported and used anywhere in your services, repositories, workers, and controllers:
41
+ `logger` is a global proxy satisfying the `Logger` interface. It can be imported and executed anywhere across controllers, services, repositories, or background tasks.
73
42
 
74
43
  ```typescript
75
44
  import { logger } from 'exisjs/logger'
76
45
 
77
- // Standard level methods
46
+ // Level logging methods
78
47
  logger.info('Payment service initialized')
79
48
  logger.warn({ ip: req.ip, attempts: 3 }, 'Multiple failed login attempts')
80
49
  logger.error({ err, orderId: 'ord_123' }, 'Stripe webhook processing failed')
@@ -82,16 +51,54 @@ logger.debug({ payload }, 'Parsed RPC frame')
82
51
  logger.trace('Entering database connection pool checkout')
83
52
  logger.fatal({ err }, 'Unrecoverable process state')
84
53
 
85
- // Child loggers with bound context
54
+ // Contextual child loggers
86
55
  const workerLogger = logger.child({ workerId: 'worker-1', queue: 'emails' })
87
56
  workerLogger.info('Processing email batch')
88
57
  ```
89
58
 
59
+ ### `Logger` Interface
60
+
61
+ ```typescript
62
+ export interface LogFn {
63
+ (msg: string, ...args: unknown[]): void
64
+ (obj: Record<string, unknown>, msg?: string, ...args: unknown[]): void
65
+ }
66
+
67
+ export interface Logger {
68
+ fatal: LogFn
69
+ error: LogFn
70
+ warn: LogFn
71
+ info: LogFn
72
+ debug: LogFn
73
+ trace: LogFn
74
+ silent: LogFn
75
+ child(bindings: Record<string, unknown>): Logger
76
+ level: string
77
+ }
78
+ ```
79
+
90
80
  ---
91
81
 
92
- ## 4. Configuration (`configureLogger`)
82
+ ## Configuration (`configureLogger`)
83
+
84
+ Configures global logger settings, default log levels, terminal pretty printing, and sensitive field redaction.
85
+
86
+ ```typescript
87
+ function configureLogger(
88
+ config: LoggerConfig & { replaceRedact?: boolean }
89
+ ): void
90
+ ```
91
+
92
+ ### Options Reference (`LoggerConfig`)
93
+
94
+ | Property | Type | Default | Description |
95
+ | :--- | :--- | :--- | :--- |
96
+ | `level` | `'fatal' \| 'error' \| 'warn' \| 'info' \| 'debug' \| 'trace' \| 'silent'` | `'info'` | Minimum severity level to emit. |
97
+ | `pretty` | `boolean` | `NODE_ENV !== 'production'` | Whether to use formatted single-line terminal output or raw NDJSON. |
98
+ | `redact` | `string[]` | *See Redaction section* | Array of object property paths to censor. |
99
+ | `replaceRedact` | `boolean` | `false` | When `true`, overrides the default redact list instead of merging with it. |
93
100
 
94
- Use `configureLogger()` to adjust log levels, toggle pretty printing, and customize sensitive field redactions across your entire application:
101
+ ### Example
95
102
 
96
103
  ```typescript filename="src/http/server.ts"
97
104
  import { configureLogger } from 'exisjs/logger'
@@ -99,28 +106,45 @@ import { configureLogger } from 'exisjs/logger'
99
106
  configureLogger({
100
107
  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
101
108
  pretty: process.env.NODE_ENV !== 'production',
102
- redact: ['*.password', '*.token', '*.secret', 'req.headers.cookie', '*.creditCard'],
109
+ redact: ['*.password', '*.token', '*.secret', 'req.headers.cookie'],
103
110
  })
104
111
  ```
105
112
 
106
- ### Options Reference
113
+ ---
107
114
 
108
- | Option | Type | Default | Description |
109
- | :--- | :--- | :--- | :--- |
110
- | `level` | `'fatal' \| 'error' \| 'warn' \| 'info' \| 'debug' \| 'trace' \| 'silent'` | `'info'` | Minimum log level to emit |
111
- | `pretty` | `boolean` | `NODE_ENV !== 'production'` | Whether to use colored single-line terminal formatting |
112
- | `redact` | `string[]` | *See Redaction section* | Array of object paths to automatically censor from logs |
113
- | `replaceRedact` | `boolean` | `false` | When `true`, overrides default redact paths instead of merging |
115
+ ## Custom Logger Replacement (`setLogger`)
116
+
117
+ Replaces the underlying global logger instance with a custom Pino instance or third-party logger implementing the `Logger` interface.
118
+
119
+ ```typescript
120
+ function setLogger(custom: Logger): void
121
+ ```
122
+
123
+ ### Example: Custom Transport with `pino-loki`
124
+
125
+ ```typescript filename="src/http/server.ts"
126
+ import { setLogger } from 'exisjs/logger'
127
+ import pino from 'pino'
128
+
129
+ const customPino = pino({
130
+ level: 'info',
131
+ transport: {
132
+ target: 'pino-loki',
133
+ options: { host: 'http://localhost:3100' },
134
+ },
135
+ })
136
+
137
+ setLogger(customPino)
138
+ ```
114
139
 
115
140
  ---
116
141
 
117
- ## 5. Security & Sensitive Data Redaction
142
+ ## Sensitive Data Redaction
118
143
 
119
- By default, ExisJS automatically censors sensitive fields in all log payloads before they are serialized to disk or terminal:
144
+ By default, the logger censors sensitive fields in logged objects, replacing values with `"[Redacted]"` before serialization:
120
145
 
121
146
  ```typescript
122
- // Built-in default redacted paths:
123
- [
147
+ const DEFAULT_REDACT = [
124
148
  'req.headers.authorization',
125
149
  'req.headers.cookie',
126
150
  'req.body.password',
@@ -131,44 +155,43 @@ By default, ExisJS automatically censors sensitive fields in all log payloads be
131
155
  '*.secret',
132
156
  'password',
133
157
  'token',
134
- 'secret'
158
+ 'secret',
135
159
  ]
136
160
  ```
137
161
 
138
- When logging objects containing these keys (e.g. `{ username: 'alex', password: 'supersecretpassword' }`), the value is replaced with `"[Redacted]"`.
139
-
140
162
  ---
141
163
 
142
- ## 6. Request-Scoped Logger (`req.log` / `ctx.log`)
164
+ ## Request-Scoped Logging (`req.log`)
165
+
166
+ Every incoming `ExisRequest` provides a lazy child logger bound to `req.log` containing contextual request metadata:
143
167
 
144
- Every incoming HTTP request in ExisJS provides a zero-allocation lazy child logger bound to `req.log`. It automatically inherits and binds:
145
- - `requestId` (`req.requestId`)
146
- - `method` (`req.method`)
147
- - `url` (`req.path`)
168
+ - `requestId`: Unique request identifier (`req.requestId`).
169
+ - `method`: HTTP method (e.g. `GET`, `POST`).
170
+ - `url`: Request path.
148
171
 
149
172
  ```typescript filename="src/http/orders/route.ts"
150
- import { route, controller } from 'exisjs/router'
173
+ import { controller, route } from 'exisjs/router'
151
174
 
152
175
  export default controller({
153
176
  create: route.post('/', {
154
177
  async handle({ req, body }) {
155
- // req.log automatically includes { requestId, method, url }
156
178
  req.log.info({ orderId: body.id }, 'Creating order record')
157
179
  return { success: true }
158
- }
159
- })
180
+ },
181
+ }),
160
182
  })
161
183
  ```
162
184
 
163
185
  ---
164
186
 
165
- ## 7. OpenTelemetry & Distributed Tracing
187
+ ## Distributed Tracing & OpenTelemetry
166
188
 
167
- ExisJS automatically integrates with `@opentelemetry/api` when present in your environment. Every log entry emitted via `logger` or `req.log` automatically receives the active `trace_id` and `span_id`:
189
+ When `@opentelemetry/api` is present in the application runtime, log entries automatically include active distributed tracing identifiers:
168
190
 
169
191
  ```json
170
192
  {
171
193
  "level": 30,
194
+ "time": 1774286390000,
172
195
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
173
196
  "span_id": "00f067aa0ba902b7",
174
197
  "msg": "Order created successfully"
@@ -177,56 +200,17 @@ ExisJS automatically integrates with `@opentelemetry/api` when present in your e
177
200
 
178
201
  ---
179
202
 
180
- ## 8. Custom Logger Integration (`setLogger`)
203
+ ## Formatting Utilities
181
204
 
182
- To route ExisJS logs directly into custom transports (such as `pino-loki`, `@google-cloud/logging`, or Elasticsearch), supply your custom instance to `setLogger()`:
205
+ The module exports helper utilities for formatting terminal outputs:
183
206
 
184
- ```typescript filename="src/http/server.ts"
185
- import { setLogger } from 'exisjs/logger'
186
- import pino from 'pino'
187
-
188
- const customPino = pino({
189
- level: 'info',
190
- transport: {
191
- target: 'pino-loki',
192
- options: { host: 'http://localhost:3100' }
193
- }
194
- })
195
-
196
- setLogger(customPino)
197
- ```
198
-
199
- ---
200
-
201
- ## 9. Formatting Helper Utilities
202
-
203
- ExisJS exports all terminal formatting helpers from `exisjs/logger` so you can use them in custom CLI tools, workers, and plugins:
204
-
205
- ```typescript
206
- import {
207
- formatBytes,
208
- formatLatency,
209
- formatMethod,
210
- formatStatus,
211
- formatUrl,
212
- formatIp,
213
- extractValidationSummary,
214
- extractErrorMessage,
215
- } from 'exisjs/logger'
216
-
217
- // Byte formatting
218
- formatBytes(1420) // "1.4 KB"
219
-
220
- // Latency with color threshold
221
- formatLatency(14.5) // "\x1b[32m14.5ms\x1b[0m"
222
-
223
- // Padded color-coded method
224
- formatMethod('GET') // "\x1b[1;36mGET \x1b[0m"
225
-
226
- // Status code with standard phrase
227
- formatStatus(200) // "\x1b[1;32m200 OK\x1b[0m"
207
+ | Function | Signature | Output Example |
208
+ | :--- | :--- | :--- |
209
+ | `formatBytes` | `(bytes?: number) => string` | `1420` -> `'1.4 KB'` |
210
+ | `formatLatency` | `(ms?: number) => string` | `14.5` -> `'\x1b[32m14.5ms\x1b[0m'` |
211
+ | `formatMethod` | `(method?: string) => string` | `'GET'` -> `'\x1b[1;36mGET \x1b[0m'` |
212
+ | `formatStatus` | `(status: number) => string` | `200` -> `'\x1b[1;32m200 OK\x1b[0m'` |
213
+ | `formatIp` | `(ip?: string) => string` | `'192.168.1.10'` -> formatted IP string |
214
+ | `createSilentLogger` | `() => Logger` | Returns a no-op logger instance |
215
+ | `isLogger` | `(obj: unknown) => obj is Logger` | Type guard checking `Logger` compliance |
228
216
 
229
- // Localhost suppression
230
- formatIp('127.0.0.1') // "" (suppressed)
231
- formatIp('192.168.1.10') // "\x1b[90m192.168.1.10\x1b[0m"
232
- ```