@venizia/ignis-docs 0.2.0 → 0.2.1-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 (142) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +22 -11
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +6 -2
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +182 -93
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -20,17 +20,17 @@ APP_ENV_POSTGRES_PASSWORD=database_password_here
20
20
 
21
21
  **Generate strong secrets:**
22
22
  ```bash
23
- node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
23
+ bun -e "console.log(Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('base64'))"
24
24
  ```
25
25
 
26
26
  ### Redaction at Log Time
27
27
 
28
- Never hard-coding a secret is not enough on its own -- an options object holding one still ends up in a log line the moment it is passed to `logger.info('...: %s', opts)`. `@venizia/ignis-helpers` provides two primitives for exactly this:
28
+ Never hard-coding a secret is not enough on its own - an options object holding one still ends up in a log line the moment it is passed to `logger.info('...: %s', opts)`. `@venizia/ignis-helpers` provides two primitives for exactly this:
29
29
 
30
30
  | Function | Use For | Behavior |
31
31
  |----------|---------|----------|
32
- | `redactSecrets(value)` | Any object/array being logged | Recursively replaces every value whose key matches a secret-looking name (`password`, `token`, `apiKey`, `authorization`, HTTP header spellings like `x-api-key`/`cookie`/`proxy-authorization`, etc., case-insensitive) with `'[REDACTED]'` |
33
- | `redactUrlCredentials(url)` | A connection/broker URL string | Strips the password out of a URL's authority section (`mqtts://user:hunter2@broker:8883` becomes `mqtts://user:[REDACTED]@broker:8883`); a value that doesn't parse as a URL is returned unchanged |
32
+ | `redactSecrets(value)` | Any object/array being logged | Recursively replaces every value whose key matches a secret-looking name with `'[REDACTED]'` |
33
+ | `redactUrlCredentials(url)` | A connection/broker URL string | Strips the password out of a URL's authority section (`mqtts://user:hunter2@broker:8883` becomes `mqtts://user:[REDACTED]@broker:8883`); a value that doesn't parse as a URL, or one with no password, is returned unchanged |
34
34
 
35
35
  ```typescript
36
36
  import { redactSecrets, redactUrlCredentials } from '@venizia/ignis-helpers';
@@ -39,7 +39,19 @@ this.logger.info('[connect] Options: %s', redactSecrets(connectionOptions));
39
39
  this.logger.info('[connect] Broker: %s', redactUrlCredentials(brokerUrl));
40
40
  ```
41
41
 
42
- These are the primitives the framework itself uses -- outbound HTTP request configs (`NodeFetcher`/`AxiosFetcher`, see [Network Helper](/extensions/helpers/network/)) and MQTT broker URLs (`MQTTClientHelper`, see [Queue Helper](/extensions/helpers/queue/)) are both redacted this way before they reach a log line.
42
+ `redactSecrets` matches on the **key name**, case-insensitively, at any depth:
43
+
44
+ - Options-object spellings: `password`, `passphrase`, `secret`, `token`, `apiKey`, `privateKey`, `credentials`, `authorization`, `connectionString`, ...
45
+ - Any `*_token` / `*Token` key: `access_token`, `refresh_token`, `vaultToken`, ...
46
+ - Vault wire keys: `client_token`, `secret_id`, `role_id`
47
+ - HTTP header spellings: `x-api-key`, `x-vault-token`, `cookie`, `set-cookie`, `proxy-authorization`, `www-authenticate`
48
+
49
+ It also handles the shapes naive redaction breaks on: an `Error` is reprojected so its non-enumerable `message`/`stack` survive, cycles become `'[Circular]'`, and buffers/typed arrays are summarized as `[Binary N bytes]` instead of serialized.
50
+
51
+ These are the primitives the framework itself uses - outbound HTTP request configs (`NodeFetcher`/`AxiosFetcher`, see [Network Helper](/extensions/helpers/network/)) and MQTT broker URLs (`MQTTClientHelper`, see [Queue Helper](/extensions/helpers/queue/)) are both redacted this way before they reach a log line.
52
+
53
+ > [!WARNING]
54
+ > `APP_ENV_LOGGER_DO_REDACT=false` turns both functions into the identity function. It is a local-debugging kill-switch and must never be set in production. The check is fail-closed - only the literal string `false` disables redaction - and is read per call, so it can be flipped at runtime.
43
55
 
44
56
  ## 2. Input Validation
45
57
 
@@ -110,7 +122,7 @@ Configure model properties that should **never be returned** through repository
110
122
  hiddenProperties: ['password', 'apiSecret', 'internalToken'],
111
123
  },
112
124
  })
113
- export class User extends BasePostgresEntity<typeof User.schema> {
125
+ export class User extends BaseRelationalEntity<typeof User.schema> {
114
126
  static override schema = pgTable('User', {
115
127
  ...generateIdColumnDefs({ id: { dataType: 'string' } }),
116
128
  email: text('email').notNull(),
@@ -131,7 +143,7 @@ export class User extends BasePostgresEntity<typeof User.schema> {
131
143
 
132
144
  ```typescript
133
145
  // For authentication - access password via connector
134
- const connector = userRepository.getConnector();
146
+ const connector = userRepository.connector;
135
147
  const [user] = await connector
136
148
  .select({ id: User.schema.id, password: User.schema.password })
137
149
  .from(User.schema)
@@ -339,7 +351,7 @@ const redisHelper = new RedisSingleHelper({
339
351
  name: 'rate-limiter',
340
352
  host: process.env.APP_ENV_REDIS_HOST ?? 'localhost',
341
353
  port: process.env.APP_ENV_REDIS_PORT ?? '6379',
342
- password: process.env.APP_ENV_REDIS_PASSWORD,
354
+ password: process.env.APP_ENV_REDIS_PASSWORD ?? '',
343
355
  });
344
356
 
345
357
  const distributedRateLimiter = async (opts: { key: string; max: number; windowSeconds: number }) => {
@@ -462,6 +474,18 @@ export class AuthService extends BaseService {
462
474
  }
463
475
  ```
464
476
 
477
+ ### Error Responses Are Hardened in Production
478
+
479
+ The global error handler decides what a client sees by environment, and it is **fail-closed**: an unset or unrecognized `NODE_ENV` is treated as production. Only `NODE_ENV` values in the development set relax it.
480
+
481
+ | In production | Behavior |
482
+ |---|---|
483
+ | Unexpected errors | Replaced with a generic `"Internal Server Error"` - raw text may carry SQL, schema names or connection details |
484
+ | Database constraint errors (400) | Base message only; the driver's `Detail:` (which echoes row values like emails), `Table:` and `Constraint:` are stripped |
485
+ | `details.stack` / `details.cause` | Omitted |
486
+
487
+ Deliberate `getError` messages are always returned verbatim, in every environment - so never put internal detail in one. Use `requestId` plus the server log to diagnose what the response no longer shows. See [Error Handling](./error-handling#_5-error-response-format).
488
+
465
489
  **Events to Log:**
466
490
  - Failed login attempts
467
491
  - Successful logins
@@ -471,7 +495,7 @@ export class AuthService extends BaseService {
471
495
  - Admin actions
472
496
 
473
497
  > [!NOTE]
474
- > When logging a request or connection config that might carry credentials, wrap it in `redactSecrets()` (or `redactUrlCredentials()` for a URL) rather than logging it raw -- see [Redaction at Log Time](#redaction-at-log-time) above. This is what the framework's own outbound HTTP and MQTT logging already does automatically.
498
+ > When logging a request or connection config that might carry credentials, wrap it in `redactSecrets()` (or `redactUrlCredentials()` for a URL) rather than logging it raw - see [Redaction at Log Time](#redaction-at-log-time) above. This is what the framework's own outbound HTTP and MQTT logging already does automatically.
475
499
 
476
500
  ## Security Checklist
477
501
 
@@ -489,6 +513,8 @@ Before deploying to production, verify:
489
513
  | **Dependencies** | No known vulnerabilities (`bun audit`) |
490
514
  | **HTTPS** | TLS configured for production |
491
515
  | **Hidden Data** | Sensitive fields use `hiddenProperties` |
516
+ | **Redaction** | `APP_ENV_LOGGER_DO_REDACT` is unset (never `false`) |
517
+ | **Error Leakage** | `NODE_ENV` set to a production value so responses are sanitized |
492
518
 
493
519
  ## See Also
494
520
 
@@ -102,8 +102,8 @@ bun test
102
102
  # Run specific test file
103
103
  bun test src/__tests__/user.service.test.ts
104
104
 
105
- # Run tests matching pattern
106
- bun test --grep "UserService"
105
+ # Run tests whose name matches a pattern
106
+ bun test -t "UserService"
107
107
 
108
108
  # Watch mode
109
109
  bun test --watch
@@ -410,6 +410,11 @@ describe('UserController E2E', () => {
410
410
  });
411
411
 
412
412
  expect(response.status).toBe(409);
413
+
414
+ // Error responses carry one message shape: { text, code, args }.
415
+ // There is no flat top-level messageCode - branch on normalized.code.
416
+ const body = await response.json();
417
+ expect(body.normalized.code).toBeDefined();
413
418
  });
414
419
  });
415
420
 
@@ -50,11 +50,9 @@ This prints all registered routes on startup.
50
50
 
51
51
  **Debug bindings:**
52
52
  ```typescript
53
- // In postConfigure() method
54
- async postConfigure(): Promise<void> {
55
- this.logger.info('Available bindings: %s',
56
- Array.from(this.bindings.keys())
57
- );
53
+ // In your Application class - `bindings` is protected on the container it extends
54
+ override async postConfigure(): Promise<void> {
55
+ this.logger.info('[postConfigure] Available bindings: %j', Array.from(this.bindings.keys()));
58
56
  }
59
57
  ```
60
58
 
@@ -77,16 +75,21 @@ curl -H "Authorization: Bearer YOUR_TOKEN" \
77
75
 
78
76
  **Enable detailed logging:**
79
77
  ```bash
80
- # Enable debug mode via environment variable
78
+ # `debug` is the only gated level - it is dropped unless DEBUG is set
81
79
  DEBUG=true
80
+
81
+ # File logging is OPT-IN. Without this, logs go to console/dgram only
82
+ APP_ENV_LOGGER_FOLDER_PATH=./logs
82
83
  ```
83
84
 
84
85
  **Use method-scoped logging with `.for()`:**
85
86
  ```typescript
87
+ import { ApplicationLogger, type ILogger } from '@venizia/ignis-helpers';
88
+
86
89
  class UserService {
87
- private logger = Logger.get('UserService');
90
+ private logger: ILogger = ApplicationLogger.get('UserService');
88
91
 
89
- async createUser(data: CreateUserDto) {
92
+ async createUser(data: TCreateUserRequest) {
90
93
  this.logger.for('createUser').info('Creating user: %j', data);
91
94
  // Output: [UserService-createUser] Creating user: {...}
92
95
 
@@ -102,16 +105,19 @@ class UserService {
102
105
  }
103
106
  ```
104
107
 
108
+ Annotate against `ILogger`, never a concrete provider class. Acquire a logger via `BaseHelper.logger` (inside any helper, service, controller or repository), `ApplicationLogger.get('Scope')`, or `LoggerFactory.getLogger(['A', 'B'])`.
109
+
105
110
  **Common debugging commands:**
106
111
  ```bash
107
- # View application logs
108
- tail -f logs/app.log
112
+ # View application logs - the rotating files are <APP_ENV_APPLICATION_NAME>-info-<date>.log
113
+ # and -error-<date>.log inside APP_ENV_LOGGER_FOLDER_PATH
114
+ tail -f "$APP_ENV_LOGGER_FOLDER_PATH"/*-info-*.log
109
115
 
110
- # Check TypeScript compilation errors
111
- bun run build
116
+ # Check TypeScript compilation errors (from the repo root)
117
+ make core
112
118
 
113
119
  # Validate environment variables
114
- cat .env | grep APP_ENV
120
+ grep APP_ENV .env
115
121
  ```
116
122
 
117
123
  **Useful debugging patterns:**
@@ -144,10 +150,10 @@ async getUser(c: Context) {
144
150
  **Filtering logs by request:**
145
151
  ```bash
146
152
  # Find all logs for a specific request
147
- grep "abc123" logs/app.log
153
+ grep "abc123" "$APP_ENV_LOGGER_FOLDER_PATH"/*-info-*.log
148
154
 
149
155
  # Extract request timing
150
- grep "\[abc123\]" logs/app.log | grep "Took:"
156
+ grep "\[abc123\]" "$APP_ENV_LOGGER_FOLDER_PATH"/*-info-*.log | grep "Took:"
151
157
  ```
152
158
 
153
159
  **Why this matters:**
@@ -159,12 +165,16 @@ grep "\[abc123\]" logs/app.log | grep "Took:"
159
165
 
160
166
  When Zod validation fails, IGNIS returns a structured error response. Understanding this format helps debug client-side issues.
161
167
 
162
- **Error response structure** (top-level `message`/`messageCode` come from the first issue; the fallback message is `ValidationError`):
168
+ **Error response structure** (`message`/`normalized.code` come from the first issue; the fallback message is `ValidationError`):
163
169
  ```json
164
170
  {
165
171
  "statusCode": 422,
166
172
  "message": "Invalid email address",
167
- "messageCode": "invalid_format",
173
+ "normalized": {
174
+ "text": "Invalid email address",
175
+ "code": "invalid_format",
176
+ "args": {}
177
+ },
168
178
  "requestId": "abc123",
169
179
  "details": {
170
180
  "url": "http://localhost:3000/api/users",