strong-tie/inbound-calls
0
1'use strict'2 3const { buildSchemas } = require('./schemas')4const SerializerSelector = require('@fastify/fast-json-stringify-compiler')5const ValidatorSelector = require('@fastify/ajv-compiler')6 7/**8 * Called at every fastify context that is being created.9 * @param {object} parentSchemaCtrl: the SchemaController instance of the Fastify parent context10 * @param {object} opts: the `schemaController` server option. It can be undefined when a parentSchemaCtrl is set11 * @return {object}:a new SchemaController12 */13function buildSchemaController (parentSchemaCtrl, opts) {14 if (parentSchemaCtrl) {15 return new SchemaController(parentSchemaCtrl, opts)16 }17 18 const compilersFactory = Object.assign({19 buildValidator: null,20 buildSerializer: null21 }, opts?.compilersFactory)22 23 if (!compilersFactory.buildValidator) {24 compilersFactory.buildValidator = ValidatorSelector()25 }26 if (!compilersFactory.buildSerializer) {27 compilersFactory.buildSerializer = SerializerSelector()28 }29 30 const option = {31 bucket: (opts && opts.bucket) || buildSchemas,32 compilersFactory,33 isCustomValidatorCompiler: typeof opts?.compilersFactory?.buildValidator === 'function',34 isCustomSerializerCompiler: typeof opts?.compilersFactory?.buildValidator === 'function'35 }36 37 return new SchemaController(undefined, option)38}39 40class SchemaController {41 constructor (parent, options) {42 this.opts = options || parent?.opts43 this.addedSchemas = false44 45 this.compilersFactory = this.opts.compilersFactory46 47 if (parent) {48 this.schemaBucket = this.opts.bucket(parent.getSchemas())49 this.validatorCompiler = parent.getValidatorCompiler()50 this.serializerCompiler = parent.getSerializerCompiler()51 this.isCustomValidatorCompiler = parent.isCustomValidatorCompiler52 this.isCustomSerializerCompiler = parent.isCustomSerializerCompiler53 this.parent = parent54 } else {55 this.schemaBucket = this.opts.bucket()56 this.isCustomValidatorCompiler = this.opts.isCustomValidatorCompiler || false57 this.isCustomSerializerCompiler = this.opts.isCustomSerializerCompiler || false58 }59 }60 61 // Bucket interface62 add (schema) {63 this.addedSchemas = true64 return this.schemaBucket.add(schema)65 }66 67 getSchema (schemaId) {68 return this.schemaBucket.getSchema(schemaId)69 }70 71 getSchemas () {72 return this.schemaBucket.getSchemas()73 }74 75 setValidatorCompiler (validatorCompiler) {76 // Set up as if the fixed validator compiler had been provided77 // by a custom 'options.compilersFactory.buildValidator' that78 // always returns the same compiler object. This is required because:79 //80 // - setValidatorCompiler must immediately install a compiler to preserve81 // legacy behavior82 // - setupValidator will recreate compilers from builders in some83 // circumstances, so we have to install this adapter to make it84 // behave the same if the legacy API is used85 //86 // The cloning of the compilersFactory object is necessary because87 // we are aliasing the parent compilersFactory if none was provided88 // to us (see constructor.)89 this.compilersFactory = Object.assign(90 {},91 this.compilersFactory,92 { buildValidator: () => validatorCompiler })93 this.validatorCompiler = validatorCompiler94 this.isCustomValidatorCompiler = true95 }96 97 setSerializerCompiler (serializerCompiler) {98 // Set up as if the fixed serializer compiler had been provided99 // by a custom 'options.compilersFactory.buildSerializer' that100 // always returns the same compiler object. This is required because:101 //102 // - setSerializerCompiler must immediately install a compiler to preserve103 // legacy behavior104 // - setupSerializer will recreate compilers from builders in some105 // circumstances, so we have to install this adapter to make it106 // behave the same if the legacy API is used107 //108 // The cloning of the compilersFactory object is necessary because109 // we are aliasing the parent compilersFactory if none was provided110 // to us (see constructor.)111 this.compilersFactory = Object.assign(112 {},113 this.compilersFactory,114 { buildSerializer: () => serializerCompiler })115 this.serializerCompiler = serializerCompiler116 this.isCustomSerializerCompiler = true117 }118 119 getValidatorCompiler () {120 return this.validatorCompiler || (this.parent && this.parent.getValidatorCompiler())121 }122 123 getSerializerCompiler () {124 return this.serializerCompiler || (this.parent && this.parent.getSerializerCompiler())125 }126 127 getSerializerBuilder () {128 return this.compilersFactory.buildSerializer || (this.parent && this.parent.getSerializerBuilder())129 }130 131 getValidatorBuilder () {132 return this.compilersFactory.buildValidator || (this.parent && this.parent.getValidatorBuilder())133 }134 135 /**136 * This method will be called when a validator must be setup.137 * Do not setup the compiler more than once138 * @param {object} serverOptions the fastify server options139 */140 setupValidator (serverOptions) {141 const isReady = this.validatorCompiler !== undefined && !this.addedSchemas142 if (isReady) {143 return144 }145 this.validatorCompiler = this.getValidatorBuilder()(this.schemaBucket.getSchemas(), serverOptions.ajv)146 }147 148 /**149 * This method will be called when a serializer must be setup.150 * Do not setup the compiler more than once151 * @param {object} serverOptions the fastify server options152 */153 setupSerializer (serverOptions) {154 const isReady = this.serializerCompiler !== undefined && !this.addedSchemas155 if (isReady) {156 return157 }158 159 this.serializerCompiler = this.getSerializerBuilder()(this.schemaBucket.getSchemas(), serverOptions.serializerOpts)160 }161}162 163SchemaController.buildSchemaController = buildSchemaController164module.exports = SchemaController165 