@gasket/plugin-fastify 8.0.0-next.1 → 8.0.0-next.2
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.
- package/README.md +12 -0
- package/lib/adapters/adapter-factory.js +46 -0
- package/lib/adapters/base-adapter.js +30 -0
- package/lib/adapters/fastify-v4-adapter.js +55 -0
- package/lib/adapters/fastify-v5-adapter.js +67 -0
- package/lib/adapters/index.js +4 -0
- package/lib/utils.js +15 -27
- package/package.json +3 -7
package/README.md
CHANGED
|
@@ -24,6 +24,18 @@ export default makeGasket({
|
|
|
24
24
|
});
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Fastify Version Support
|
|
28
|
+
|
|
29
|
+
This plugin supports both Fastify v4 and v5 through an internal adapter pattern. The appropriate version-specific adapter is automatically selected based on your installed Fastify version.
|
|
30
|
+
|
|
31
|
+
### Fastify v4
|
|
32
|
+
- **Installation**: `npm install fastify@^4`
|
|
33
|
+
|
|
34
|
+
### Fastify v5
|
|
35
|
+
- **Installation**: `npm install fastify@^5`
|
|
36
|
+
|
|
37
|
+
The plugin automatically detects your Fastify version and applies the correct configuration. No manual configuration is required.
|
|
38
|
+
|
|
27
39
|
## Configuration
|
|
28
40
|
|
|
29
41
|
All the configurations for the plugin are added under `fastify` in the config:
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { FastifyV4Adapter } from './fastify-v4-adapter.js';
|
|
3
|
+
import { FastifyV5Adapter } from './fastify-v5-adapter.js';
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Detect the installed Fastify version.
|
|
9
|
+
* Reads the version from fastify/package.json in node_modules.
|
|
10
|
+
* This works reliably with npm, pnpm, yarn, and bun.
|
|
11
|
+
* @returns {string} - Version string (e.g., '5.2.1')
|
|
12
|
+
*/
|
|
13
|
+
export function detectFastifyVersion() {
|
|
14
|
+
try {
|
|
15
|
+
const fastifyModule = require('fastify/package.json');
|
|
16
|
+
return fastifyModule.version;
|
|
17
|
+
} catch (err) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Could not detect Fastify version. Ensure fastify is installed.\n' +
|
|
20
|
+
`Error: ${err.message}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create the appropriate Fastify adapter based on the installed Fastify version.
|
|
27
|
+
* Automatically detects the version from fastify/package.json.
|
|
28
|
+
* @returns {import('./base-adapter.js').FastifyAdapter} - Adapter instance
|
|
29
|
+
*/
|
|
30
|
+
export function createFastifyAdapter() {
|
|
31
|
+
const version = detectFastifyVersion();
|
|
32
|
+
const majorVersion = parseInt(version.split('.')[0], 10);
|
|
33
|
+
|
|
34
|
+
switch (majorVersion) {
|
|
35
|
+
case 4:
|
|
36
|
+
return new FastifyV4Adapter();
|
|
37
|
+
case 5:
|
|
38
|
+
return new FastifyV5Adapter();
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Unsupported Fastify version: ${version}\n` +
|
|
42
|
+
'Gasket supports Fastify v4 and v5. Please upgrade or downgrade Fastify, ' +
|
|
43
|
+
'or open an issue at https://github.com/godaddy/gasket'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base abstract class for Fastify version adapters.
|
|
3
|
+
* Provides a common interface for creating and configuring Fastify instances
|
|
4
|
+
* across different major versions.
|
|
5
|
+
* @abstract
|
|
6
|
+
*/
|
|
7
|
+
export class FastifyAdapter {
|
|
8
|
+
constructor() {
|
|
9
|
+
if (new.target === FastifyAdapter) {
|
|
10
|
+
throw new Error('FastifyAdapter is an abstract class and cannot be instantiated directly');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a Fastify instance with version-specific configuration.
|
|
16
|
+
* Subclasses must implement this method to handle version-specific options.
|
|
17
|
+
* @abstract
|
|
18
|
+
* @param {object} config - Fastify configuration options
|
|
19
|
+
* @param {boolean} [config.trustProxy] - Trust proxy headers
|
|
20
|
+
* @param {object} [config.https] - HTTPS configuration
|
|
21
|
+
* @param {boolean} [config.http2] - Enable HTTP/2
|
|
22
|
+
* @param {boolean} [config.disableRequestLogging] - Disable request logging
|
|
23
|
+
* @param {object} logger - Gasket logger instance
|
|
24
|
+
* @returns {ReturnType<typeof import('fastify').default>} - Configured Fastify instance
|
|
25
|
+
*/
|
|
26
|
+
// eslint-disable-next-line no-unused-vars
|
|
27
|
+
createInstance(config, logger) {
|
|
28
|
+
throw new Error('createInstance() must be implemented by subclass');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fastify from 'fastify';
|
|
2
|
+
import { FastifyAdapter } from './base-adapter.js';
|
|
3
|
+
|
|
4
|
+
const fallbackMap = {
|
|
5
|
+
fatal: 'error',
|
|
6
|
+
trace: 'debug'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adapter for Fastify v4.x
|
|
11
|
+
*
|
|
12
|
+
* Key differences from v5:
|
|
13
|
+
* - Uses 'logger' option (not 'loggerInstance')
|
|
14
|
+
* - No 'useSemicolonDelimiter' option
|
|
15
|
+
* - Supports Node.js v14+
|
|
16
|
+
*/
|
|
17
|
+
export class FastifyV4Adapter extends FastifyAdapter {
|
|
18
|
+
/**
|
|
19
|
+
* Align Gasket logger with Fastify v4 requirements.
|
|
20
|
+
* Ensures 'fatal' and 'trace' log levels exist.
|
|
21
|
+
* @param {object} logger - Gasket logger instance
|
|
22
|
+
* @returns {object} - Fastify-compatible logger
|
|
23
|
+
*/
|
|
24
|
+
alignLogger(logger) {
|
|
25
|
+
const fastifyLogger = logger;
|
|
26
|
+
['fatal', 'trace'].forEach(level => {
|
|
27
|
+
if (!logger[level]) {
|
|
28
|
+
fastifyLogger[level] = logger[fallbackMap[level]];
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return fastifyLogger;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a Fastify v4 instance.
|
|
36
|
+
* @param {object} config - Fastify configuration
|
|
37
|
+
* @param {object} logger - Gasket logger
|
|
38
|
+
* @returns {ReturnType<typeof import('fastify').default>} - Configured Fastify v4 instance
|
|
39
|
+
*/
|
|
40
|
+
createInstance(config, logger) {
|
|
41
|
+
const { trustProxy = false, disableRequestLogging = true, https, http2, ...restConfig } = config;
|
|
42
|
+
|
|
43
|
+
const fastifyLogger = this.alignLogger(logger);
|
|
44
|
+
|
|
45
|
+
// Fastify v4 uses 'logger' option
|
|
46
|
+
return fastify({
|
|
47
|
+
logger: fastifyLogger,
|
|
48
|
+
trustProxy,
|
|
49
|
+
disableRequestLogging,
|
|
50
|
+
https,
|
|
51
|
+
http2,
|
|
52
|
+
...restConfig
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fastify from 'fastify';
|
|
2
|
+
import { FastifyAdapter } from './base-adapter.js';
|
|
3
|
+
|
|
4
|
+
const fallbackMap = {
|
|
5
|
+
fatal: 'error',
|
|
6
|
+
trace: 'debug'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adapter for Fastify v5.x
|
|
11
|
+
*
|
|
12
|
+
* Key differences from v4:
|
|
13
|
+
* - Uses 'loggerInstance' option (not 'logger')
|
|
14
|
+
* - Adds 'useSemicolonDelimiter' option (defaults to true)
|
|
15
|
+
* - Requires Node.js v20+
|
|
16
|
+
* - Stricter JSON Schema validation
|
|
17
|
+
*/
|
|
18
|
+
export class FastifyV5Adapter extends FastifyAdapter {
|
|
19
|
+
/**
|
|
20
|
+
* Align Gasket logger with Fastify v5 requirements.
|
|
21
|
+
* Ensures 'fatal' and 'trace' log levels exist.
|
|
22
|
+
* @param {object} logger - Gasket logger instance
|
|
23
|
+
* @returns {object} - Fastify-compatible logger
|
|
24
|
+
*/
|
|
25
|
+
alignLogger(logger) {
|
|
26
|
+
const fastifyLogger = logger;
|
|
27
|
+
['fatal', 'trace'].forEach(level => {
|
|
28
|
+
if (!logger[level]) {
|
|
29
|
+
fastifyLogger[level] = logger[fallbackMap[level]];
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return fastifyLogger;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a Fastify v5 instance.
|
|
37
|
+
* @param {object} config - Fastify configuration
|
|
38
|
+
* @param {object} logger - Gasket logger
|
|
39
|
+
* @returns {ReturnType<typeof import('fastify').default>} - Configured Fastify v5 instance
|
|
40
|
+
*/
|
|
41
|
+
createInstance(config, logger) {
|
|
42
|
+
const {
|
|
43
|
+
trustProxy = false,
|
|
44
|
+
disableRequestLogging = true,
|
|
45
|
+
https,
|
|
46
|
+
http2,
|
|
47
|
+
useSemicolonDelimiter = true,
|
|
48
|
+
...restConfig
|
|
49
|
+
} = config;
|
|
50
|
+
|
|
51
|
+
const fastifyLogger = this.alignLogger(logger);
|
|
52
|
+
|
|
53
|
+
// Fastify v5 uses 'loggerInstance' instead of 'logger'
|
|
54
|
+
// Router options are nested under 'routerOptions' to avoid deprecation warnings
|
|
55
|
+
return fastify({
|
|
56
|
+
loggerInstance: fastifyLogger,
|
|
57
|
+
trustProxy,
|
|
58
|
+
disableRequestLogging,
|
|
59
|
+
https,
|
|
60
|
+
http2,
|
|
61
|
+
routerOptions: {
|
|
62
|
+
useSemicolonDelimiter
|
|
63
|
+
},
|
|
64
|
+
...restConfig
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1,29 +1,9 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
const fallbackMap = {
|
|
6
|
-
fatal: 'error',
|
|
7
|
-
trace: 'debug'
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A helper function to ensure that all the required log levels
|
|
12
|
-
* for a Fastify server are present.
|
|
13
|
-
* @type {import('@gasket/plugin-fastify').alignLogger}
|
|
14
|
-
*/
|
|
15
|
-
function alignLogger(logger) {
|
|
16
|
-
const fastifyLogger = logger;
|
|
17
|
-
['fatal', 'trace'].map(level => {
|
|
18
|
-
if (!logger[level]) {
|
|
19
|
-
fastifyLogger[level] = logger[fallbackMap[level]];
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return fastifyLogger;
|
|
24
|
-
}
|
|
3
|
+
import { createFastifyAdapter } from './adapters/index.js';
|
|
25
4
|
|
|
26
5
|
let instance = null;
|
|
6
|
+
let adapter = null;
|
|
27
7
|
|
|
28
8
|
/**
|
|
29
9
|
* Get the Fastify instance.
|
|
@@ -33,21 +13,29 @@ let instance = null;
|
|
|
33
13
|
export function getAppInstance(gasket) {
|
|
34
14
|
if (!instance) {
|
|
35
15
|
const { fastify: fastifyConfig = {}, http2, https } = gasket.config;
|
|
36
|
-
const { trustProxy = false, disableRequestLogging = true } = fastifyConfig;
|
|
37
|
-
const fastifyLogger = alignLogger(gasket.logger);
|
|
38
16
|
|
|
39
|
-
|
|
17
|
+
// Create the appropriate adapter for the installed Fastify version
|
|
18
|
+
adapter = createFastifyAdapter();
|
|
19
|
+
|
|
20
|
+
// Use the adapter to create the Fastify instance
|
|
21
|
+
instance = adapter.createInstance(
|
|
22
|
+
{
|
|
23
|
+
...fastifyConfig,
|
|
24
|
+
https,
|
|
25
|
+
http2
|
|
26
|
+
},
|
|
27
|
+
gasket.logger
|
|
28
|
+
);
|
|
40
29
|
}
|
|
41
30
|
|
|
42
31
|
return instance;
|
|
43
32
|
}
|
|
44
33
|
|
|
45
|
-
export { alignLogger };
|
|
46
|
-
|
|
47
34
|
/**
|
|
48
35
|
* Clear the Fastify app instance (for testing only)
|
|
49
36
|
* @returns {void}
|
|
50
37
|
*/
|
|
51
38
|
export function testClearAppInstance() {
|
|
52
39
|
instance = null;
|
|
40
|
+
adapter = null;
|
|
53
41
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gasket/plugin-fastify",
|
|
3
|
-
"version": "8.0.0-next.
|
|
3
|
+
"version": "8.0.0-next.2",
|
|
4
4
|
"description": "Adds fastify support to your application",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -29,13 +29,9 @@
|
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"bugs": "https://github.com/godaddy/gasket/issues",
|
|
31
31
|
"homepage": "https://github.com/godaddy/gasket/tree/main/packages/gasket-plugin-fastify",
|
|
32
|
-
"dependencies": {
|
|
33
|
-
"@fastify/express": "^3.0.0",
|
|
34
|
-
"fastify": "^4.29.1"
|
|
35
|
-
},
|
|
36
32
|
"devDependencies": {
|
|
37
33
|
"@types/connect": "^3.4.38",
|
|
38
|
-
"fastify": "^
|
|
34
|
+
"fastify": "^5.0.0",
|
|
39
35
|
"vitest": "^3.2.0",
|
|
40
36
|
"@gasket/core": "^8.0.0-next.1",
|
|
41
37
|
"@gasket/plugin-https": "^8.0.0-next.1",
|
|
@@ -44,7 +40,7 @@
|
|
|
44
40
|
"create-gasket-app": "^8.0.0-next.1"
|
|
45
41
|
},
|
|
46
42
|
"peerDependencies": {
|
|
47
|
-
"fastify": "^4.29.1"
|
|
43
|
+
"fastify": "^4.29.1 || ^5.0.0"
|
|
48
44
|
},
|
|
49
45
|
"scripts": {
|
|
50
46
|
"lint": "eslint .",
|