Repository: fastify/fastify
File: lib/schema-controller.js (JavaScript)

Code before:
  getValidatorCompiler () {
    return this.validatorCompiler || (this.parent && this.parent.getValidatorCompiler())
  }

  getSerializerCompiler () {
    return this.serializerCompiler || (this.parent && this.parent.getSerializerCompiler())
  }

  getSerializerBuilder () {
    return this.compilersFactory.buildSerializer || (this.parent && this.parent.getSerializerBuilder())
  }

  getValidatorBuilder () {
    return this.compilersFactory.buildValidator || (this.parent && this.parent.getValidatorBuilder())
  }

  /**
   * This method will be called when a validator must be setup.
   * Do not setup the compiler more than once
   * @param {object} serverOptions the fastify server options
   */
  setupValidator (serverOptions) {
    // WARNING: isCustomValidatorCompiler will be true if there is a custom builder OR if there is a custom compiler
    // installed directly via setValidatorCompiler, leading to this messy condition.  Compilers installed via
    // setValidatorCompiler will not be invalidated and recreated if schemas are added.
    const isReady = this.validatorCompiler !== undefined && (this.isCustomValidatorCompiler || !this.addedSchemas)
    if (isReady) {
      return
    }
    this.validatorCompiler = this.getValidatorBuilder()(this.schemaBucket.getSchemas(), serverOptions.ajv)
  }

  /**
   * This method will be called when a serializer must be setup.
   * Do not setup the compiler more than once
   * @param {object} serverOptions the fastify server options
   */
  setupSerializer (serverOptions) {
    const isReady = this.serializerCompiler !== undefined && !this.addedSchemas
    if (isReady) {
      return
    }

    this.serializerCompiler = this.getSerializerBuilder()(this.schemaBucket.getSchemas(), serverOptions.serializerOpts)
  }
}

SchemaController.buildSchemaController = buildSchemaController
module.exports = SchemaController


Review comment (suggestion):
> For your discussion: as a new user of the framework, I would have much preferred if `setSchemaValidator` didn't exist or was marked deprecated and bad, because it is unsafe and trying to use it wasted a bunch of time. If I had found the other mechanism was there (schema controller opts) then I would have just used that. Unfortunately sample code and google hits made me find the old ("easy" but also dangerous) mechanism and I didn't know it.

@Eomm is there any plan to drop this API in v5?

So far I believe it should be ok to do this; we just need to verify the risk is documented somewhere.

Code after:
    // The cloning of the compilersFactory object is necessary because
    // we are aliasing the parent compilersFactory if none was provided
    // to us (see constructor.)
    this.compilersFactory = Object.assign(
      {},
      this.compilersFactory,
      { buildValidator: () => validatorCompiler })
    this.validatorCompiler = validatorCompiler
    this.isCustomValidatorCompiler = true
  }

  setSerializerCompiler (serializerCompiler) {
    // Set up as if the fixed serializer compiler had been provided
    // by a custom 'options.compilersFactory.buildSerializer' that
    // always returns the same compiler object. This is required because:
    //
    // - setSerializerCompiler must immediately install a compiler to preserve
    //   legacy behavior
    // - setupSerializer will recreate compilers from builders in some
    //   circumstances, so we have to install this adapter to make it
    //   behave the same if the legacy API is used
    //
    // The cloning of the compilersFactory object is necessary because
    // we are aliasing the parent compilersFactory if none was provided
    // to us (see constructor.)
    this.compilersFactory = Object.assign(
      {},
      this.compilersFactory,
      { buildSerializer: () => serializerCompiler })
    this.serializerCompiler = serializerCompiler
    this.isCustomSerializerCompiler = true
  }

  getValidatorCompiler () {
    return this.validatorCompiler || (this.parent && this.parent.getValidatorCompiler())
  }

  getSerializerCompiler () {
    return this.serializerCompiler || (this.parent && this.parent.getSerializerCompiler())
  }

  getSerializerBuilder () {
    return this.compilersFactory.buildSerializer || (this.parent && this.parent.getSerializerBuilder())
  }

  getValidatorBuilder () {
    return this.compilersFactory.buildValidator || (this.parent && this.parent.getValidatorBuilder())
  }

  /**
   * This method will be called when a validator must be setup.