@jgamaraalv/ts-dev-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +24 -0
  3. package/CHANGELOG.md +24 -0
  4. package/LICENSE +21 -0
  5. package/README.md +128 -0
  6. package/agents/accessibility-pro.md +139 -0
  7. package/agents/api-builder.md +110 -0
  8. package/agents/code-reviewer.md +190 -0
  9. package/agents/database-expert.md +138 -0
  10. package/agents/debugger.md +241 -0
  11. package/agents/docker-expert.md +51 -0
  12. package/agents/multi-agent-coordinator.md +378 -0
  13. package/agents/nextjs-expert.md +136 -0
  14. package/agents/performance-engineer.md +138 -0
  15. package/agents/playwright-expert.md +126 -0
  16. package/agents/react-specialist.md +97 -0
  17. package/agents/security-scanner.md +105 -0
  18. package/agents/test-generator.md +221 -0
  19. package/agents/typescript-pro.md +253 -0
  20. package/agents/ux-optimizer.md +93 -0
  21. package/docs/rules/orchestration.md.template +126 -0
  22. package/package.json +28 -0
  23. package/skills/bullmq/SKILL.md +225 -0
  24. package/skills/bullmq/references/flows-and-schedulers.md +186 -0
  25. package/skills/bullmq/references/job-types-and-options.md +163 -0
  26. package/skills/bullmq/references/patterns.md +273 -0
  27. package/skills/bullmq/references/production.md +308 -0
  28. package/skills/composition-patterns/SKILL.md +58 -0
  29. package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
  30. package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
  31. package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
  32. package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
  33. package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
  34. package/skills/composition-patterns/references/state-context-interface.md +194 -0
  35. package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
  36. package/skills/composition-patterns/references/state-lift-state.md +126 -0
  37. package/skills/conventional-commits/SKILL.md +148 -0
  38. package/skills/docker/SKILL.md +55 -0
  39. package/skills/docker/references/compose-configs.md +95 -0
  40. package/skills/docker/references/monorepo-dockerfile.md +111 -0
  41. package/skills/drizzle-pg/SKILL.md +202 -0
  42. package/skills/drizzle-pg/references/advanced.md +299 -0
  43. package/skills/drizzle-pg/references/migrations.md +214 -0
  44. package/skills/drizzle-pg/references/queries.md +321 -0
  45. package/skills/drizzle-pg/references/relations.md +272 -0
  46. package/skills/drizzle-pg/references/schema-pg.md +256 -0
  47. package/skills/drizzle-pg/references/sql-operator.md +215 -0
  48. package/skills/fastify-best-practices/SKILL.md +143 -0
  49. package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
  50. package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
  51. package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
  52. package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
  53. package/skills/fastify-best-practices/references/server-and-options.md +127 -0
  54. package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
  55. package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
  56. package/skills/ioredis/SKILL.md +51 -0
  57. package/skills/ioredis/references/advanced-patterns.md +312 -0
  58. package/skills/ioredis/references/cluster-sentinel.md +280 -0
  59. package/skills/ioredis/references/connection-options.md +187 -0
  60. package/skills/ioredis/references/core-api.md +179 -0
  61. package/skills/nextjs-best-practices/SKILL.md +194 -0
  62. package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
  63. package/skills/nextjs-best-practices/references/bundling.md +192 -0
  64. package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
  65. package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
  66. package/skills/nextjs-best-practices/references/directives.md +74 -0
  67. package/skills/nextjs-best-practices/references/error-handling.md +237 -0
  68. package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
  69. package/skills/nextjs-best-practices/references/font.md +175 -0
  70. package/skills/nextjs-best-practices/references/functions.md +116 -0
  71. package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
  72. package/skills/nextjs-best-practices/references/image.md +184 -0
  73. package/skills/nextjs-best-practices/references/metadata.md +305 -0
  74. package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
  75. package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
  76. package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
  77. package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
  78. package/skills/nextjs-best-practices/references/scripts.md +148 -0
  79. package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
  80. package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
  81. package/skills/owasp-security-review/SKILL.md +98 -0
  82. package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
  83. package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
  84. package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
  85. package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
  86. package/skills/owasp-security-review/references/a05-injection.md +106 -0
  87. package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
  88. package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
  89. package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
  90. package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
  91. package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
  92. package/skills/postgresql/SKILL.md +50 -0
  93. package/skills/postgresql/references/ddl-schema.md +300 -0
  94. package/skills/postgresql/references/indexes.md +257 -0
  95. package/skills/postgresql/references/jsonb.md +261 -0
  96. package/skills/postgresql/references/performance.md +291 -0
  97. package/skills/postgresql/references/psql-cli.md +153 -0
  98. package/skills/postgresql/references/queries.md +287 -0
  99. package/skills/postgresql/references/transactions.md +280 -0
  100. package/skills/react-best-practices/SKILL.md +110 -0
  101. package/skills/react-best-practices/references/advanced-patterns.md +91 -0
  102. package/skills/react-best-practices/references/async-patterns.md +233 -0
  103. package/skills/react-best-practices/references/bundle-optimization.md +201 -0
  104. package/skills/react-best-practices/references/client-patterns.md +178 -0
  105. package/skills/react-best-practices/references/js-performance.md +210 -0
  106. package/skills/react-best-practices/references/rendering-performance.md +209 -0
  107. package/skills/react-best-practices/references/rerender-optimization.md +316 -0
  108. package/skills/react-best-practices/references/server-performance.md +274 -0
  109. package/skills/service-worker/SKILL.md +195 -0
  110. package/skills/service-worker/references/api-reference.md +114 -0
  111. package/skills/service-worker/references/caching-strategies.md +202 -0
  112. package/skills/service-worker/references/push-and-sync.md +261 -0
  113. package/skills/typescript-conventions/SKILL.md +51 -0
  114. package/skills/ui-ux-guidelines/SKILL.md +105 -0
  115. package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
  116. package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
  117. package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
@@ -0,0 +1,127 @@
1
+ # Server Factory & Options
2
+
3
+ ## Table of Contents
4
+
5
+ - [Factory: fastify(options)](#factory-fastifyoptions)
6
+ - [Core options](#core-options)
7
+ - [Router options](#router-options)
8
+ - [Security options](#security-options)
9
+ - [Validation/serialization options](#validationserialization-options)
10
+ - [Advanced options](#advanced-options)
11
+ - [Key server methods](#key-server-methods)
12
+ - [Key properties](#key-properties)
13
+ - [Graceful shutdown pattern](#graceful-shutdown-pattern)
14
+
15
+ ## Factory: `fastify(options)`
16
+
17
+ ### Core options
18
+
19
+ | Option | Type | Default | Description |
20
+ | ----------------------- | --------------------- | --------------- | ------------------------------------------------ |
21
+ | `logger` | bool/object | `false` | Pino logger config. `true` enables with defaults |
22
+ | `loggerInstance` | object | — | Custom Pino-compatible logger instance |
23
+ | `disableRequestLogging` | bool/fn | `false` | Disable auto request/response logging |
24
+ | `trustProxy` | bool/string/number/fn | `false` | Trust X-Forwarded-\* headers |
25
+ | `bodyLimit` | number | `1048576` (1MB) | Max request body bytes |
26
+ | `maxParamLength` | number | 100 | Max URL parameter length |
27
+ | `pluginTimeout` | number | `10000` | Max ms for plugin load |
28
+ | `requestTimeout` | number | `0` | Max ms to receive full request |
29
+ | `connectionTimeout` | number | `0` | Socket timeout ms |
30
+ | `keepAliveTimeout` | number | `72000` | HTTP/1 keep-alive timeout ms |
31
+ | `requestIdHeader` | string | `'request-id'` | Header for request ID |
32
+ | `genReqId` | fn(rawReq) | auto-increment | Custom request ID generator |
33
+
34
+ ### Router options
35
+
36
+ | Option | Type | Default | Description |
37
+ | ------------------------ | ---- | ------- | ------------------------------------ |
38
+ | `caseSensitive` | bool | `true` | Case-sensitive route matching |
39
+ | `ignoreTrailingSlash` | bool | `false` | Match `/foo` and `/foo/` |
40
+ | `ignoreDuplicateSlashes` | bool | `false` | Treat `//` as `/` |
41
+ | `exposeHeadRoutes` | bool | `true` | Auto-create HEAD for GET routes |
42
+ | `return503OnClosing` | bool | `true` | 503 for new requests during shutdown |
43
+
44
+ ### Security options
45
+
46
+ | Option | Type | Default | Description |
47
+ | ------------------------ | ------ | --------- | ----------------------------------------------------------- |
48
+ | `onProtoPoisoning` | string | `'error'` | Handle `__proto__` in JSON: `'error'`/`'remove'`/`'ignore'` |
49
+ | `onConstructorPoisoning` | string | `'error'` | Handle `constructor` in JSON |
50
+
51
+ ### Validation/serialization options
52
+
53
+ | Option | Type | Default | Description |
54
+ | ---------------- | ------ | ------- | --------------------------------------- |
55
+ | `ajv` | object | — | `{ customOptions, plugins }` for Ajv v8 |
56
+ | `serializerOpts` | object | — | fast-json-stringify options |
57
+
58
+ ### Advanced options
59
+
60
+ | Option | Type | Default | Description |
61
+ | ------------------- | ------- | ------- | ----------------------------- |
62
+ | `http2` | bool | `false` | Enable HTTP/2 |
63
+ | `https` | object | — | TLS options |
64
+ | `serverFactory` | fn | — | Custom HTTP server factory |
65
+ | `rewriteUrl` | fn(req) | — | Rewrite request URL |
66
+ | `querystringParser` | fn | — | Custom query string parser |
67
+ | `frameworkErrors` | fn | — | Handle framework-level errors |
68
+
69
+ ## Key server methods
70
+
71
+ ```
72
+ .listen({ port, host }) → Start server (returns Promise)
73
+ .close() → Graceful shutdown (returns Promise)
74
+ .ready() → Wait for plugins to load (returns Promise)
75
+ .inject(request) → Fake HTTP request for testing (returns Promise)
76
+
77
+ .register(plugin, opts?) → Register plugin (creates new scope)
78
+ .addHook(name, handler) → Add lifecycle hook
79
+ .route(options) → Add route (full form)
80
+ .get/post/put/delete/patch(...) → Add route (shorthand)
81
+
82
+ .decorate(name, value) → Decorate server instance
83
+ .decorateRequest(name, value) → Decorate Request prototype
84
+ .decorateReply(name, value) → Decorate Reply prototype
85
+ .hasDecorator(name) → Check if decorator exists
86
+
87
+ .addSchema({ $id, ... }) → Add reusable JSON schema
88
+ .getSchema(id) → Retrieve schema by $id
89
+ .getSchemas() → Get all schemas (encapsulation-aware)
90
+
91
+ .setErrorHandler(fn) → Set custom error handler
92
+ .setNotFoundHandler(fn) → Set custom 404 handler
93
+ .setValidatorCompiler(fn) → Set schema validator compiler
94
+ .setSerializerCompiler(fn) → Set response serializer compiler
95
+
96
+ .addContentTypeParser(type, fn) → Register custom content-type parser
97
+ .hasContentTypeParser(type) → Check if parser exists
98
+
99
+ .printRoutes() → Print route tree (debugging)
100
+ .printPlugins() → Print plugin tree (debugging)
101
+ .addresses() → Get listening addresses [{port, family, address}]
102
+ ```
103
+
104
+ ## Key properties
105
+
106
+ ```
107
+ .server → Node.js HTTP/HTTPS server instance
108
+ .log → Pino logger instance
109
+ .prefix → Current route prefix (scoped to plugin)
110
+ .pluginName → Current plugin name (root = 'fastify')
111
+ .version → Fastify version string
112
+ .initialConfig → Frozen read-only initial options
113
+ .listeningOrigin → Current listening address string
114
+ ```
115
+
116
+ ## Graceful shutdown pattern
117
+
118
+ ```ts
119
+ const signals = ["SIGTERM", "SIGINT"];
120
+ for (const signal of signals) {
121
+ process.on(signal, async () => {
122
+ fastify.log.info(`Received ${signal}, shutting down...`);
123
+ await fastify.close();
124
+ process.exit(0);
125
+ });
126
+ }
127
+ ```
@@ -0,0 +1,223 @@
1
+ # TypeScript & Logging
2
+
3
+ ## Table of Contents
4
+
5
+ - [TypeScript Patterns](#typescript-patterns)
6
+ - [Route generics](#route-generics)
7
+ - [Type providers (Zod integration)](#type-providers-zod-integration)
8
+ - [Augmenting FastifyInstance (custom decorators)](#augmenting-fastifyinstance-custom-decorators)
9
+ - [Plugin typing](#plugin-typing)
10
+ - [Decorator typing gotchas](#decorator-typing-gotchas)
11
+ - [Import style (ESM)](#import-style-esm)
12
+ - [Logging with Pino](#logging-with-pino)
13
+ - [Basic setup](#basic-setup)
14
+ - [Development (pretty printing)](#development-pretty-printing)
15
+ - [Production recommendations](#production-recommendations)
16
+ - [Disable request logging](#disable-request-logging)
17
+ - [Request-scoped logging](#request-scoped-logging)
18
+ - [Custom request ID](#custom-request-id)
19
+
20
+ ## TypeScript Patterns
21
+
22
+ ## Route generics
23
+
24
+ Type request parts using generics:
25
+
26
+ ```ts
27
+ interface CreateUserBody {
28
+ email: string;
29
+ name: string;
30
+ }
31
+
32
+ interface UserParams {
33
+ id: string;
34
+ }
35
+
36
+ interface UserQuery {
37
+ include?: string;
38
+ }
39
+
40
+ fastify.post<{
41
+ Body: CreateUserBody;
42
+ Params: UserParams;
43
+ Querystring: UserQuery;
44
+ Headers: { "x-api-key": string };
45
+ }>("/users/:id", async (request) => {
46
+ request.body.email; // typed as string
47
+ request.params.id; // typed as string
48
+ request.query.include; // typed as string | undefined
49
+ });
50
+ ```
51
+
52
+ ## Type providers (Zod integration)
53
+
54
+ ```ts
55
+ import Fastify from "fastify";
56
+ import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "fastify-type-provider-zod";
57
+ import { z } from "zod";
58
+
59
+ const fastify = Fastify().withTypeProvider<ZodTypeProvider>();
60
+ fastify.setValidatorCompiler(validatorCompiler);
61
+ fastify.setSerializerCompiler(serializerCompiler);
62
+
63
+ fastify.post(
64
+ "/users",
65
+ {
66
+ schema: {
67
+ body: z.object({ email: z.string().email() }),
68
+ response: { 201: z.object({ id: z.string() }) },
69
+ },
70
+ },
71
+ async (request) => {
72
+ request.body.email; // inferred from Zod schema
73
+ return { id: "123" };
74
+ },
75
+ );
76
+ ```
77
+
78
+ ## Augmenting FastifyInstance (custom decorators)
79
+
80
+ ```ts
81
+ declare module "fastify" {
82
+ interface FastifyInstance {
83
+ db: Pool;
84
+ redis: Redis;
85
+ }
86
+ interface FastifyRequest {
87
+ user?: { id: string; email: string };
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Plugin typing
93
+
94
+ See [plugins-and-encapsulation.md](plugins-and-encapsulation.md) for the full `FastifyPluginCallback` and `FastifyPluginAsync` patterns.
95
+
96
+ **Quick reference for type annotations:**
97
+
98
+ ```ts
99
+ import type { FastifyPluginCallback, FastifyPluginAsync } from "fastify";
100
+ ```
101
+
102
+ ## Logging with Pino
103
+
104
+ ## Pino logging configuration
105
+
106
+ ### Basic setup
107
+
108
+ ```ts
109
+ const fastify = Fastify({
110
+ logger: true, // default Pino with info level
111
+ });
112
+
113
+ // Or with options:
114
+ const fastify = Fastify({
115
+ logger: {
116
+ level: "info",
117
+ },
118
+ });
119
+ ```
120
+
121
+ ### Development (pretty printing)
122
+
123
+ ```ts
124
+ const fastify = Fastify({
125
+ logger: {
126
+ level: "debug",
127
+ transport: {
128
+ target: "pino-pretty",
129
+ options: {
130
+ translateTime: "HH:MM:ss Z",
131
+ ignore: "pid,hostname",
132
+ },
133
+ },
134
+ },
135
+ });
136
+ ```
137
+
138
+ ### Production recommendations
139
+
140
+ ```ts
141
+ const fastify = Fastify({
142
+ logger: {
143
+ level: process.env.LOG_LEVEL ?? "info",
144
+ // Redact sensitive data
145
+ redact: ["req.headers.authorization", "req.headers.cookie"],
146
+ serializers: {
147
+ req(request) {
148
+ return {
149
+ method: request.method,
150
+ url: request.url,
151
+ hostname: request.hostname,
152
+ remoteAddress: request.ip,
153
+ };
154
+ },
155
+ },
156
+ },
157
+ });
158
+ ```
159
+
160
+ ### Disable request logging
161
+
162
+ ```ts
163
+ const fastify = Fastify({
164
+ disableRequestLogging: true, // no auto req/res logs
165
+ });
166
+
167
+ // Or conditionally:
168
+ const fastify = Fastify({
169
+ disableRequestLogging: (req) => req.url === "/health",
170
+ });
171
+ ```
172
+
173
+ ### Request-scoped logging
174
+
175
+ Every request has `request.log` — a child logger with `reqId` bound:
176
+
177
+ ```ts
178
+ fastify.get("/", async (request) => {
179
+ request.log.info("processing request"); // includes reqId
180
+ request.log.info({ userId: 123 }, "user found"); // structured data
181
+ });
182
+ ```
183
+
184
+ ### Custom request ID
185
+
186
+ ```ts
187
+ const fastify = Fastify({
188
+ requestIdHeader: "x-request-id", // read from header
189
+ genReqId: (req) => crypto.randomUUID(), // or generate
190
+ requestIdLogLabel: "reqId", // log field name
191
+ });
192
+ ```
193
+
194
+ ## Decorator typing gotchas
195
+
196
+ **Wrong — shared reference:**
197
+
198
+ ```ts
199
+ fastify.decorateRequest("data", {}); // ALL requests share same object!
200
+ ```
201
+
202
+ **Right — null initial + onRequest assignment:**
203
+
204
+ ```ts
205
+ fastify.decorateRequest("user", null);
206
+
207
+ fastify.addHook("onRequest", async (request) => {
208
+ request.user = await getUser(request); // unique per request
209
+ });
210
+ ```
211
+
212
+ ## Import style (ESM)
213
+
214
+ ```ts
215
+ // Fastify:
216
+ import Fastify from "fastify";
217
+ import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
218
+
219
+ // fastify-plugin:
220
+ import fp from "fastify-plugin";
221
+ ```
222
+
223
+ > **ioredis**: See CLAUDE.md for the canonical ioredis import convention (`import { Redis } from "ioredis"`).
@@ -0,0 +1,190 @@
1
+ # Validation & Serialization
2
+
3
+ ## Table of Contents
4
+
5
+ - [Request validation (JSON Schema + Ajv v8)](#request-validation-json-schema--ajv-v8)
6
+ - [Ajv defaults](#ajv-defaults)
7
+ - [Customizing Ajv](#customizing-ajv)
8
+ - [Response serialization (fast-json-stringify)](#response-serialization-fast-json-stringify)
9
+ - [Schema reuse with $ref](#schema-reuse-with-ref)
10
+ - [Custom validator compiler (e.g., Zod)](#custom-validator-compiler-eg-zod)
11
+ - [Error formatting](#error-formatting)
12
+ - [Gotchas](#gotchas)
13
+
14
+ ## Request validation (JSON Schema + Ajv v8)
15
+
16
+ Fastify validates request data against JSON Schema. Invalid requests get **400** automatically.
17
+
18
+ ```ts
19
+ fastify.post("/users", {
20
+ schema: {
21
+ body: {
22
+ type: "object",
23
+ required: ["email"],
24
+ properties: {
25
+ email: { type: "string", format: "email" },
26
+ name: { type: "string", minLength: 1, maxLength: 100 },
27
+ age: { type: "integer", minimum: 0 },
28
+ },
29
+ additionalProperties: false,
30
+ },
31
+ querystring: {
32
+ type: "object",
33
+ properties: {
34
+ page: { type: "integer", default: 1 },
35
+ limit: { type: "integer", default: 20, maximum: 100 },
36
+ },
37
+ },
38
+ params: {
39
+ type: "object",
40
+ properties: {
41
+ id: { type: "string", format: "uuid" },
42
+ },
43
+ },
44
+ headers: {
45
+ type: "object",
46
+ properties: {
47
+ "x-api-key": { type: "string" },
48
+ },
49
+ required: ["x-api-key"],
50
+ },
51
+ },
52
+ handler: async (request, reply) => { ... },
53
+ });
54
+ ```
55
+
56
+ ### Ajv defaults
57
+
58
+ Fastify configures Ajv with:
59
+
60
+ - `coerceTypes: true` — strings coerced to numbers/booleans for query/params
61
+ - `removeAdditional: true` — extra properties stripped
62
+ - `useDefaults: true` — missing properties get defaults
63
+ - `allErrors: false` — stops at first error (faster)
64
+
65
+ ### Customizing Ajv
66
+
67
+ ```ts
68
+ const fastify = Fastify({
69
+ ajv: {
70
+ customOptions: {
71
+ allErrors: true, // return all errors
72
+ removeAdditional: "all", // strip all extra properties
73
+ },
74
+ plugins: [ajvFormats], // add format validators
75
+ },
76
+ });
77
+ ```
78
+
79
+ ## Response serialization (fast-json-stringify)
80
+
81
+ Define response schemas per status code. Fastify uses `fast-json-stringify` for 2-5x faster serialization than `JSON.stringify`, and it **prevents leaking fields** not in the schema.
82
+
83
+ ```ts
84
+ schema: {
85
+ response: {
86
+ 200: {
87
+ type: "object",
88
+ properties: {
89
+ id: { type: "string" },
90
+ email: { type: "string" },
91
+ },
92
+ },
93
+ "4xx": {
94
+ type: "object",
95
+ properties: {
96
+ error: { type: "string" },
97
+ message: { type: "string" },
98
+ },
99
+ },
100
+ default: {
101
+ type: "object",
102
+ properties: {
103
+ error: { type: "string" },
104
+ },
105
+ },
106
+ },
107
+ }
108
+ ```
109
+
110
+ ## Schema reuse with $ref
111
+
112
+ **Register shared schemas:**
113
+
114
+ ```ts
115
+ fastify.addSchema({
116
+ $id: "user",
117
+ type: "object",
118
+ properties: {
119
+ id: { type: "string" },
120
+ email: { type: "string" },
121
+ name: { type: "string" },
122
+ },
123
+ });
124
+
125
+ fastify.addSchema({
126
+ $id: "pagination",
127
+ type: "object",
128
+ properties: {
129
+ page: { type: "integer", default: 1 },
130
+ limit: { type: "integer", default: 20 },
131
+ total: { type: "integer" },
132
+ },
133
+ });
134
+ ```
135
+
136
+ **Reference in routes:**
137
+
138
+ ```ts
139
+ schema: {
140
+ response: {
141
+ 200: { $ref: "user#" }, // whole schema
142
+ },
143
+ }
144
+
145
+ // Or reference properties:
146
+ schema: {
147
+ body: {
148
+ type: "object",
149
+ properties: {
150
+ user: { $ref: "user#" },
151
+ meta: { $ref: "pagination#" },
152
+ },
153
+ },
154
+ }
155
+ ```
156
+
157
+ ## Custom validator compiler (e.g., Zod)
158
+
159
+ ```ts
160
+ import { serializerCompiler, validatorCompiler } from "fastify-type-provider-zod";
161
+
162
+ fastify.setValidatorCompiler(validatorCompiler);
163
+ fastify.setSerializerCompiler(serializerCompiler);
164
+
165
+ // Then in routes:
166
+ fastify.post("/users", {
167
+ schema: {
168
+ body: z.object({ email: z.string().email(), name: z.string() }),
169
+ response: { 201: z.object({ id: z.string(), email: z.string() }) },
170
+ },
171
+ handler: async (request) => { ... },
172
+ });
173
+ ```
174
+
175
+ ## Error formatting
176
+
177
+ ```ts
178
+ fastify.setSchemaErrorFormatter((errors, dataVar) => {
179
+ const message = errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).join("; ");
180
+ return new Error(message);
181
+ });
182
+ ```
183
+
184
+ ## Gotchas
185
+
186
+ - **No response schema = slow + leaky** — `JSON.stringify()` is used, and all object properties are included
187
+ - **`additionalProperties: false`** is important — without it, extra fields pass validation
188
+ - **Ajv formats** (`email`, `uuid`, `date-time`, etc.) require `ajv-formats` plugin
189
+ - **Schema compilation** happens at startup — errors are thrown during `.listen()`, not at runtime
190
+ - **Shared schemas** are encapsulation-aware — schemas in child plugins are invisible to parents unless using `fastify-plugin`
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: ioredis
3
+ description: "ioredis v5 reference for Node.js Redis client — connection setup, RedisOptions, pipelines, transactions, Pub/Sub, Lua scripting, Cluster, and Sentinel. Use when: (1) creating or configuring Redis connections (standalone, cluster, sentinel), (2) writing Redis commands with ioredis (get/set, pipelines, multi/exec), (3) setting up Pub/Sub or Streams, (4) configuring retryStrategy, TLS, or auto-pipelining, (5) working with Redis Cluster options (scaleReads, NAT mapping), or (6) debugging ioredis connection issues. Important: use named import `import { Redis } from 'ioredis'` for correct TypeScript types with NodeNext."
4
+ ---
5
+
6
+ # ioredis v5 — Node.js Redis Client
7
+
8
+ ioredis v5.x. Requires Node.js >= 12, Redis >= 2.6.12. 100% TypeScript.
9
+
10
+ ## Critical: Import Style
11
+
12
+ ```ts
13
+ // CORRECT — named import (required for NodeNext / moduleResolution: "nodenext")
14
+ import { Redis } from "ioredis";
15
+
16
+ // For Cluster:
17
+ import { Redis, Cluster } from "ioredis";
18
+ ```
19
+
20
+ ## When to Load References
21
+
22
+ | Need | Reference file |
23
+ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
24
+ | Connection setup, RedisOptions, TLS, retryStrategy, lifecycle | [references/connection-options.md](references/connection-options.md) |
25
+ | Core API: pipelines, transactions, Pub/Sub, Lua scripting, scanning, events | [references/core-api.md](references/core-api.md) |
26
+ | Streams, auto-pipelining, transformers, binary data, error handling, debugging | [references/advanced-patterns.md](references/advanced-patterns.md) |
27
+ | Redis Cluster setup, ClusterOptions, Sentinel config, failover | [references/cluster-sentinel.md](references/cluster-sentinel.md) |
28
+
29
+ ## Quick Reference
30
+
31
+ | Operation | Code |
32
+ | -------------- | -------------------------------------------------------------------------- |
33
+ | Connect | `new Redis()` or `new Redis(6379, "host")` or `new Redis("redis://...")` |
34
+ | Get/Set | `await redis.set("key", "val")` / `await redis.get("key")` |
35
+ | Pipeline | `await redis.pipeline().set("a","1").get("a").exec()` |
36
+ | Transaction | `await redis.multi().set("a","1").get("a").exec()` |
37
+ | Pub/Sub | `sub.subscribe("ch")` / `sub.on("message", cb)` / `pub.publish("ch", msg)` |
38
+ | Lua script | `redis.defineCommand("name", { numberOfKeys: 1, lua: "..." })` |
39
+ | Scan | `redis.scanStream({ match: "prefix:*", count: 100 })` |
40
+ | Graceful close | `await redis.quit()` |
41
+ | Force close | `redis.disconnect()` |
42
+
43
+ ## Common Gotchas
44
+
45
+ 1. **Named import**: Always `import { Redis } from "ioredis"` with NodeNext resolution
46
+ 2. **Pub/Sub isolation**: A subscribed client cannot run other commands — use separate instances
47
+ 3. **`maxRetriesPerRequest`**: Default is 20. Set to `null` for infinite retries (required by BullMQ)
48
+ 4. **Pipeline errors**: `pipeline.exec()` never rejects — errors are in each result's `[0]` position
49
+ 5. **`showFriendlyErrorStack`**: Performance cost — never enable in production
50
+ 6. **Cluster pipelines**: All keys in a pipeline must hash to slots served by the same node
51
+ 7. **`enableAutoPipelining`**: 35-50% throughput improvement, safe to enable globally