fastify 5.12.1 → 5.12.3

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.
@@ -1,22 +0,0 @@
1
- ## 15:46 UTC — Task
2
-
3
- ### What went wrong
4
- - Interpolated `${{ inputs.package }}` directly into `actions/github-script` JavaScript, allowing malformed input to break or inject code.
5
- - Fetched npm metadata with the raw package name instead of URL-encoding it.
6
- - Assumed `data.repository.url` always existed and was a GitHub `.git` URL.
7
- - Used a brittle repository URL regex that missed scoped/modern GitHub URL formats and failed without a clear error.
8
-
9
- ### How it was fixed
10
- - Pass workflow input through `env.NPM_PACKAGE` and read it from `process.env` inside the script.
11
- - Validate the package name with an npm package-name regex before using it.
12
- - Use `encodeURIComponent(packageName)` in the npm registry URL.
13
- - Check `response.ok` and throw explicit errors for failed registry fetches or unsupported repository URLs.
14
-
15
- ## 16:04 UTC — Task
16
-
17
- ### What went wrong
18
- - PR title did not satisfy the repository's conventional title check before opening/updating the PR.
19
-
20
- ### How it was fixed
21
- - Renamed PR #6833 to `ci: harden CITGM package workflow input handling` using `gh pr edit`, then watched checks until `pull-request-title-check` passed.
22
-
@@ -1,50 +0,0 @@
1
- ## 19:37 UTC — Task
2
-
3
- ### What went wrong
4
- - Continued initiating tool work after the tool-budget warning instead of stopping to assess the existing evidence.
5
- - Started a test command that was aborted, leaving the primitive-coercion fix unverified.
6
- - Investigated Ajv internals and custom compiler compatibility without first isolating the exact failing repository behavior.
7
- - Did not establish regression coverage for missing schemaEnv handling and root primitive coercion before changing direction.
8
-
9
- ### How it was fixed
10
- - Honor soft tool-budget and interruption signals immediately; stop browsing and provide a bounded reflection.
11
- - Run only the single highest-value targeted test before the budget limit, then report if execution is blocked.
12
- - Reproduce root primitive coercion with the repository’s actual validatorCompiler path rather than relying on Ajv internals alone.
13
- - Add focused tests covering custom validator compilation, schemaEnv availability, and root primitive coercion.
14
-
15
- ## 20:03 UTC — Task
16
-
17
- ### What went wrong
18
- - Root primitive request values were validated without a parent reference, so Ajv coercion changed only its local value and left request.body as a string.
19
- - Test command output was misread: Borp ran the broader suite despite a specific file argument, making targeted coverage unclear.
20
-
21
- ### How it was fixed
22
- - Pass request and parameter metadata as Ajv parentData/parentDataProperty so root coercions update the original request value.
23
- - Add a regression test asserting quoted numeric JSON becomes a number in the handler while out-of-range values remain rejected.
24
- - Verify targeted test execution separately from the full suite to avoid mistaking aggregate counts for focused coverage.
25
-
26
- ## 20:06 UTC — Task
27
-
28
- ### What went wrong
29
- - Ajv was called with a primitive root value without parentData context, so coerced values were not written back to request.body.
30
- - The regression scenario was initially vulnerable because the handler received string "10" after validation accepted it.
31
- - The CVSS rating assumed PR:L without repository evidence that authentication is required; many affected routes may be unauthenticated.
32
- - The impact rating was stated as application-dependent without defining the affected endpoint’s actual confidentiality and integrity consequences.
33
-
34
- ### How it was fixed
35
- - Pass parentData and parentDataProperty to Ajv validators so root primitive coercions update the request object.
36
- - Retain the direct-call path for validators without schemaEnv to avoid changing non-Ajv validator behavior.
37
- - Add a regression test asserting quoted numeric JSON reaches the handler as number 10.
38
- - Determine PR from the deployed route’s authentication requirements; use PR:N for unauthenticated endpoints.
39
- - Base C/I impact on the specific handler and data affected rather than assigning a universal Fastify score.
40
-
41
- ## 20:09 UTC — Task
42
-
43
- ### What went wrong
44
- - Validation coerced a root primitive but failed to preserve the coerced value for the caller.
45
- - The regression scenario was not covered by existing tests.
46
-
47
- ### How it was fixed
48
- - Updated `lib/validation.js` to retain and return coerced root values.
49
- - Added `test/fix-root-primitive-coercion.test.js` to prevent recurrence.
50
-
@@ -1,41 +0,0 @@
1
- ## 10:59 UTC — Task
2
-
3
- ### What went wrong
4
- - Assumed /static/..%2f… 404 meant getPathnameForSend/route miss instead of later send pipeline behavior
5
- - Did not check that encodeURI() re-encodes residual % as %25 before blaming path guards
6
- - Conflated reply.callNotFound() JSON ("Route GET:… not found") with an actual find-my-way miss
7
- - Debugged isolated getPathnameForSend reimplementation before tracing pumpSendToReply → encodeURI(pathnameForSend) → @fastify/send
8
- - Compared send() on decoded ../ paths (403) to static outcomes without using the exact post-encodeURI string static passes
9
-
10
- ### How it was fixed
11
- - Always log/compare the exact pathname string passed into send(), including after encodeURI
12
- - When statuses differ for "same" path, diff charCodes for % vs %25 double-encoding first
13
- - Instrument static handler vs router to separate callNotFound from unmatched routes
14
- - Trace full pipeline: raw.url → getPathnameForSend → dotDot guards → encodeURI → @fastify/send
15
- - Reproduce with send(root, p) using both raw and encodeURI(p) before changing triage conclusions
16
-
17
- ## 11:12 UTC — Task
18
-
19
- ### What went wrong
20
- - Assumed encodeURI leaves '%' intact on paths like '/..%2ftop-secret.txt', so static 404 vs raw '..' 403 looked inconsistent.
21
- - Treated encoded traversal and decoded param sinks as the same layer before separating find-my-way dual-decode from @fastify/send root checks.
22
- - Relied on log/message shape alone (callNotFound 'Route ... not found') to infer static failure mode without probing @fastify/send inputs.
23
-
24
- ### How it was fixed
25
- - Empirically print encodeURI output/charCodes: '%' → '%25', so static sees '/..%252ftop-secret.txt' (safe 404) not a '..' segment.
26
- - Reproduce with @fastify/send directly for raw percent, encodeURI(percent), and decoded '../' to map 403 vs 404 to normalize/root logic.
27
- - Keep reporter response framed as app-level path.join(param) misuse; cite static/sendFile containment and Express parity, not a core CVE.
28
-
29
- ## 12:31 UTC — Task
30
-
31
- ### What went wrong
32
- - Markdown lint invoked in a way that flooded output with unrelated files (AGENTS.md, .pi memory, response.md) instead of only the two edited docs.
33
- - Untracked response.md sat in the working tree and could have been staged if git add was too broad.
34
- - Relied on noisy repo-wide lint signal before confirming MD013 on the actual changed regions.
35
-
36
- ### How it was fixed
37
- - Re-run markdownlint scoped strictly to docs/Reference/Request.md and docs/Reference/Routes.md.
38
- - Stage only those two paths (git add docs/Reference/Request.md docs/Reference/Routes.md); never git add .
39
- - Manually awk length>80 on changed files to confirm new lines stay ≤80 before commit.
40
- - Leave response.md untracked and verify git status/diff --stat before commit and PR.
41
-
@@ -1,40 +0,0 @@
1
- ## 19:37 UTC — Task
2
-
3
- ### What went wrong
4
- - Assumed the draft advisory meant `origin/main` and `origin/5.x` must remain untouched without first confirming whether the user expected public pushes.
5
- - Reported that the private branches were complete without clearly distinguishing advisory-fork refs from public `origin` refs, prompting the user to stop and verify deployment status.
6
- - Combined PR closing with an unsupported workspace-repository comment under `set -e`, causing the entire command to fail before the close could occur.
7
- - Called the PR “now-empty” even though GitHub still reported it as mergeable with different head and base OIDs.
8
- - Deleted local security branches before resolving whether the user wanted the commits pushed to public branches, reducing convenient recovery points.
9
-
10
- ### How it was fixed
11
- - Before any security-fix push, explicitly ask whether targets are the private advisory fork, public `origin`, or both; treat a draft advisory as a warning, not implicit authorization policy.
12
- - Always state push destinations and exact resulting refs, e.g. `advisory-ghsa-3m5p/main` changed while `origin/main` remained at `6e95cb9f`.
13
- - Run workspace-sensitive PR operations separately: attempt the comment, record an expected permission denial, then independently close only if authorized.
14
- - Describe PR state from verified fields (`CLOSED`, `mergedAt: null`, head/base OIDs) rather than inferring that it is empty.
15
- - Keep local security branches until the user confirms the intended public/private publication state; delete them only after final authorization and ref verification.
16
-
17
- ## 19:38 UTC — Task
18
-
19
- ### What went wrong
20
- - Initially pushed the security fix only to the private advisory fork, leaving `origin/main` and `origin/5.x` unchanged without first confirming the intended publication target.
21
- - After pushing remote refs, local `main` remained one commit behind, creating temporary local/remote inconsistency.
22
- - A GraphQL `addComment` action was attempted despite workspace-repository restrictions; the denial indicates an intentional permission boundary that should not be bypassed.
23
-
24
- ### How it was fixed
25
- - Obtained explicit approval before public disclosure, then atomically fast-forwarded `origin/main` to `af079bd4` and `origin/5.x` to `8acfea7e`, verifying both refs with `git ls-remote`.
26
- - Fast-forwarded local `main` to `origin/main` and confirmed a clean synchronized status.
27
- - Do not retry forbidden workspace GraphQL actions; use permitted repository operations or ask the user for an authorized alternative before attempting comments or metadata changes.
28
-
29
- ## 19:46 UTC — Task
30
-
31
- ### What went wrong
32
- - Private PR #1 remained open after its head commit had already been placed on private `main`; its mergeability was `UNKNOWN` and it was no longer the correct landing path.
33
- - Local `main` and temporary security branches were left out of sync after updating the remote branches.
34
- - Direct public branch updates bypassed the repository’s pull-request-only rules, so ancestry and target refs required explicit validation to avoid unsafe rewrites.
35
-
36
- ### How it was fixed
37
- - Closed PR #1 without merging after confirming its head SHA was already the intended private `main` commit.
38
- - Fetched current `origin/main` and `origin/5.x`, verified each security commit’s parent exactly matched the corresponding remote tip, then used an atomic push.
39
- - Verified public and private `main`/`5.x` refs matched, fast-forwarded local `main`, deleted temporary security branches, and confirmed a clean synchronized checkout.
40
-
@@ -1,89 +0,0 @@
1
- # Long-term Memory
2
-
3
- Complete history of durable learnings and recurring mistakes.
4
- Last updated: 2026-08-18T19:46:43.093Z
5
-
6
- ## All learnings
7
- - Closed PR #1 without merging after confirming its head SHA was already the intended private `main` commit.
8
- - Fetched current `origin/main` and `origin/5.x`, verified each security commit’s parent exactly matched the corresponding remote tip, then used an atomic push.
9
- - Verified public and private `main`/`5.x` refs matched, fast-forwarded local `main`, deleted temporary security branches, and confirmed a clean synchronized checkout.
10
- - Obtained explicit approval before public disclosure, then atomically fast-forwarded `origin/main` to `af079bd4` and `origin/5.x` to `8acfea7e`, verifying both refs with `git ls-remote`.
11
- - Fast-forwarded local `main` to `origin/main` and confirmed a clean synchronized status.
12
- - Do not retry forbidden workspace GraphQL actions; use permitted repository operations or ask the user for an authorized alternative before attempting comments or metadata changes.
13
- - Before any security-fix push, explicitly ask whether targets are the private advisory fork, public `origin`, or both; treat a draft advisory as a warning, not implicit authorization policy.
14
- - Always state push destinations and exact resulting refs, e.g. `advisory-ghsa-3m5p/main` changed while `origin/main` remained at `6e95cb9f`.
15
- - Run workspace-sensitive PR operations separately: attempt the comment, record an expected permission denial, then independently close only if authorized.
16
- - Describe PR state from verified fields (`CLOSED`, `mergedAt: null`, head/base OIDs) rather than inferring that it is empty.
17
- - Keep local security branches until the user confirms the intended public/private publication state; delete them only after final authorization and ref verification.
18
- - Re-run markdownlint scoped strictly to docs/Reference/Request.md and docs/Reference/Routes.md.
19
- - Stage only those two paths (git add docs/Reference/Request.md docs/Reference/Routes.md); never git add .
20
- - Manually awk length>80 on changed files to confirm new lines stay ≤80 before commit.
21
- - Leave response.md untracked and verify git status/diff --stat before commit and PR.
22
- - Empirically print encodeURI output/charCodes: '%' → '%25', so static sees '/..%252ftop-secret.txt' (safe 404) not a '..' segment.
23
- - Reproduce with @fastify/send directly for raw percent, encodeURI(percent), and decoded '../' to map 403 vs 404 to normalize/root logic.
24
- - Keep reporter response framed as app-level path.join(param) misuse; cite static/sendFile containment and Express parity, not a core CVE.
25
- - Always log/compare the exact pathname string passed into send(), including after encodeURI
26
- - When statuses differ for "same" path, diff charCodes for % vs %25 double-encoding first
27
- - Instrument static handler vs router to separate callNotFound from unmatched routes
28
- - Trace full pipeline: raw.url → getPathnameForSend → dotDot guards → encodeURI → @fastify/send
29
- - Reproduce with send(root, p) using both raw and encodeURI(p) before changing triage conclusions
30
- - Updated `lib/validation.js` to retain and return coerced root values.
31
- - Added `test/fix-root-primitive-coercion.test.js` to prevent recurrence.
32
- - Pass parentData and parentDataProperty to Ajv validators so root primitive coercions update the request object.
33
- - Retain the direct-call path for validators without schemaEnv to avoid changing non-Ajv validator behavior.
34
- - Add a regression test asserting quoted numeric JSON reaches the handler as number 10.
35
- - Determine PR from the deployed route’s authentication requirements; use PR:N for unauthenticated endpoints.
36
- - Base C/I impact on the specific handler and data affected rather than assigning a universal Fastify score.
37
- - Pass request and parameter metadata as Ajv parentData/parentDataProperty so root coercions update the original request value.
38
- - Add a regression test asserting quoted numeric JSON becomes a number in the handler while out-of-range values remain rejected.
39
- - Verify targeted test execution separately from the full suite to avoid mistaking aggregate counts for focused coverage.
40
- - Honor soft tool-budget and interruption signals immediately; stop browsing and provide a bounded reflection.
41
- - Run only the single highest-value targeted test before the budget limit, then report if execution is blocked.
42
- - Reproduce root primitive coercion with the repository’s actual validatorCompiler path rather than relying on Ajv internals alone.
43
- - Add focused tests covering custom validator compilation, schemaEnv availability, and root primitive coercion.
44
- - Renamed PR #6833 to `ci: harden CITGM package workflow input handling` using `gh pr edit`, then watched checks until `pull-request-title-check` passed.
45
- - Pass workflow input through `env.NPM_PACKAGE` and read it from `process.env` inside the script.
46
- - Validate the package name with an npm package-name regex before using it.
47
- - Use `encodeURIComponent(packageName)` in the npm registry URL.
48
- - Check `response.ok` and throw explicit errors for failed registry fetches or unsupported repository URLs.
49
-
50
- ## All watch-outs
51
- - Private PR #1 remained open after its head commit had already been placed on private `main`; its mergeability was `UNKNOWN` and it was no longer the correct landing path.
52
- - Local `main` and temporary security branches were left out of sync after updating the remote branches.
53
- - Direct public branch updates bypassed the repository’s pull-request-only rules, so ancestry and target refs required explicit validation to avoid unsafe rewrites.
54
- - Initially pushed the security fix only to the private advisory fork, leaving `origin/main` and `origin/5.x` unchanged without first confirming the intended publication target.
55
- - After pushing remote refs, local `main` remained one commit behind, creating temporary local/remote inconsistency.
56
- - A GraphQL `addComment` action was attempted despite workspace-repository restrictions; the denial indicates an intentional permission boundary that should not be bypassed.
57
- - Assumed the draft advisory meant `origin/main` and `origin/5.x` must remain untouched without first confirming whether the user expected public pushes.
58
- - Reported that the private branches were complete without clearly distinguishing advisory-fork refs from public `origin` refs, prompting the user to stop and verify deployment status.
59
- - Combined PR closing with an unsupported workspace-repository comment under `set -e`, causing the entire command to fail before the close could occur.
60
- - Called the PR “now-empty” even though GitHub still reported it as mergeable with different head and base OIDs.
61
- - Deleted local security branches before resolving whether the user wanted the commits pushed to public branches, reducing convenient recovery points.
62
- - Markdown lint invoked in a way that flooded output with unrelated files (AGENTS.md, .pi memory, response.md) instead of only the two edited docs.
63
- - Untracked response.md sat in the working tree and could have been staged if git add was too broad.
64
- - Relied on noisy repo-wide lint signal before confirming MD013 on the actual changed regions.
65
- - Assumed encodeURI leaves '%' intact on paths like '/..%2ftop-secret.txt', so static 404 vs raw '..' 403 looked inconsistent.
66
- - Treated encoded traversal and decoded param sinks as the same layer before separating find-my-way dual-decode from @fastify/send root checks.
67
- - Relied on log/message shape alone (callNotFound 'Route ... not found') to infer static failure mode without probing @fastify/send inputs.
68
- - Assumed /static/..%2f… 404 meant getPathnameForSend/route miss instead of later send pipeline behavior
69
- - Did not check that encodeURI() re-encodes residual % as %25 before blaming path guards
70
- - Conflated reply.callNotFound() JSON ("Route GET:… not found") with an actual find-my-way miss
71
- - Debugged isolated getPathnameForSend reimplementation before tracing pumpSendToReply → encodeURI(pathnameForSend) → @fastify/send
72
- - Compared send() on decoded ../ paths (403) to static outcomes without using the exact post-encodeURI string static passes
73
- - Validation coerced a root primitive but failed to preserve the coerced value for the caller.
74
- - The regression scenario was not covered by existing tests.
75
- - Ajv was called with a primitive root value without parentData context, so coerced values were not written back to request.body.
76
- - The regression scenario was initially vulnerable because the handler received string "10" after validation accepted it.
77
- - The CVSS rating assumed PR:L without repository evidence that authentication is required; many affected routes may be unauthenticated.
78
- - The impact rating was stated as application-dependent without defining the affected endpoint’s actual confidentiality and integrity consequences.
79
- - Root primitive request values were validated without a parent reference, so Ajv coercion changed only its local value and left request.body as a string.
80
- - Test command output was misread: Borp ran the broader suite despite a specific file argument, making targeted coverage unclear.
81
- - Continued initiating tool work after the tool-budget warning instead of stopping to assess the existing evidence.
82
- - Started a test command that was aborted, leaving the primitive-coercion fix unverified.
83
- - Investigated Ajv internals and custom compiler compatibility without first isolating the exact failing repository behavior.
84
- - Did not establish regression coverage for missing schemaEnv handling and root primitive coercion before changing direction.
85
- - PR title did not satisfy the repository's conventional title check before opening/updating the PR.
86
- - Interpolated `${{ inputs.package }}` directly into `actions/github-script` JavaScript, allowing malformed input to break or inject code.
87
- - Fetched npm metadata with the raw package name instead of URL-encoding it.
88
- - Assumed `data.repository.url` always existed and was a GitHub `.git` URL.
89
- - Used a brittle repository URL regex that missed scoped/modern GitHub URL formats and failed without a clear error.
package/AGENTS.md DELETED
@@ -1,290 +0,0 @@
1
- # AGENTS.md - Guide for AI Agents Working with Fastify
2
-
3
- This document provides information and guidelines for AI agents (such as GitHub Copilot, Cursor, pi, or other AI coding assistants) working with the Fastify codebase.
4
-
5
- ## Project Overview
6
-
7
- Fastify is a high-performance web framework for Node.js focused on:
8
- - **Speed**: One of the fastest Node.js web frameworks
9
- - **Extensibility**: Powerful plugin architecture with hooks and decorators
10
- - **Schema-based**: JSON Schema validation and serialization
11
- - **Developer experience**: Expressive API with minimal overhead
12
- - **TypeScript support**: Full type definitions included
13
-
14
- **Current Version**: 5.7.1 (main branch)
15
- **Repository**: https://github.com/fastify/fastify
16
-
17
- ## Repository Structure
18
-
19
- ```
20
- fastify/
21
- ├── docs/ # Documentation (Guides and Reference)
22
- │ ├── Guides/ # Tutorials and how-to guides
23
- │ └── Reference/ # API documentation
24
- ├── examples/ # Example applications and benchmarks
25
- ├── lib/ # Core library code
26
- ├── test/ # Test files
27
- ├── types/ # TypeScript type definitions
28
- ├── build/ # Build scripts
29
- ├── integration/ # Integration tests
30
- ├── fastify.js # Main entry point
31
- ├── fastify.d.ts # Main TypeScript definitions
32
- └── package.json # Dependencies and scripts
33
- ```
34
-
35
- ## Key Files for Agents
36
-
37
- ### Core Files
38
- - **`fastify.js`** - Main Fastify class and entry point
39
- - **`fastify.d.ts`** - TypeScript type definitions (keep these in sync)
40
- - **`lib/`** - All core functionality:
41
- - `route.js` - Route handling
42
- - `req-res.js` - Request and Reply objects
43
- - `hooks.js` - Lifecycle hooks
44
- - `plugin.js` - Plugin system
45
- - `validation.js` - Schema validation
46
- - `content-type-parser.js` - Body parsing
47
- - `logger.js` - Pino logger integration
48
-
49
- ### Configuration Files
50
- - **`package.json`** - Scripts, dependencies, and contributors
51
- - **`eslint.config.js`** - Linting configuration (uses neostandard)
52
- - **`.markdownlint-cli2.yaml`** - Markdown linting rules
53
-
54
- ### Documentation Files
55
- - **`README.md`** - Project overview and quick start
56
- - **`CONTRIBUTING.md`** - Contribution guidelines
57
- - **`GOVERNANCE.md`** - Links to organization governance
58
- - **`SECURITY.md`** - Security policy
59
- - **`docs/Guides/Contributing.md`** - Detailed contributing guide
60
- - **`docs/Guides/Style-Guide.md`** - Coding style conventions
61
-
62
- ## Testing Conventions
63
-
64
- ### Test Framework
65
- Fastify uses **Borp** (a custom test runner) for testing.
66
-
67
- ### Test Structure
68
- - Tests are in the **`test/`** directory
69
- - Test files follow the pattern: `test/<module>.test.js`
70
- - Integration tests are in **`integration/`** directory
71
-
72
- ### Running Tests
73
-
74
- ```bash
75
- # Run all tests
76
- npm test
77
-
78
- # Run unit tests only
79
- npm run unit
80
-
81
- # Run tests with coverage
82
- npm run coverage
83
-
84
- # Run tests in watch mode
85
- npm run test:watch
86
-
87
- # Run TypeScript type tests
88
- npm run test:typescript
89
-
90
- # Run CI tests (minimal)
91
- npm run test:ci
92
- ```
93
-
94
- ### Test Requirements
95
- - **100% line coverage** is required for all changes (enforced by CI)
96
- - Tests must pass on all supported Node.js versions
97
- - TypeScript types must be tested (using `tsd`)
98
-
99
- ## Code Style and Conventions
100
-
101
- ### Linting
102
- - Uses **Neostandard** JavaScript style guide
103
- - ESLint is configured in `eslint.config.js`
104
- - Run `npm run lint` to check code style
105
- - Run `npm run lint:fix` to auto-fix issues
106
-
107
- ### Key Style Rules (from Style-Guide.md)
108
- - Use `const` and `let`, never `var`
109
- - Use arrow functions for callbacks
110
- - Use async/await instead of promises
111
- - Follow semicolon usage (neostandard enforces this)
112
- - Use template literals for string interpolation
113
- - Prefer functional methods (`map`, `filter`, `reduce`) over loops
114
- - Error-first callback pattern for async operations where needed
115
-
116
- ### Naming Conventions
117
- - **Files**: kebab-case (`content-type-parser.js`)
118
- - **Variables**: camelCase
119
- - **Constants**: UPPER_SNAKE_CASE
120
- - **Classes**: PascalCase
121
- - **Private methods**: prefixed with `_`
122
-
123
- ## Common Tasks
124
-
125
- ### Adding a New Feature
126
- 1. Implement the feature in `lib/`
127
- 2. Add tests in `test/`
128
- 3. Update TypeScript types in `fastify.d.ts` or `types/`
129
- 4. Update documentation in `docs/`
130
- 5. Run `npm test` to ensure all tests pass
131
- 6. Run `npm run lint` to check code style
132
- 7. Add changelog entry for release
133
-
134
- ### Fixing a Bug
135
- 1. Add a failing test case in `test/`
136
- 2. Fix the bug in `lib/`
137
- 3. Ensure all tests pass
138
- 4. Check if TypeScript types need updating
139
- 5. Update documentation if behavior changes
140
-
141
- ### Working with Plugins
142
- - See `docs/Guides/Write-Plugin.md` for plugin authoring
143
- - See `docs/Guides/Plugins-Guide.md` for plugin usage
144
- - Plugin example: `lib/plugin.js`
145
-
146
- ## Architecture Highlights
147
-
148
- ### Core Components
149
-
150
- 1. **Server (`fastify.js`)**
151
- - Main Fastify class
152
- - Server initialization and configuration
153
- - Plugin system integration (via `avvio`)
154
-
155
- 2. **Routing (`lib/route.js`)**
156
- - Uses `find-my-way` for fast route matching
157
- - Route registration and lookup
158
- - Shorthand methods (get, post, put, delete, etc.)
159
-
160
- 3. **Request/Response (`lib/req-res.js`)**
161
- - Request object extensions
162
- - Reply object with fluent API
163
- - Decorator support
164
-
165
- 4. **Hooks (`lib/hooks.js`)**
166
- - Lifecycle hooks (onRequest, preHandler, etc.)
167
- - Hook execution order and timing
168
-
169
- 5. **Validation (`lib/validation.js`)**
170
- - JSON Schema validation via AJV
171
- - Response serialization
172
- - Built-in error serializer
173
-
174
- 6. **Content Type Parser (`lib/content-type-parser.js`)**
175
- - Request body parsing
176
- - Custom parser support
177
- - JSON and other formats
178
-
179
- ### Plugin System
180
- - Plugins are loaded asynchronously via `avvio`
181
- - Supports encapsulation (scoped plugins)
182
- - Hooks and decorators can be scoped
183
- - See `lib/plugin.js` for implementation
184
-
185
- ## TypeScript Integration
186
-
187
- - TypeScript definitions are in `fastify.d.ts` and `types/`
188
- - Types must be tested with `tsd`
189
- - Run `npm run test:typescript` to verify types
190
- - Keep types in sync with JavaScript implementation
191
-
192
- ## Performance Considerations
193
-
194
- Fastify prioritizes performance:
195
- - **Routes**: Pre-compiled functions for fast matching
196
- - **Validation**: Compiled JSON Schema validators
197
- - **Serialization**: Compiled serializers (fast-json-stringify)
198
- - **Logging**: Low-overhead Pino logger
199
- - **Caching**: Route context caching with `toad-cache`
200
-
201
- When making changes:
202
- - Profile performance impact for hot paths
203
- - Use benchmarks in `examples/benchmark/`
204
- - Run `npm run benchmark` to measure
205
-
206
- ## Documentation Updates
207
-
208
- Documentation is critical for Fastify. When changing behavior:
209
-
210
- 1. Update relevant docs in `docs/Reference/` for API changes
211
- 2. Update `docs/Guides/` for usage pattern changes
212
- 3. Check for broken links (CI validates this)
213
- 4. Update examples in `examples/` if needed
214
- 5. Run `npm run lint:markdown` to check docs
215
-
216
- ## Pre-commit Checks
217
-
218
- Before submitting changes, ensure:
219
-
220
- 1. ✅ All tests pass: `npm test`
221
- 2. ✅ 100% coverage: `npm run coverage`
222
- 3. ✅ Linting passes: `npm run lint`
223
- 4. ✅ TypeScript types pass: `npm run test:typescript`
224
- 5. ✅ Markdown linting passes: `npm run lint:markdown`
225
- 6. ✅ Documentation is updated
226
- 7. ✅ Examples still work if affected
227
-
228
- ## Working with CI
229
-
230
- Fastify uses GitHub Actions for CI. Workflows are in `.github/workflows/`:
231
- - **`ci.yml`** - Main CI pipeline
232
- - **`package-manager-ci.yml`** - Tests multiple package managers
233
- - **`website.yml`** - Website deployment
234
-
235
- ## Agent-Specific Tips
236
-
237
- ### When Generating Code
238
- 1. Check existing patterns in `lib/` before creating new patterns
239
- 2. Follow the established error handling patterns
240
- 3. Use async/await consistently
241
- 4. Add appropriate hooks if extending lifecycle
242
- 5. Consider TypeScript types from the start
243
-
244
- ### When Refactoring
245
- 1. Ensure all tests still pass
246
- 2. Don't change public APIs without semver consideration
247
- 3. Update TypeScript definitions if signatures change
248
- 4. Check for deprecation needs
249
- 5. Update documentation for changed behavior
250
-
251
- ### When Analyzing Issues
252
- 1. Check `test/` for usage examples
253
- 2. Review relevant `docs/Reference/` files
254
- 3. Look at similar implementations in `lib/`
255
- 4. Consider the plugin system and encapsulation
256
- 5. Check hook timing and order
257
-
258
- ### Common Gotchas
259
- - **Encapsulation**: Plugins are isolated - decorators don't leak
260
- - **Hook order**: Hooks run in specific order (see docs/Reference/Hooks.md)
261
- - **Async boot**: Server starts asynchronously - use `ready()` or `after()`
262
- - **Error handling**: Use Fastify error classes from `@fastify/error`
263
- - **Validation**: Schemas are compiled - changes require recompilation
264
-
265
- ## Key Dependencies
266
-
267
- - **`avvio`** - Plugin loading and boot
268
- - **`find-my-way`** - Fast HTTP router
269
- - **`fast-json-stringify`** - Response serialization
270
- - **`pino`** - Logging
271
- - **`@fastify/ajv-compiler`** - JSON Schema validation
272
- - **`light-my-request`** - HTTP injection for testing
273
-
274
- ## Contact and Resources
275
-
276
- - **Documentation**: https://fastify.dev/
277
- - **Discord**: https://discord.gg/fastify
278
- - **GitHub Issues**: https://github.com/fastify/fastify/issues
279
- - **GitHub Discussions**: https://github.com/fastify/fastify/discussions
280
- - **Help**: https://github.com/fastify/help
281
-
282
- ## Version Information
283
-
284
- - **Main branch**: Fastify v5
285
- - **v4 branch**: https://github.com/fastify/fastify/tree/4.x
286
- - **LTS Policy**: See `docs/Reference/LTS.md`
287
-
288
- ---
289
-
290
- This document is maintained by the Fastify team. For questions or suggestions, please open an issue or discussion.