@venizia/ignis-docs 0.0.8-3 → 0.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 (213) hide show
  1. package/README.md +7 -7
  2. package/{wiki → content}/best-practices/api-usage-examples.md +15 -12
  3. package/{wiki → content}/best-practices/architectural-patterns.md +70 -78
  4. package/{wiki → content}/best-practices/architecture-decisions.md +91 -60
  5. package/{wiki → content}/best-practices/code-style-standards/advanced-patterns.md +56 -44
  6. package/{wiki → content}/best-practices/code-style-standards/constants-configuration.md +11 -11
  7. package/{wiki → content}/best-practices/code-style-standards/control-flow.md +5 -2
  8. package/{wiki → content}/best-practices/code-style-standards/documentation.md +13 -13
  9. package/{wiki → content}/best-practices/code-style-standards/function-patterns.md +9 -10
  10. package/{wiki → content}/best-practices/code-style-standards/index.md +1 -1
  11. package/{wiki → content}/best-practices/code-style-standards/naming-conventions.md +10 -8
  12. package/{wiki → content}/best-practices/code-style-standards/route-definitions.md +30 -12
  13. package/{wiki → content}/best-practices/code-style-standards/tooling.md +8 -5
  14. package/{wiki → content}/best-practices/code-style-standards/type-safety.md +13 -12
  15. package/{wiki → content}/best-practices/common-pitfalls.md +56 -37
  16. package/{wiki → content}/best-practices/contribution-workflow.md +13 -14
  17. package/{wiki → content}/best-practices/data-modeling.md +44 -20
  18. package/{wiki → content}/best-practices/deployment-strategies.md +28 -27
  19. package/{wiki → content}/best-practices/error-handling.md +48 -24
  20. package/{wiki → content}/best-practices/index.md +5 -5
  21. package/{wiki → content}/best-practices/performance-optimization.md +36 -28
  22. package/{wiki → content}/best-practices/security-guidelines.md +52 -23
  23. package/{wiki → content}/best-practices/testing-strategies.md +65 -51
  24. package/{wiki → content}/best-practices/troubleshooting-tips.md +24 -24
  25. package/{wiki/extensions/components/swagger.md → content/extensions/components/api-reference.md} +40 -31
  26. package/{wiki → content}/extensions/components/authentication/api.md +19 -19
  27. package/{wiki → content}/extensions/components/authentication/errors.md +7 -7
  28. package/{wiki → content}/extensions/components/authentication/index.md +10 -8
  29. package/{wiki → content}/extensions/components/authentication/usage.md +101 -6
  30. package/{wiki → content}/extensions/components/authorization/api.md +45 -25
  31. package/{wiki → content}/extensions/components/authorization/errors.md +6 -6
  32. package/{wiki → content}/extensions/components/authorization/index.md +11 -10
  33. package/{wiki → content}/extensions/components/authorization/usage.md +21 -21
  34. package/{wiki → content}/extensions/components/health-check.md +1 -1
  35. package/{wiki → content}/extensions/components/index.md +5 -5
  36. package/{wiki → content}/extensions/components/mail/errors.md +15 -15
  37. package/{wiki → content}/extensions/components/mail/index.md +1 -2
  38. package/{wiki → content}/extensions/components/mail/usage.md +1 -1
  39. package/{wiki → content}/extensions/components/request-tracker.md +1 -1
  40. package/{wiki → content}/extensions/components/socket-io/api.md +9 -9
  41. package/{wiki → content}/extensions/components/socket-io/errors.md +5 -5
  42. package/{wiki → content}/extensions/components/socket-io/index.md +8 -8
  43. package/{wiki → content}/extensions/components/socket-io/usage.md +1 -1
  44. package/{wiki → content}/extensions/components/static-asset/api.md +17 -4
  45. package/{wiki → content}/extensions/components/static-asset/errors.md +4 -4
  46. package/{wiki → content}/extensions/components/static-asset/index.md +26 -28
  47. package/{wiki → content}/extensions/components/static-asset/usage.md +13 -12
  48. package/{wiki → content}/extensions/components/template/index.md +2 -2
  49. package/{wiki → content}/extensions/components/template/setup-page.md +1 -1
  50. package/{wiki → content}/extensions/components/websocket/api.md +3 -3
  51. package/{wiki → content}/extensions/components/websocket/errors.md +5 -5
  52. package/{wiki → content}/extensions/components/websocket/index.md +5 -5
  53. package/{wiki → content}/extensions/components/websocket/usage.md +3 -3
  54. package/{wiki → content}/extensions/helpers/cron/index.md +2 -2
  55. package/{wiki → content}/extensions/helpers/crypto/index.md +1 -1
  56. package/{wiki → content}/extensions/helpers/env/index.md +27 -12
  57. package/content/extensions/helpers/error/index.md +283 -0
  58. package/{wiki → content}/extensions/helpers/index.md +2 -3
  59. package/{wiki → content}/extensions/helpers/inversion/index.md +15 -7
  60. package/{wiki → content}/extensions/helpers/kafka/examples.md +1 -1
  61. package/{wiki → content}/extensions/helpers/logger/index.md +32 -2
  62. package/{wiki → content}/extensions/helpers/network/index.md +6 -0
  63. package/{wiki → content}/extensions/helpers/queue/index.md +14 -17
  64. package/content/extensions/helpers/redis/index.md +713 -0
  65. package/{wiki → content}/extensions/helpers/socket-io/index.md +14 -10
  66. package/{wiki → content}/extensions/helpers/storage/api.md +44 -8
  67. package/{wiki → content}/extensions/helpers/storage/index.md +43 -7
  68. package/{wiki → content}/extensions/helpers/template/index.md +6 -3
  69. package/{wiki → content}/extensions/helpers/types/index.md +11 -8
  70. package/{wiki → content}/extensions/helpers/websocket/api.md +9 -9
  71. package/{wiki → content}/extensions/helpers/websocket/index.md +7 -7
  72. package/{wiki → content}/extensions/helpers/worker-thread/index.md +2 -2
  73. package/{wiki → content}/extensions/index.md +3 -4
  74. package/{wiki → content}/extensions/src-details/mcp-server.md +18 -24
  75. package/{wiki → content}/guides/core-concepts/application/bootstrapping.md +11 -14
  76. package/{wiki → content}/guides/core-concepts/application/index.md +3 -3
  77. package/{wiki → content}/guides/core-concepts/components.md +19 -10
  78. package/{wiki → content}/guides/core-concepts/dependency-injection.md +6 -3
  79. package/{wiki → content}/guides/core-concepts/grpc-controllers.md +6 -5
  80. package/{wiki → content}/guides/core-concepts/persistent/datasources.md +33 -27
  81. package/{wiki → content}/guides/core-concepts/persistent/index.md +16 -5
  82. package/{wiki → content}/guides/core-concepts/persistent/models.md +24 -20
  83. package/content/guides/core-concepts/persistent/postgres-drivers.md +167 -0
  84. package/{wiki → content}/guides/core-concepts/persistent/repositories.md +40 -23
  85. package/content/guides/core-concepts/persistent/search-meilisearch.md +183 -0
  86. package/content/guides/core-concepts/persistent/search-typesense.md +429 -0
  87. package/{wiki → content}/guides/core-concepts/persistent/transactions.md +61 -25
  88. package/{wiki → content}/guides/core-concepts/rest-controllers.md +12 -9
  89. package/content/guides/core-concepts/services.md +389 -0
  90. package/{wiki → content}/guides/get-started/5-minute-quickstart.md +19 -19
  91. package/{wiki → content}/guides/get-started/philosophy.md +36 -36
  92. package/{wiki → content}/guides/get-started/setup.md +3 -3
  93. package/{wiki → content}/guides/index.md +3 -3
  94. package/content/guides/migrations/redis-helpers-migration.md +177 -0
  95. package/{wiki → content}/guides/migrations/scoped-rbac-migration.md +17 -17
  96. package/content/guides/migrations/unified-connectors-migration.md +113 -0
  97. package/{wiki → content}/guides/reference/glossary.md +19 -12
  98. package/{wiki → content}/guides/reference/mcp-docs-server.md +22 -18
  99. package/{wiki → content}/guides/tutorials/building-a-crud-api.md +30 -33
  100. package/{wiki → content}/guides/tutorials/complete-installation.md +17 -17
  101. package/{wiki → content}/guides/tutorials/ecommerce-api.md +158 -119
  102. package/{wiki → content}/guides/tutorials/realtime-chat.md +176 -130
  103. package/content/guides/tutorials/testing.md +264 -0
  104. package/content/index.md +5 -0
  105. package/content/public/apple-touch-icon.png +0 -0
  106. package/content/public/og-image.png +0 -0
  107. package/content/public/site.webmanifest +11 -0
  108. package/{wiki → content}/references/base/application.md +4 -5
  109. package/{wiki → content}/references/base/bootstrapping.md +18 -5
  110. package/{wiki → content}/references/base/components.md +149 -120
  111. package/content/references/base/connectors.md +178 -0
  112. package/{wiki → content}/references/base/controllers.md +41 -30
  113. package/content/references/base/datasources.md +527 -0
  114. package/{wiki → content}/references/base/dependency-injection.md +34 -22
  115. package/{wiki → content}/references/base/filter-system/application-usage.md +17 -14
  116. package/{wiki → content}/references/base/filter-system/array-operators.md +7 -2
  117. package/{wiki → content}/references/base/filter-system/comparison-operators.md +3 -0
  118. package/{wiki → content}/references/base/filter-system/default-filter.md +89 -71
  119. package/{wiki → content}/references/base/filter-system/fields-order-pagination.md +22 -22
  120. package/{wiki → content}/references/base/filter-system/index.md +6 -3
  121. package/{wiki → content}/references/base/filter-system/json-filtering.md +20 -1
  122. package/{wiki → content}/references/base/filter-system/list-operators.md +1 -1
  123. package/{wiki → content}/references/base/filter-system/logical-operators.md +33 -1
  124. package/{wiki → content}/references/base/filter-system/null-operators.md +30 -1
  125. package/{wiki → content}/references/base/filter-system/quick-reference.md +23 -4
  126. package/{wiki → content}/references/base/filter-system/tips.md +5 -5
  127. package/{wiki → content}/references/base/filter-system/use-cases.md +12 -12
  128. package/{wiki → content}/references/base/grpc-controllers.md +13 -13
  129. package/{wiki → content}/references/base/index.md +24 -12
  130. package/{wiki/references/base/middleware.md → content/references/base/middlewares.md} +205 -24
  131. package/{wiki → content}/references/base/models.md +63 -49
  132. package/{wiki → content}/references/base/providers.md +136 -130
  133. package/{wiki → content}/references/base/repositories/advanced.md +59 -58
  134. package/{wiki → content}/references/base/repositories/index.md +115 -91
  135. package/content/references/base/repositories/mixins.md +99 -0
  136. package/{wiki → content}/references/base/repositories/relations.md +54 -64
  137. package/{wiki → content}/references/base/repositories/soft-deletable.md +31 -30
  138. package/content/references/base/services.md +404 -0
  139. package/{wiki → content}/references/configuration/environment-variables.md +46 -30
  140. package/{wiki → content}/references/configuration/index.md +6 -6
  141. package/{wiki → content}/references/index.md +17 -12
  142. package/{wiki → content}/references/quick-reference.md +65 -106
  143. package/content/references/utilities/crypto.md +98 -0
  144. package/{wiki → content}/references/utilities/index.md +3 -3
  145. package/{wiki → content}/references/utilities/jsx.md +6 -4
  146. package/content/references/utilities/module.md +90 -0
  147. package/{wiki → content}/references/utilities/parse.md +4 -14
  148. package/{wiki → content}/references/utilities/promise.md +9 -7
  149. package/{wiki → content}/references/utilities/schema.md +5 -3
  150. package/dist/mcp-server/common/guards.d.ts +8 -0
  151. package/dist/mcp-server/common/guards.d.ts.map +1 -0
  152. package/dist/mcp-server/common/guards.js +14 -0
  153. package/dist/mcp-server/common/guards.js.map +1 -0
  154. package/dist/mcp-server/common/index.d.ts +1 -0
  155. package/dist/mcp-server/common/index.d.ts.map +1 -1
  156. package/dist/mcp-server/common/index.js +1 -0
  157. package/dist/mcp-server/common/index.js.map +1 -1
  158. package/dist/mcp-server/common/paths.d.ts.map +1 -1
  159. package/dist/mcp-server/common/paths.js +2 -2
  160. package/dist/mcp-server/common/paths.js.map +1 -1
  161. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  162. package/dist/mcp-server/helpers/docs.helper.js +4 -2
  163. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  164. package/dist/mcp-server/helpers/github.helper.js +1 -1
  165. package/dist/mcp-server/index.js +7 -2
  166. package/dist/mcp-server/index.js.map +1 -1
  167. package/dist/mcp-server/tools/base.tool.d.ts +6 -2
  168. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  169. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  170. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
  171. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  172. package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
  173. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  174. package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
  175. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  176. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  177. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
  178. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  179. package/package.json +12 -12
  180. package/wiki/extensions/helpers/error/index.md +0 -227
  181. package/wiki/extensions/helpers/redis/index.md +0 -488
  182. package/wiki/extensions/helpers/testing/index.md +0 -510
  183. package/wiki/guides/core-concepts/services.md +0 -119
  184. package/wiki/guides/tutorials/testing.md +0 -722
  185. package/wiki/index.md +0 -183
  186. package/wiki/references/base/datasources.md +0 -454
  187. package/wiki/references/base/middlewares.md +0 -590
  188. package/wiki/references/base/repositories/mixins.md +0 -335
  189. package/wiki/references/base/services.md +0 -201
  190. package/wiki/references/utilities/crypto.md +0 -56
  191. package/wiki/references/utilities/module.md +0 -42
  192. /package/{wiki → content}/extensions/components/mail/api.md +0 -0
  193. /package/{wiki → content}/extensions/components/template/api-page.md +0 -0
  194. /package/{wiki → content}/extensions/components/template/errors-page.md +0 -0
  195. /package/{wiki → content}/extensions/components/template/single-page.md +0 -0
  196. /package/{wiki → content}/extensions/components/template/usage-page.md +0 -0
  197. /package/{wiki → content}/extensions/helpers/kafka/admin.md +0 -0
  198. /package/{wiki → content}/extensions/helpers/kafka/consumer.md +0 -0
  199. /package/{wiki → content}/extensions/helpers/kafka/index.md +0 -0
  200. /package/{wiki → content}/extensions/helpers/kafka/producer.md +0 -0
  201. /package/{wiki → content}/extensions/helpers/kafka/schema-registry.md +0 -0
  202. /package/{wiki → content}/extensions/helpers/network/api.md +0 -0
  203. /package/{wiki → content}/extensions/helpers/socket-io/api.md +0 -0
  204. /package/{wiki → content}/extensions/helpers/template/single-page.md +0 -0
  205. /package/{wiki → content}/extensions/helpers/uid/index.md +0 -0
  206. /package/{wiki → content}/guides/core-concepts/components-guide.md +0 -0
  207. /package/{wiki → content}/public/logo.svg +0 -0
  208. /package/{wiki → content}/references/base/filter-system/pattern-matching.md +0 -0
  209. /package/{wiki → content}/references/base/filter-system/range-operators.md +0 -0
  210. /package/{wiki → content}/references/utilities/date.md +0 -0
  211. /package/{wiki → content}/references/utilities/performance.md +0 -0
  212. /package/{wiki → content}/references/utilities/request.md +0 -0
  213. /package/{wiki → content}/references/utilities/statuses.md +0 -0
@@ -1,488 +0,0 @@
1
- # Redis
2
-
3
- Powerful Redis abstraction supporting single instances and clusters via `ioredis`, with automatic JSON serialization, connection lifecycle callbacks, Pub/Sub with optional zlib compression, RedisJSON operations, and raw command execution.
4
-
5
- ## Quick Reference
6
-
7
- | Class | Extends | Use Case |
8
- |-------|---------|----------|
9
- | **`DefaultRedisHelper`** | `BaseHelper` | Base class with unified API for all Redis operations |
10
- | **`RedisHelper`** | `DefaultRedisHelper` | Single Redis instance with auto-connect and retry strategy |
11
- | **`RedisClusterHelper`** | `DefaultRedisHelper` | Redis cluster with multi-node support |
12
-
13
- #### Import Paths
14
-
15
- ```typescript
16
- // From the helpers package
17
- import {
18
- DefaultRedisHelper,
19
- RedisHelper,
20
- RedisClusterHelper,
21
- } from '@venizia/ignis-helpers';
22
-
23
- // Types are also available from the core package (via type-only re-export)
24
- import type {
25
- IRedisHelperOptions,
26
- IRedisClusterHelperOptions,
27
- IRedisHelperCallbacks,
28
- IRedisHelperProps,
29
- IRedisClusterHelperProps,
30
- } from '@venizia/ignis-helpers'; // or from '@venizia/ignis'
31
- ```
32
-
33
- ## Creating an Instance
34
-
35
- ### Single Instance
36
-
37
- Use `RedisHelper` for connecting to a single Redis server.
38
-
39
- ```typescript
40
- import { RedisHelper } from '@venizia/ignis-helpers';
41
-
42
- const redis = new RedisHelper({
43
- name: 'my-redis',
44
- host: 'localhost',
45
- port: 6379,
46
- password: 'secret',
47
- database: 0,
48
- autoConnect: true,
49
- maxRetry: 5,
50
-
51
- onInitialized: ({ name, helper }) => {
52
- console.log(`Redis "${name}" initialized`);
53
- },
54
- onConnected: ({ name }) => {
55
- console.log(`Redis "${name}" connected`);
56
- },
57
- onReady: ({ name }) => {
58
- console.log(`Redis "${name}" ready`);
59
- },
60
- onError: ({ name, error }) => {
61
- console.error(`Redis "${name}" error:`, error);
62
- },
63
- });
64
- ```
65
-
66
- #### `IRedisHelperOptions`
67
-
68
- | Option | Type | Required | Default | Description |
69
- |--------|------|----------|---------|-------------|
70
- | `name` | `string` | Yes | -- | Unique identifier for this client instance |
71
- | `host` | `string` | Yes | -- | Redis server hostname |
72
- | `port` | `string \| number` | Yes | -- | Redis server port |
73
- | `password` | `string` | Yes | -- | Redis password |
74
- | `user` | `string` | No | -- | Redis username (ACL authentication) |
75
- | `database` | `number` | No | `0` | Redis database index |
76
- | `autoConnect` | `boolean` | No | `true` | Connect immediately on creation. When `false`, uses ioredis `lazyConnect` mode |
77
- | `maxRetry` | `number` | No | `0` | Maximum reconnection attempts. `0` = unlimited retries. Values below `0` disable retry entirely |
78
- | `onInitialized` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called synchronously immediately after client construction |
79
- | `onConnected` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called when the TCP connection is established |
80
- | `onReady` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called when the client is ready to accept commands |
81
- | `onError` | `(opts: { name: string; helper: DefaultRedisHelper; error: any }) => void` | No | -- | Called on connection or command errors |
82
-
83
- **Retry strategy:** Exponential backoff clamped between 1s and 5s: `Math.max(Math.min(attempt * 2000, 5000), 1000)`. The ioredis option `maxRetriesPerRequest` is set to `null` internally, which is required for compatibility with BullMQ.
84
-
85
- **ioredis configuration:** `RedisHelper` creates an ioredis `Redis` instance with `showFriendlyErrorStack: true` for better error diagnostics.
86
-
87
- ### Cluster
88
-
89
- Use `RedisClusterHelper` for connecting to a Redis cluster.
90
-
91
- ```typescript
92
- import { RedisClusterHelper } from '@venizia/ignis-helpers';
93
-
94
- const cluster = new RedisClusterHelper({
95
- name: 'my-cluster',
96
- nodes: [
97
- { host: 'redis-node-1', port: 7000 },
98
- { host: 'redis-node-2', port: 7001, password: 'node-specific-pass' },
99
- { host: 'redis-node-3', port: 7002 },
100
- ],
101
- clusterOptions: {
102
- redisOptions: { password: 'cluster-password' },
103
- },
104
-
105
- onReady: ({ name }) => {
106
- console.log(`Cluster "${name}" ready`);
107
- },
108
- });
109
- ```
110
-
111
- #### `IRedisClusterHelperOptions`
112
-
113
- | Option | Type | Required | Default | Description |
114
- |--------|------|----------|---------|-------------|
115
- | `name` | `string` | Yes | -- | Unique identifier for this cluster client |
116
- | `nodes` | `Array<{ host: string; port: string \| number; password?: string }>` | Yes | -- | List of cluster node addresses |
117
- | `clusterOptions` | `ClusterOptions` | No | -- | ioredis `ClusterOptions` passed directly to the `Cluster` constructor |
118
- | `onInitialized` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called synchronously immediately after cluster client construction |
119
- | `onConnected` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called when connected |
120
- | `onReady` | `(opts: { name: string; helper: DefaultRedisHelper }) => void` | No | -- | Called when ready |
121
- | `onError` | `(opts: { name: string; helper: DefaultRedisHelper; error: any }) => void` | No | -- | Called on errors |
122
-
123
- ### Lifecycle Callbacks
124
-
125
- All Redis helpers accept the same lifecycle callbacks via `IRedisHelperCallbacks`:
126
-
127
- ```typescript
128
- interface IRedisHelperCallbacks {
129
- onInitialized?: (opts: { name: string; helper: DefaultRedisHelper }) => void;
130
- onConnected?: (opts: { name: string; helper: DefaultRedisHelper }) => void;
131
- onReady?: (opts: { name: string; helper: DefaultRedisHelper }) => void;
132
- onError?: (opts: { name: string; helper: DefaultRedisHelper; error: any }) => void;
133
- }
134
- ```
135
-
136
- | Callback | Redis Event | When |
137
- |----------|-------------|------|
138
- | `onInitialized` | -- | Immediately after client construction (synchronous) |
139
- | `onConnected` | `connect` | TCP connection established |
140
- | `onReady` | `ready` | Client ready to accept commands |
141
- | `onError` | `error` | Connection or command error |
142
-
143
- Additionally, the client internally logs a warning on `reconnecting` events.
144
-
145
- ## Usage
146
-
147
- All operations below are available on both `RedisHelper` and `RedisClusterHelper` via the shared `DefaultRedisHelper` base class.
148
-
149
- ### Connection Management
150
-
151
- ```typescript
152
- // Manual connect (when autoConnect is false)
153
- const connected = await redis.connect();
154
- // => true if status becomes 'ready', false if already connected/connecting
155
-
156
- // Disconnect gracefully (sends QUIT command)
157
- const disconnected = await redis.disconnect();
158
- // => true if quit succeeded
159
-
160
- // Health check
161
- const pong = await redis.ping();
162
- // => 'PONG'
163
-
164
- // Access underlying ioredis client
165
- const ioredisClient = redis.getClient();
166
- // RedisHelper returns Redis, RedisClusterHelper returns Cluster
167
- ```
168
-
169
- > [!NOTE]
170
- > `connect()` resolves to `false` without action if the client status is already `ready`, `reconnecting`, or `connecting`. Similarly, `disconnect()` resolves to `false` if the status is `end` or `close`.
171
-
172
- ### Key-Value Operations
173
-
174
- ```typescript
175
- // Set a value (auto-serialized to JSON)
176
- await redis.set({ key: 'user:1', value: { name: 'Alice', age: 30 } });
177
-
178
- // Set with logging enabled
179
- await redis.set({ key: 'user:1', value: { name: 'Alice' }, options: { log: true } });
180
-
181
- // Get raw string value
182
- const raw = await redis.get({ key: 'user:1' });
183
- // => '{"name":"Alice","age":30}'
184
-
185
- // Get with custom transform
186
- const parsed = await redis.get({
187
- key: 'user:1',
188
- transform: (input) => JSON.parse(input),
189
- });
190
-
191
- // Convenience: get as string (alias for get)
192
- const str = await redis.getString({ key: 'user:1' });
193
-
194
- // Convenience: get as parsed JSON object
195
- const user = await redis.getObject({ key: 'user:1' });
196
- // => { name: 'Alice', age: 30 }
197
-
198
- // Delete keys
199
- await redis.del({ keys: ['user:1', 'user:2'] });
200
- ```
201
-
202
- ### Multi-Key Operations
203
-
204
- ```typescript
205
- // Set multiple keys at once
206
- await redis.mset({
207
- payload: [
208
- { key: 'user:1', value: { name: 'Alice' } },
209
- { key: 'user:2', value: { name: 'Bob' } },
210
- ],
211
- });
212
-
213
- // Get multiple raw values
214
- const values = await redis.mget({ keys: ['user:1', 'user:2'] });
215
- // => ['{"name":"Alice"}', '{"name":"Bob"}']
216
-
217
- // Get multiple with transform
218
- const users = await redis.mget({
219
- keys: ['user:1', 'user:2'],
220
- transform: (el) => JSON.parse(el),
221
- });
222
-
223
- // Convenience: get multiple strings
224
- const strings = await redis.getStrings({ keys: ['key1', 'key2'] });
225
-
226
- // Convenience: get multiple parsed objects
227
- const objects = await redis.getObjects({ keys: ['user:1', 'user:2'] });
228
- ```
229
-
230
- > [!TIP]
231
- > `mSet()`, `mGet()`, `hSet()`, and `hGetAll()` are camelCase aliases for `mset()`, `mget()`, `hset()`, and `hgetall()` respectively. Both forms are valid.
232
-
233
- ### Hash Operations
234
-
235
- ```typescript
236
- // Set hash fields
237
- await redis.hset({
238
- key: 'session:abc',
239
- value: { userId: 'u1', token: 'tok123', createdAt: '2025-01-01' },
240
- });
241
-
242
- // Set hash fields with logging
243
- await redis.hset({
244
- key: 'session:abc',
245
- value: { userId: 'u1' },
246
- options: { log: true },
247
- });
248
-
249
- // Get all hash fields
250
- const session = await redis.hgetall({ key: 'session:abc' });
251
- // => { userId: 'u1', token: 'tok123', createdAt: '2025-01-01' }
252
-
253
- // Get all hash fields with transform
254
- const transformed = await redis.hgetall({
255
- key: 'session:abc',
256
- transform: (input) => ({ ...input, extra: true }),
257
- });
258
- ```
259
-
260
- ### Key Scanning
261
-
262
- ```typescript
263
- // Find keys matching a pattern
264
- const matchingKeys = await redis.keys({ key: 'user:*' });
265
- // => ['user:1', 'user:2', ...]
266
- ```
267
-
268
- > [!WARNING]
269
- > `keys()` uses the Redis `KEYS` command, which scans the entire keyspace. Avoid using it in production on large databases -- prefer `SCAN` via `execute()` instead.
270
-
271
- ### RedisJSON Operations
272
-
273
- If your Redis server has the [RedisJSON](https://redis.io/docs/stack/json/) module installed, you can use the `j*` methods for native JSON document operations.
274
-
275
- ```typescript
276
- // Set a JSON document
277
- await redis.jSet({ key: 'doc:1', path: '$', value: { name: 'Alice', scores: [10, 20] } });
278
-
279
- // Get entire document (path defaults to '$')
280
- const doc = await redis.jGet({ key: 'doc:1' });
281
-
282
- // Get a nested path
283
- const scores = await redis.jGet({ key: 'doc:1', path: '$.scores' });
284
-
285
- // Delete a JSON path
286
- await redis.jDelete({ key: 'doc:1', path: '$.scores' });
287
-
288
- // Delete entire document (path defaults to '$')
289
- await redis.jDelete({ key: 'doc:1' });
290
-
291
- // Increment a number at a path
292
- await redis.jNumberIncreaseBy({ key: 'doc:1', path: '$.counter', value: 5 });
293
-
294
- // Append to a string at a path
295
- await redis.jStringAppend({ key: 'doc:1', path: '$.name', value: ' Smith' });
296
-
297
- // Push to an array at a path
298
- await redis.jPush({ key: 'doc:1', path: '$.tags', value: 'new-tag' });
299
-
300
- // Pop from an array at a path
301
- const popped = await redis.jPop({ key: 'doc:1', path: '$.tags' });
302
- ```
303
-
304
- #### RedisJSON Method Signatures
305
-
306
- | Method | Parameters | Returns | Redis Command |
307
- |--------|-----------|---------|---------------|
308
- | `jSet<T>()` | `{ key: string; path: string; value: T }` | `Promise<string \| null>` | `JSON.SET` |
309
- | `jGet<T>()` | `{ key: string; path?: string }` | `Promise<T \| null>` | `JSON.GET` |
310
- | `jDelete()` | `{ key: string; path?: string }` | `Promise<number>` | `JSON.DEL` |
311
- | `jNumberIncreaseBy()` | `{ key: string; path: string; value: number }` | `Promise<string \| null>` | `JSON.NUMINCRBY` |
312
- | `jStringAppend()` | `{ key: string; path: string; value: string }` | `Promise<number[] \| null>` | `JSON.STRAPPEND` |
313
- | `jPush<T>()` | `{ key: string; path: string; value: T }` | `Promise<number[] \| null>` | `JSON.ARRAPPEND` |
314
- | `jPop<T>()` | `{ key: string; path: string }` | `Promise<T \| null>` | `JSON.ARRPOP` |
315
-
316
- `jGet` and `jDelete` default `path` to `'$'` (root) when omitted. All other `j*` methods require `path` explicitly.
317
-
318
- ### Pub/Sub
319
-
320
- The helper supports Redis Pub/Sub for real-time messaging with optional zlib compression.
321
-
322
- ```typescript
323
- // Subscribe to a topic
324
- redis.subscribe({ topic: 'events' });
325
-
326
- // Listen for messages on the underlying ioredis client
327
- redis.getClient().on('message', (channel, message) => {
328
- if (channel === 'events') {
329
- console.log('Received:', JSON.parse(message));
330
- }
331
- });
332
-
333
- // Publish to one or more topics
334
- await redis.publish({
335
- topics: ['events', 'audit-log'],
336
- payload: { action: 'user.created', userId: 'u1' },
337
- });
338
-
339
- // Publish with zlib compression
340
- await redis.publish({
341
- topics: ['compressed-channel'],
342
- payload: { large: 'dataset' },
343
- useCompress: true,
344
- });
345
-
346
- // Unsubscribe from a topic
347
- redis.unsubscribe({ topic: 'events' });
348
- ```
349
-
350
- > [!IMPORTANT]
351
- > When using Pub/Sub, the subscribing client enters subscriber mode and can only execute `SUBSCRIBE`, `PSUBSCRIBE`, `UNSUBSCRIBE`, `PUNSUBSCRIBE`, `PING`, and `QUIT` commands. Use a separate `RedisHelper` instance for Pub/Sub if you also need to perform regular data operations.
352
-
353
- ### Raw Command Execution
354
-
355
- For commands not wrapped by the helper, use `execute()` to call any Redis command directly.
356
-
357
- ```typescript
358
- // Execute any Redis command
359
- const result = await redis.execute<string>('SET', ['mykey', 'myvalue', 'EX', 60]);
360
-
361
- // Command without parameters
362
- const info = await redis.execute<string>('INFO');
363
-
364
- // SCAN instead of KEYS for production use
365
- const [cursor, keys] = await redis.execute<[string, string[]]>(
366
- 'SCAN', [0, 'MATCH', 'user:*', 'COUNT', 100],
367
- );
368
- ```
369
-
370
- ## API Summary
371
-
372
- | Method | Returns | Description |
373
- |--------|---------|-------------|
374
- | **Connection** | | |
375
- | `connect()` | `Promise<boolean>` | Manual connect (no-op if already connected/connecting/ready) |
376
- | `disconnect()` | `Promise<boolean>` | Graceful disconnect via `QUIT` (no-op if already ended/closed) |
377
- | `ping()` | `Promise<string>` | Health check, returns `'PONG'` |
378
- | `getClient()` | `Redis \| Cluster` | Access the underlying ioredis client |
379
- | **Key-Value** | | |
380
- | `set<T>(opts)` | `Promise<void>` | Set a key with JSON-serialized value. Options: `{ key, value, options?: { log } }` |
381
- | `get<T>(opts)` | `Promise<T \| null>` | Get raw value with optional transform. Options: `{ key, transform? }` |
382
- | `getString(opts)` | `Promise<string \| null>` | Get raw string value. Options: `{ key }` |
383
- | `getObject(opts)` | `Promise<object \| null>` | Get value parsed as JSON. Options: `{ key }` |
384
- | `del(opts)` | `Promise<number>` | Delete one or more keys. Options: `{ keys: string[] }` |
385
- | **Multi-Key** | | |
386
- | `mset<T>(opts)` / `mSet<T>(opts)` | `Promise<void>` | Set multiple key-value pairs. Options: `{ payload: Array<{ key, value }>, options?: { log } }` |
387
- | `mget<T>(opts)` / `mGet<T>(opts)` | `Promise<(T \| null)[]>` | Get multiple values with optional transform. Options: `{ keys, transform? }` |
388
- | `getStrings(opts)` | `Promise<(string \| null)[]>` | Get multiple raw string values. Options: `{ keys }` |
389
- | `getObjects(opts)` | `Promise<(object \| null)[]>` | Get multiple values parsed as JSON. Options: `{ keys }` |
390
- | **Hashes** | | |
391
- | `hset<T>(opts)` / `hSet<T>(opts)` | `Promise<number>` | Set hash fields. Options: `{ key, value: Record<string, unknown>, options?: { log } }` |
392
- | `hgetall(opts)` / `hGetAll(opts)` | `Promise<Record<string, string> \| null>` | Get all hash fields with optional transform. Options: `{ key, transform? }` |
393
- | **Key Scanning** | | |
394
- | `keys(opts)` | `Promise<string[]>` | Find keys matching a glob pattern. Options: `{ key }` |
395
- | **RedisJSON** | | |
396
- | `jSet<T>(opts)` | `Promise<string \| null>` | Set a JSON document at path (`JSON.SET`) |
397
- | `jGet<T>(opts)` | `Promise<T \| null>` | Get a JSON document or path (`JSON.GET`) |
398
- | `jDelete(opts)` | `Promise<number>` | Delete a JSON path (`JSON.DEL`) |
399
- | `jNumberIncreaseBy(opts)` | `Promise<string \| null>` | Increment a number at path (`JSON.NUMINCRBY`) |
400
- | `jStringAppend(opts)` | `Promise<number[] \| null>` | Append to a string at path (`JSON.STRAPPEND`) |
401
- | `jPush<T>(opts)` | `Promise<number[] \| null>` | Push to an array at path (`JSON.ARRAPPEND`) |
402
- | `jPop<T>(opts)` | `Promise<T \| null>` | Pop from an array at path (`JSON.ARRPOP`) |
403
- | **Pub/Sub** | | |
404
- | `subscribe(opts)` | `void` | Subscribe to a topic. Options: `{ topic }` |
405
- | `publish<T>(opts)` | `Promise<void>` | Publish to one or more topics with optional compression. Options: `{ topics, payload, useCompress? }` |
406
- | `unsubscribe(opts)` | `void` | Unsubscribe from a topic. Options: `{ topic }` |
407
- | **Raw** | | |
408
- | `execute<R>(command, parameters?)` | `Promise<R>` | Execute any Redis command directly |
409
-
410
- ## Troubleshooting
411
-
412
- ### "[execute] Invalid client to execute | command: ..."
413
-
414
- **Cause:** `execute()` was called when the ioredis client is `null` or `undefined`. This typically happens if the helper was not properly constructed or the connection was never established.
415
-
416
- **Fix:** Ensure the helper is instantiated correctly and, if using `autoConnect: false`, call `await redis.connect()` before issuing commands.
417
-
418
- ### "[subscribe] Failed to subscribe to topic: ..."
419
-
420
- **Cause:** The ioredis `subscribe()` callback received an error. This can happen if the client lost its connection or the Redis server rejected the subscription.
421
-
422
- **Fix:** Check that the Redis server is reachable and the client is in a valid state. Monitor the `onError` callback for connection issues.
423
-
424
- ### "[unsubscribe] Failed to unsubscribe from topic: ..."
425
-
426
- **Cause:** The ioredis `unsubscribe()` callback received an error, usually due to a broken connection.
427
-
428
- **Fix:** Same as above -- verify connectivity and client state.
429
-
430
- ### Connection Refused / Timeout
431
-
432
- **Symptoms:** `ECONNREFUSED`, connection hangs, or `onError` fires immediately.
433
-
434
- **Checklist:**
435
- - Verify Redis is running and reachable at the configured `host:port`
436
- - Check firewall rules and network access between your application and the Redis server
437
- - If using `autoConnect: false`, ensure you call `await redis.connect()` before any operations
438
- - Verify `password` is correct (Redis returns a generic error for auth failure)
439
- - For clusters, ensure all node addresses are reachable and the cluster is healthy (`redis-cli cluster info`)
440
-
441
- ### Pub/Sub Subscriber Mode Conflicts
442
-
443
- **Symptoms:** `ERR only (P|S)SUBSCRIBE / (P|S)UNSUBSCRIBE / PING / QUIT / RESET allowed in this context`
444
-
445
- **Cause:** You called `subscribe()` on a client and then attempted a regular command (`get`, `set`, etc.) on the same client.
446
-
447
- **Fix:** Use a separate connection for Pub/Sub:
448
-
449
- ```typescript
450
- const dataClient = new RedisHelper({ name: 'data', host, port, password });
451
- const subClient = new RedisHelper({ name: 'sub', host, port, password });
452
-
453
- // Use subClient only for subscribe/unsubscribe
454
- subClient.subscribe({ topic: 'events' });
455
- subClient.getClient().on('message', (channel, msg) => { /* ... */ });
456
-
457
- // Use dataClient for everything else
458
- await dataClient.set({ key: 'foo', value: 'bar' });
459
- ```
460
-
461
- ### RedisJSON Commands Return Errors
462
-
463
- **Symptoms:** `ERR unknown command 'JSON.SET'`
464
-
465
- **Cause:** The RedisJSON module is not installed on your Redis server.
466
-
467
- **Fix:** Install Redis Stack or the RedisJSON module. See [RedisJSON documentation](https://redis.io/docs/stack/json/).
468
-
469
- ## See Also
470
-
471
- - **Related Concepts:**
472
- - [Services](/guides/core-concepts/services) - Using Redis in services
473
-
474
- - **Other Helpers:**
475
- - [Helpers Index](../index) - All available helpers
476
- - [Queue Helper](../queue/) - BullMQ uses Redis as backend
477
-
478
- - **References:**
479
- - [DataSources](/references/base/datasources) - Database connections
480
-
481
- - **External Resources:**
482
- - [ioredis Documentation](https://github.com/redis/ioredis) - Redis client library
483
- - [Redis Commands](https://redis.io/commands/) - Redis command reference
484
- - [RedisJSON](https://redis.io/docs/stack/json/) - JSON module documentation
485
-
486
- - **Best Practices:**
487
- - [Performance Optimization](/best-practices/performance-optimization) - Caching strategies
488
- - [Security Guidelines](/best-practices/security-guidelines) - Redis security