diff --git a/standalone.js b/standalone.js index 7f0d40a..f4b6066 100644 --- a/standalone.js +++ b/standalone.js @@ -5,7 +5,28 @@ 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) + const cache = new WeakMap() + + return function responseSchemaCompilerWithCache (opts) { + const { schema } = opts + const isObject = typeof schema === 'object' && schema !== null + + if (isObject) { + const serializer = cache.get(schema) + + if (serializer !== undefined) { + return serializer + } + } + + const serializer = responseSchemaCompiler(fjsOpts, opts) + + if (isObject) { + cache.set(schema, serializer) + } + + return serializer + } } } diff --git a/test/duplicate-schema.test.js b/test/duplicate-schema.test.js index 2acaa24..ebb1dea 100644 --- a/test/duplicate-schema.test.js +++ b/test/duplicate-schema.test.js @@ -3,24 +3,82 @@ const { test } = require('node:test') const FjsCompiler = require('../index') -test('Use input schema duplicate in the externalSchemas', async t => { - t.plan(1) +test('reuse compiled serializer for the same schema object', t => { + const schema = { + type: 'object', + properties: { + value: { type: 'string' } + } + } + + const factory = FjsCompiler() + const compiler = factory({}) + + const first = compiler({ schema }) + const second = compiler({ schema }) + + t.assert.strictEqual(first, second) +}) + +test('compile different schema objects independently', t => { + const factory = FjsCompiler() + const compiler = factory({}) + + const first = compiler({ schema: { type: 'string' } }) + const second = compiler({ schema: { type: 'number' } }) + + t.assert.notStrictEqual(first, second) +}) + +test('isolate caches between selector instances', t => { + const schema = { type: 'string' } + + const firstCompiler = FjsCompiler()({}) + const secondCompiler = FjsCompiler()({}) + + const first = firstCompiler({ schema }) + const second = secondCompiler({ schema }) + + t.assert.notStrictEqual(first, second) +}) + +test('handle schema duplicated in externalSchemas', t => { + const schema = { + $id: 'schema1', + type: 'number' + } + const externalSchemas = { - schema1: { - $id: 'schema1', - type: 'number' - }, + schema1: schema, schema2: { $id: 'schema2', type: 'string' } } - const factory = FjsCompiler() - const compiler = factory(externalSchemas) + const compiler = FjsCompiler()(externalSchemas) + const serializer = compiler({ schema }) + + t.assert.strictEqual(serializer(42), '42') +}) + +test('isolate caches between factory instances', t => { + const schema = { type: 'string' } + const selector = FjsCompiler() + + const firstCompiler = selector({}) + const secondCompiler = selector({}) + + const first = firstCompiler({ schema }) + const second = secondCompiler({ schema }) + + t.assert.notStrictEqual(first, second) +}) + +test('handle boolean schemas', t => { + const compiler = FjsCompiler()({}) - compiler({ schema: externalSchemas.schema1 }) - compiler({ schema: externalSchemas.schema2 }) + const serializer = compiler({ schema: false }) - t.assert.ok(true) + t.assert.strictEqual(typeof serializer, 'function') })