Skip to content

Commit 29d6e36

Browse files
Tobbeladderschool
andcommitted
feat(deps): Upgrade to Fastify v5 (#109)
Huge shoutout to @ladderschool who originally created this PR over at the RedwoodGQL repo: redwoodjs/graphql#12046 V4 of Fastify is approaching end of life by 6/30/25. This PR seeks to upgrade the relevant packages. Fastify V5 also requires node >=20 now. Migration docs: https://fastify.dev/docs/latest/Guides/Migration-Guide-V5/ Luckily many changes were already deprecated from V3->V4 and I have found no issues running V5 in my production app. The only breaking change is how Fastify handles the logger, which this PR addresses, specifically in the [createServerHelpers.ts](https://github.com/redwoodjs/graphql/compare/main...ladderschool:redwood:main?expand=1#diff-2f9b7c2c7a03d2b1aca7d841ce3365a524a92b7bee07c5177272f1dbf1395d84) file. ```js // v5 const loggerInstance = require('pino')() const fastify = require('fastify')({ loggerInstance }) ``` There's a test repository that @ladderschool used to confirm these updates in this PR from: https://github.com/ladderschool/fastify-v5-test Local build succeeded: https://cloud.nx.app/runs/saVKz8Qhgn Local tests succeeded: https://cloud.nx.app/runs/5SujFvDgYM --------- Co-authored-by: ladderschool <[email protected]>
1 parent 6533479 commit 29d6e36

File tree

9 files changed

+316
-260
lines changed

9 files changed

+316
-260
lines changed

.changesets/109.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
- feat(deps): Upgrade (#109) by @Tobbe
2+
3+
This PR is a breaking change. It upgrades Fastify from v4 to v5, so if you're
4+
running CedarJS in a serverful environment you should look through your Fastify
5+
specific code.
6+
7+
Note: For v5 Fastify changed how you pass in a custom logger. CedarJS already
8+
had that code somewhat customized, so for this PR we kept the unified `logger`
9+
option we already had, so there should be no change for you in that regards,
10+
but we will probably break this appart in the future to match what Fastify is
11+
doing
12+
13+
See [the Fastify v5 migration docs](https://fastify.dev/docs/latest/Guides/Migration-Guide-V5/)
14+
for all the details.

packages/adapters/fastify/web/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
},
2323
"dependencies": {
2424
"@cedarjs/project-config": "workspace:*",
25-
"@fastify/http-proxy": "9.5.0",
26-
"@fastify/static": "6.12.0",
27-
"@fastify/url-data": "5.4.0",
25+
"@fastify/http-proxy": "11.1.2",
26+
"@fastify/static": "8.2.0",
27+
"@fastify/url-data": "6.0.3",
2828
"fast-glob": "3.3.2"
2929
},
3030
"devDependencies": {
3131
"@cedarjs/framework-tools": "workspace:*",
32-
"fastify": "4.28.1",
32+
"fastify": "5.3.3",
3333
"tsx": "4.19.3",
3434
"typescript": "5.6.2",
3535
"vitest": "2.1.9"

packages/adapters/fastify/web/src/web.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('redwoodFastifyWeb', () => {
5151
})
5252

5353
expect(res.statusCode).toBe(200)
54-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
54+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
5555
expect(res.body).toBe(
5656
fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8'),
5757
)
@@ -66,7 +66,7 @@ describe('redwoodFastifyWeb', () => {
6666
})
6767

6868
expect(res.statusCode).toBe(200)
69-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
69+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
7070
expect(res.body).toBe(
7171
fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8'),
7272
)
@@ -83,7 +83,7 @@ describe('redwoodFastifyWeb', () => {
8383
})
8484

8585
expect(res.statusCode).toBe(200)
86-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
86+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
8787
expect(res.body).toBe(
8888
fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8'),
8989
)
@@ -122,7 +122,7 @@ describe('redwoodFastifyWeb', () => {
122122
})
123123

124124
expect(res.statusCode).toBe(200)
125-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
125+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
126126
expect(res.body).toBe(
127127
fs.readFileSync(path.join(getPaths().web.dist, url), 'utf-8'),
128128
)
@@ -135,7 +135,7 @@ describe('redwoodFastifyWeb', () => {
135135
})
136136

137137
expect(res.statusCode).toBe(200)
138-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
138+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
139139
expect(res.body).toBe(
140140
fs.readFileSync(path.join(getPaths().web.dist, '200.html'), 'utf-8'),
141141
)
@@ -153,7 +153,7 @@ describe('redwoodFastifyWeb', () => {
153153

154154
expect(res.statusCode).toBe(200)
155155
expect(res.headers['content-type']).toBe(
156-
'application/javascript; charset=UTF-8',
156+
'application/javascript; charset=utf-8',
157157
)
158158
expect(res.body).toBe(
159159
fs.readFileSync(
@@ -172,7 +172,7 @@ describe('redwoodFastifyWeb', () => {
172172
})
173173

174174
expect(res.statusCode).toBe(200)
175-
expect(res.headers['content-type']).toBe('text/css; charset=UTF-8')
175+
expect(res.headers['content-type']).toBe('text/css; charset=utf-8')
176176
expect(res.body).toBe(
177177
fs.readFileSync(
178178
path.join(getPaths().web.dist, relativeFilePath),
@@ -191,7 +191,7 @@ describe('redwoodFastifyWeb', () => {
191191

192192
expect(res.statusCode).toBe(200)
193193
expect(res.headers['content-type']).toBe(
194-
'application/json; charset=UTF-8',
194+
'application/json; charset=utf-8',
195195
)
196196
expect(res.body).toBe(
197197
fs.readFileSync(
@@ -220,7 +220,7 @@ describe('redwoodFastifyWeb', () => {
220220
})
221221

222222
expect(res.statusCode).toBe(200)
223-
expect(res.headers['content-type']).toBe('text/markdown; charset=UTF-8')
223+
expect(res.headers['content-type']).toBe('text/markdown; charset=utf-8')
224224
expect(res.body).toBe(
225225
fs.readFileSync(
226226
path.join(getPaths().web.dist, relativeFilePath),
@@ -238,7 +238,7 @@ describe('redwoodFastifyWeb', () => {
238238
})
239239

240240
expect(res.statusCode).toBe(200)
241-
expect(res.headers['content-type']).toBe('text/plain; charset=UTF-8')
241+
expect(res.headers['content-type']).toBe('text/plain; charset=utf-8')
242242
expect(res.body).toBe(
243243
fs.readFileSync(
244244
path.join(getPaths().web.dist, relativeFilePath),

packages/adapters/fastify/web/src/webFallback.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('webFallback', () => {
3737
})
3838

3939
expect(res.statusCode).toBe(200)
40-
expect(res.headers['content-type']).toBe('text/html; charset=UTF-8')
40+
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
4141
expect(res.body).toBe(
4242
fs.readFileSync(path.join(getPaths().web.dist, url), 'utf-8'),
4343
)

packages/api-server/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@
3434
"@cedarjs/internal": "workspace:*",
3535
"@cedarjs/project-config": "workspace:*",
3636
"@cedarjs/web-server": "workspace:*",
37-
"@fastify/multipart": "8.3.1",
38-
"@fastify/url-data": "5.4.0",
37+
"@fastify/multipart": "9.0.3",
38+
"@fastify/url-data": "6.0.3",
3939
"chalk": "4.1.2",
4040
"chokidar": "3.6.0",
4141
"dotenv-defaults": "5.0.2",
4242
"fast-glob": "3.3.2",
4343
"fast-json-parse": "1.0.3",
44-
"fastify": "4.28.1",
45-
"fastify-raw-body": "4.3.0",
44+
"fastify": "5.3.3",
45+
"fastify-raw-body": "5.0.0",
4646
"lodash": "4.17.21",
4747
"pretty-bytes": "5.6.0",
4848
"pretty-ms": "7.0.1",
@@ -57,6 +57,7 @@
5757
"@types/qs": "6.9.16",
5858
"@types/split2": "4.2.3",
5959
"@types/yargs": "17.0.33",
60+
"memfs": "4.17.2",
6061
"pino-abstract-transport": "1.2.0",
6162
"tsx": "4.19.3",
6263
"typescript": "5.6.2",

packages/api-server/src/__tests__/createServer.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ describe('createServer', () => {
160160
level: 30,
161161
msg: 'incoming request',
162162
req: {
163-
hostname: 'localhost:80',
164163
method: 'GET',
165164
remoteAddress: '127.0.0.1',
166165
url: '/hello',

packages/api-server/src/createServerHelpers.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ export interface CreateServerOptions {
2020
/** The prefix for all routes. Defaults to `/` */
2121
apiRootPath?: string
2222

23+
// TODO: This should probably be split, to match Fastify's way of doing things
2324
/** Logger instance or options */
24-
logger?: FastifyServerOptions['logger']
25+
logger?:
26+
| FastifyServerOptions['logger']
27+
| FastifyServerOptions['loggerInstance']
2528

2629
/**
2730
* Options for the fastify server instance.
@@ -74,23 +77,29 @@ type ResolvedOptions = Required<
7477
}
7578
>
7679

80+
function isCustomLoggerInstance(
81+
logger:
82+
| FastifyServerOptions['logger']
83+
| FastifyServerOptions['loggerInstance'],
84+
): logger is FastifyServerOptions['loggerInstance'] {
85+
return !!logger && typeof logger === 'object' && 'info' in logger
86+
}
87+
7788
export function resolveOptions(
7889
options: CreateServerOptions = {},
7990
args?: string[],
8091
) {
8192
options.parseArgs ??= true
8293

8394
const defaults = getDefaultCreateServerOptions()
84-
85-
options.logger ??= defaults.logger
95+
const logger = options.logger ?? defaults.logger
8696

8797
// Set defaults.
8898
const resolvedOptions: ResolvedOptions = {
8999
apiRootPath: options.apiRootPath ?? defaults.apiRootPath,
90100

91101
fastifyServerOptions: options.fastifyServerOptions ?? {
92102
requestTimeout: defaults.fastifyServerOptions.requestTimeout,
93-
logger: options.logger ?? defaults.logger,
94103
bodyLimit: defaults.fastifyServerOptions.bodyLimit,
95104
},
96105
configureApiServer:
@@ -100,9 +109,15 @@ export function resolveOptions(
100109
}
101110

102111
// Merge fastifyServerOptions.
112+
103113
resolvedOptions.fastifyServerOptions.requestTimeout ??=
104114
defaults.fastifyServerOptions.requestTimeout
105-
resolvedOptions.fastifyServerOptions.logger = options.logger
115+
116+
if (isCustomLoggerInstance(logger)) {
117+
resolvedOptions.fastifyServerOptions.loggerInstance = logger
118+
} else {
119+
resolvedOptions.fastifyServerOptions.logger = logger
120+
}
106121

107122
if (options.parseArgs) {
108123
const { values } = parseArgs({

packages/web-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"@cedarjs/project-config": "workspace:*",
3030
"chalk": "4.1.2",
3131
"dotenv-defaults": "5.0.2",
32-
"fastify": "4.28.1",
32+
"fastify": "5.3.3",
3333
"fs-extra": "11.2.0",
3434
"yargs": "17.7.2"
3535
},

0 commit comments

Comments
 (0)