Aktueller Stand

This commit is contained in:
2026-01-22 19:05:45 +01:00
parent 85dee61a4d
commit e280e4eadb
1967 changed files with 397327 additions and 74093 deletions

View File

@@ -0,0 +1,2 @@
# Set default behavior to automatically convert line endings
* text=auto eol=lf

View File

@@ -9,5 +9,5 @@ updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
interval: "monthly"
open-pull-requests-limit: 10

View File

@@ -2,6 +2,10 @@ name: CI
on:
push:
branches:
- main
- next
- 'v*'
paths-ignore:
- 'docs/**'
- '*.md'
@@ -10,9 +14,15 @@ on:
- 'docs/**'
- '*.md'
permissions:
contents: read
jobs:
test:
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
permissions:
contents: write
pull-requests: write
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
with:
license-check: true
lint: true

View File

@@ -1,11 +1,12 @@
# @fastify/fast-json-stringify-compiler
Build and manage the [`fast-json-stringify`](https://www.npmjs.com/package/fast-json-stringify) instances for the fastify framework.
[![CI](https://github.com/fastify/fast-json-stringify-compiler/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/fast-json-stringify-compiler/actions/workflows/ci.yml)
[![NPM version](https://img.shields.io/npm/v/@fastify/fast-json-stringify-compiler.svg?style=flat)](https://www.npmjs.com/package/@fastify/fast-json-stringify-compiler)
[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)
Build and manage the [`fast-json-stringify`](https://www.npmjs.com/package/fast-json-stringify) instances for the Fastify framework.
This package is responsible for compiling the application's `response` JSON schemas into optimized functions to speed up the response time.
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
[![Continuous Integration](https://github.com/fastify/fast-json-stringify-compiler/workflows/Continuous%20Integration/badge.svg)](https://github.com/fastify/fast-json-stringify-compiler/actions/workflows/ci.yml)
## Versions
| `@fastify/fast-json-stringify-compiler` | `fast-json-stringify` | Supported `fastify` |
@@ -13,22 +14,22 @@ This package is responsible for compiling the application's `response` JSON sche
| v1.x | v3.x | ^3.x |
| v2.x | v3.x | ^4.x |
| v3.x | v4.x | ^4.x |
| v4.x | v5.x | ^4.x |
| v4.x | v5.x | ^5.x |
### fast-json-stringify Configuration
The `fast-json-stringify` configuration is the default one. You can check it the default settings in the [`fast-json-stringify` option](https://github.com/fastify/fast-json-stringify/#options) documentation.
The `fast-json-stringify` configuration is the default one. You can check the default settings in the [`fast-json-stringify` option](https://github.com/fastify/fast-json-stringify/#options) documentation.
You can also override the default configuration by passing the [`serializerOpts`](https://www.fastify.io/docs/latest/Reference/Server/#serializeropts) configuration to the Fastify instance.
You can also override the default configuration by passing the [`serializerOpts`](https://fastify.dev/docs/latest/Reference/Server/#serializeropts) configuration to the Fastify instance.
## Usage
This module is already used as default by Fastify.
If you need to provide to your server instance a different version, refer to [the official doc](https://www.fastify.io/docs/latest/Reference/Server/#schemacontroller).
If you need to provide to your server instance a different version, refer to [the official doc](https://fastify.dev/docs/latest/Reference/Server/#schemacontroller).
### fast-json-stringify Standalone
`fast-json-stringify@v4.1.0` introduces the [standalone feature](https://github.com/fastify/fast-json-stringify#standalone) that let you to pre-compile your schemas and use them in your application for a faster startup.
`fast-json-stringify@v4.1.0` introduces the [standalone feature](https://github.com/fastify/fast-json-stringify#standalone) that lets you pre-compile your schemas and use them in your application for a faster startup.
To use this feature, you must be aware of the following:
@@ -43,7 +44,7 @@ To accomplish this, you must use a new compiler: `@fastify/fast-json-stringify-c
You must provide 2 parameters to this compiler:
- `readMode: false`: a boolean to indicate that you want generate the schemas functions string.
- `readMode: false`: a boolean to indicate that you want to generate the schemas functions string.
- `storeFunction`" a sync function that must store the source code of the schemas functions. You may provide an async function too, but you must manage errors.
When `readMode: false`, **the compiler is meant to be used in development ONLY**.
@@ -84,7 +85,7 @@ app.ready().then(() => {
At this stage, you should have a file for every route's schema.
To use them, you must use the `@fastify/fast-json-stringify-compiler/standalone` with the parameters:
- `readMode: true`: a boolean to indicate that you want read and use the schemas functions string.
- `readMode: true`: a boolean to indicate that you want to read and use the schemas functions string.
- `restoreFunction`" a sync function that must return a function to serialize the route's payload.
Important keep away before you continue reading the documentation:
@@ -120,7 +121,7 @@ app.listen({ port: 3000 })
### How it works
This module provide a factory function to produce [Serializer Compilers](https://www.fastify.io/docs/latest/Reference/Server/#serializercompiler) functions.
This module provides a factory function to produce [Serializer Compilers](https://fastify.dev/docs/latest/Reference/Server/#serializercompiler) functions.
## License

View File

@@ -0,0 +1,6 @@
'use strict'
module.exports = require('neostandard')({
ignores: require('neostandard').resolveIgnoresFromGitignore(),
ts: true
})

View File

@@ -1,23 +1,8 @@
'use strict'
const fastJsonStringify = require('fast-json-stringify')
function SerializerSelector () {
return function buildSerializerFactory (externalSchemas, serializerOpts) {
const fjsOpts = Object.assign({}, serializerOpts, { schema: externalSchemas })
return responseSchemaCompiler.bind(null, fjsOpts)
}
}
function responseSchemaCompiler (fjsOpts, { schema /* method, url, httpStatus */ }) {
if (fjsOpts.schema && schema.$id && fjsOpts.schema[schema.$id]) {
fjsOpts.schema = { ...fjsOpts.schema }
delete fjsOpts.schema[schema.$id]
}
return fastJsonStringify(schema, fjsOpts)
}
const { SerializerSelector, StandaloneSerializer } = require('./standalone')
module.exports = SerializerSelector
module.exports.default = SerializerSelector
module.exports.SerializerSelector = SerializerSelector
module.exports.StandaloneSerializer = require('./standalone')
module.exports.StandaloneSerializer = StandaloneSerializer

View File

@@ -1,13 +1,14 @@
{
"name": "@fastify/fast-json-stringify-compiler",
"description": "Build and manage the fast-json-stringify instances for the fastify framework",
"version": "4.3.0",
"version": "5.0.3",
"main": "index.js",
"type": "commonjs",
"types": "types/index.d.ts",
"scripts": {
"lint": "standard",
"lint:fix": "standard --fix",
"unit": "tap test/**/*.test.js",
"lint": "eslint",
"lint:fix": "eslint --fix",
"unit": "c8 --100 node --test",
"test": "npm run unit && npm run test:typescript",
"test:typescript": "tsd"
},
@@ -17,24 +18,54 @@
},
"keywords": [],
"author": "Manuel Spigolon <manuel.spigolon@nearform.com> (https://github.com/Eomm)",
"contributors": [
{
"name": "Matteo Collina",
"email": "hello@matteocollina.com"
},
{
"name": "Aras Abbasi",
"email": "aras.abbasi@gmail.com"
},
{
"name": "James Sumners",
"url": "https://james.sumners.info"
},
{
"name": "Frazer Smith",
"email": "frazer.dev@icloud.com",
"url": "https://github.com/fdawgs"
}
],
"license": "MIT",
"bugs": {
"url": "https://github.com/fastify/fast-json-stringify-compiler/issues"
},
"homepage": "https://github.com/fastify/fast-json-stringify-compiler#readme",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"devDependencies": {
"@fastify/pre-commit": "^2.0.2",
"fastify": "^4.0.0",
"@fastify/pre-commit": "^2.1.0",
"c8": "^10.1.3",
"eslint": "^9.17.0",
"fastify": "^5.0.0",
"neostandard": "^0.12.0",
"sanitize-filename": "^1.6.3",
"standard": "^17.0.0",
"tap": "^16.0.0",
"tsd": "^0.28.0"
"tsd": "^0.31.0"
},
"pre-commit": [
"lint",
"test"
],
"dependencies": {
"fast-json-stringify": "^5.7.0"
"fast-json-stringify": "^6.0.0"
}
}

View File

@@ -1,6 +1,21 @@
'use strict'
const SerializerSelector = require('./index')
const fastJsonStringify = require('fast-json-stringify')
function SerializerSelector () {
return function buildSerializerFactory (externalSchemas, serializerOpts) {
const fjsOpts = Object.assign({}, serializerOpts, { schema: externalSchemas })
return responseSchemaCompiler.bind(null, fjsOpts)
}
}
function responseSchemaCompiler (fjsOpts, { schema /* method, url, httpStatus */ }) {
if (fjsOpts.schema && schema.$id && fjsOpts.schema[schema.$id]) {
fjsOpts.schema = { ...fjsOpts.schema }
delete fjsOpts.schema[schema.$id]
}
return fastJsonStringify(schema, fjsOpts)
}
function StandaloneSerializer (options = { readMode: true }) {
if (options.readMode === true && typeof options.restoreFunction !== 'function') {
@@ -38,5 +53,6 @@ function StandaloneSerializer (options = { readMode: true }) {
}
}
module.exports = StandaloneSerializer
module.exports.SerializerSelector = SerializerSelector
module.exports.StandaloneSerializer = StandaloneSerializer
module.exports.default = StandaloneSerializer

View File

@@ -1,9 +1,9 @@
'use strict'
const t = require('tap')
const { test } = require('node:test')
const FjsCompiler = require('../index')
t.test('Use input schema duplicate in the externalSchemas', async t => {
test('Use input schema duplicate in the externalSchemas', async t => {
t.plan(1)
const externalSchemas = {
schema1: {
@@ -22,5 +22,5 @@ t.test('Use input schema duplicate in the externalSchemas', async t => {
compiler({ schema: externalSchemas.schema1 })
compiler({ schema: externalSchemas.schema2 })
t.pass()
t.assert.ok(true)
})

View File

@@ -1,10 +1,10 @@
'use strict'
const t = require('tap')
const { test } = require('node:test')
const fastify = require('fastify')
const FjsCompiler = require('../index')
const echo = async (req, reply) => { return req.body }
const echo = async (req) => { return req.body }
const sampleSchema = Object.freeze({
$id: 'example1',
@@ -27,16 +27,16 @@ const externalSchemas2 = Object.freeze({
const fastifyFjsOptionsDefault = Object.freeze({})
t.test('basic usage', t => {
test('basic usage', t => {
t.plan(1)
const factory = FjsCompiler()
const compiler = factory(externalSchemas1, fastifyFjsOptionsDefault)
const serializeFunc = compiler({ schema: sampleSchema })
const result = serializeFunc({ name: 'hello' })
t.equal(result, '{"name":"hello"}')
t.assert.equal(result, '{"name":"hello"}')
})
t.test('fastify integration', async t => {
test('fastify integration', async t => {
const factory = FjsCompiler()
const app = fastify({
@@ -73,6 +73,6 @@ t.test('fastify integration', async t => {
}
})
t.equal(res.statusCode, 200)
t.same(res.json(), { name: 'serialize me' })
t.assert.equal(res.statusCode, 200)
t.assert.deepStrictEqual(res.json(), { name: 'serialize me' })
})

View File

@@ -1,8 +1,8 @@
'use strict'
const fs = require('fs')
const path = require('path')
const t = require('tap')
const fs = require('node:fs')
const path = require('node:path')
const { test } = require('node:test')
const fastify = require('fastify')
const sanitize = require('sanitize-filename')
@@ -16,23 +16,23 @@ function generateFileName (routeOpts) {
return fileName
}
t.test('standalone', t => {
test('standalone', async t => {
t.plan(5)
t.teardown(async () => {
t.after(async () => {
for (const fileName of generatedFileNames) {
try {
await fs.promises.unlink(path.join(__dirname, fileName))
} catch (e) {}
} catch {}
}
})
t.test('errors', t => {
t.plan(2)
t.throws(() => {
t.assert.throws(() => {
FjsStandaloneCompiler()
}, 'missing restoreFunction')
t.throws(() => {
t.assert.throws(() => {
FjsStandaloneCompiler({ readMode: false })
}, 'missing storeFunction')
})
@@ -74,28 +74,28 @@ t.test('standalone', t => {
const factory = FjsStandaloneCompiler({
readMode: false,
storeFunction (routeOpts, schemaSerializerCode) {
t.same(routeOpts, endpointSchema)
t.type(schemaSerializerCode, 'string')
t.assert.deepStrictEqual(routeOpts, endpointSchema)
t.assert.ok(typeof schemaSerializerCode === 'string')
fs.writeFileSync(path.join(__dirname, '/fjs-generated.js'), schemaSerializerCode)
generatedFileNames.push('/fjs-generated.js')
t.pass('stored the serializer function')
t.assert.ok('stored the serializer function')
}
})
const compiler = factory(schemaMap)
compiler(endpointSchema)
t.pass('compiled the endpoint schema')
t.assert.ok('compiled the endpoint schema')
t.test('usage standalone code', t => {
t.plan(3)
const standaloneSerializer = require('./fjs-generated')
t.ok(standaloneSerializer)
t.assert.ok(standaloneSerializer)
const valid = standaloneSerializer({ hello: 'world' })
t.same(valid, JSON.stringify({ hello: 'world' }))
t.assert.deepStrictEqual(valid, JSON.stringify({ hello: 'world' }))
const invalid = standaloneSerializer({ hello: [] })
t.same(invalid, '{"hello":""}')
t.assert.deepStrictEqual(invalid, '{"hello":""}')
})
})
@@ -106,9 +106,9 @@ t.test('standalone', t => {
readMode: false,
storeFunction (routeOpts, schemaSerializationCode) {
const fileName = generateFileName(routeOpts)
t.ok(routeOpts)
t.assert.ok(routeOpts)
fs.writeFileSync(path.join(__dirname, fileName), schemaSerializationCode)
t.pass(`stored the serializer function ${fileName}`)
t.assert.ok(`stored the serializer function ${fileName}`)
},
restoreFunction () {
t.fail('write mode ON')
@@ -119,16 +119,16 @@ t.test('standalone', t => {
await app.ready()
})
t.test('fastify integration - writeMode forces standalone', async t => {
await t.test('fastify integration - writeMode forces standalone', async t => {
t.plan(4)
const factory = FjsStandaloneCompiler({
readMode: false,
storeFunction (routeOpts, schemaSerializationCode) {
const fileName = generateFileName(routeOpts)
t.ok(routeOpts)
t.assert.ok(routeOpts)
fs.writeFileSync(path.join(__dirname, fileName), schemaSerializationCode)
t.pass(`stored the serializer function ${fileName}`)
t.assert.ok(`stored the serializer function ${fileName}`)
},
restoreFunction () {
t.fail('write mode ON')
@@ -143,7 +143,7 @@ t.test('standalone', t => {
await app.ready()
})
t.test('fastify integration - readMode', async t => {
await t.test('fastify integration - readMode', async t => {
t.plan(6)
const factory = FjsStandaloneCompiler({
@@ -153,7 +153,7 @@ t.test('standalone', t => {
},
restoreFunction (routeOpts) {
const fileName = generateFileName(routeOpts)
t.pass(`restore the serializer function ${fileName}}`)
t.assert.ok(`restore the serializer function ${fileName}}`)
return require(path.join(__dirname, fileName))
}
})
@@ -165,15 +165,15 @@ t.test('standalone', t => {
url: '/foo',
method: 'POST'
})
t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify({ hello: 'world' }))
t.assert.equal(res.statusCode, 200)
t.assert.equal(res.payload, JSON.stringify({ hello: 'world' }))
res = await app.inject({
url: '/bar?lang=it',
method: 'GET'
})
t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify({ lang: 'en' }))
t.assert.equal(res.statusCode, 200)
t.assert.equal(res.payload, JSON.stringify({ lang: 'en' }))
})
function buildApp (factory, serializerOpts) {

View File

@@ -6,13 +6,9 @@ declare namespace SerializerSelector {
export type SerializerFactory = (
externalSchemas?: unknown,
options?: Options
) => SerializerCompiler;
export type SerializerCompiler = (
externalSchemas?: unknown,
options?: Options
) => Serializer;
) => SerializerCompiler
export type SerializerCompiler = (routeDef: RouteDefinition) => Serializer
export type Serializer = (doc: any) => string
export type RouteDefinition = {
@@ -35,11 +31,11 @@ declare namespace SerializerSelector {
}
export type { Options }
export const SerializerSelector: FastJsonStringifyFactory;
export function StandaloneSerializer(options: StandaloneOptions): SerializerFactory;
export const SerializerSelector: FastJsonStringifyFactory
export function StandaloneSerializer (options: StandaloneOptions): SerializerFactory
export { SerializerSelector as default }
}
declare function SerializerSelector(...params: Parameters<FastJsonStringifyFactory>): ReturnType<FastJsonStringifyFactory>
declare function SerializerSelector (...params: Parameters<FastJsonStringifyFactory>): ReturnType<FastJsonStringifyFactory>
export = SerializerSelector

View File

@@ -1,4 +1,4 @@
import { expectAssignable, expectError, expectType } from "tsd";
import { expectAssignable, expectError, expectType } from 'tsd'
import SerializerSelector, {
RouteDefinition,
Serializer,
@@ -6,43 +6,41 @@ import SerializerSelector, {
SerializerFactory,
SerializerSelector as SerializerSelectorNamed,
StandaloneSerializer,
} from "..";
} from '..'
/**
* SerializerSelector
*/
{
const compiler = SerializerSelector();
expectType<SerializerFactory>(compiler);
const compiler = SerializerSelector()
expectType<SerializerFactory>(compiler)
}
{
const compiler = SerializerSelectorNamed();
expectType<SerializerFactory>(compiler);
const compiler = SerializerSelectorNamed()
expectType<SerializerFactory>(compiler)
}
{
{
const sampleSchema = {
$id: 'example1',
type: 'object',
properties: {
name: { type: 'string' }
}
const sampleSchema = {
$id: 'example1',
type: 'object',
properties: {
name: { type: 'string' }
}
const externalSchemas1 = {}
const factory = SerializerSelector()
expectType<SerializerFactory>(factory);
const compiler = factory(externalSchemas1, {})
expectType<SerializerCompiler>(compiler);
const serializeFunc = compiler({ schema: sampleSchema })
expectType<Serializer>(serializeFunc);
expectType<string>(serializeFunc({ name: 'hello' }))
}
const externalSchemas1 = {}
const factory = SerializerSelector()
expectType<SerializerFactory>(factory)
const compiler = factory(externalSchemas1, {})
expectType<SerializerCompiler>(compiler)
const serializeFunc = compiler({ schema: sampleSchema, method: '', url: '', httpStatus: '' })
expectType<Serializer>(serializeFunc)
expectType<string>(serializeFunc({ name: 'hello' }))
}
/**
@@ -55,8 +53,8 @@ const reader = StandaloneSerializer({
expectAssignable<RouteDefinition>(route)
return {} as Serializer
},
});
expectType<SerializerFactory>(reader);
})
expectType<SerializerFactory>(reader)
const writer = StandaloneSerializer({
readMode: false,
@@ -64,8 +62,8 @@ const writer = StandaloneSerializer({
expectAssignable<RouteDefinition>(route)
expectAssignable<string>(code)
},
});
expectType<SerializerFactory>(writer);
})
expectType<SerializerFactory>(writer)
{
const base = {
@@ -88,6 +86,9 @@ expectType<SerializerFactory>(writer);
}
const endpointSchema = {
method: '',
url: '',
httpStatus: '',
schema: {
$id: 'urn:schema:endpoint',
$ref: 'urn:schema:ref'