async function ajvFactory(
  /** @type {AjvFactoryOptions} */ {
    draftVersion,
    fullStrictMode = true,
    unknownFormats = [],
    unknownKeywords = [],
    unknownSchemas = [],
    options,
  },
) {
  let ajvOptions = {}
  Object.assign(
    ajvOptions,
    fullStrictMode
      ? {
          strict: true,
        }
      : {
          strictTypes: false, // recommended: true
          strictTuples: false, // recommended: true
          allowMatchingProperties: true, // recommended: false
        },
  )
  Object.assign(ajvOptions, options)

  let ajv
  switch (draftVersion) {
    case 'draft-04':
      ajv = new AjvDraft04(ajvOptions)
      addFormats(ajv)
      break
    case 'draft-06':
      ajv = new AjvDraft06And07(ajvOptions)
      ajv.addMetaSchema(AjvDraft06SchemaJson)
      addFormats(ajv)
      break
    case 'draft-07':
      /**
       * Note that draft-07 defines iri{,-reference}, idn-{hostname,email}, which
       * are not available through `addFormats`. So, use `ajvFormatsDraft2019` to
       * obtain these. Thus, some draft2019 formats like "duration" are applied.
       * See https://ajv.js.org/packages/ajv-formats.html for details.
       */
      ajv = new AjvDraft06And07(ajvOptions)
      addFormats(ajv)
      ajvFormatsDraft2019(ajv)
      break
    case '2019-09':
      ajv = new Ajv2019(ajvOptions)
      addFormats(ajv)
      ajvFormatsDraft2019(ajv)
      break
    case '2020-12':
      ajv = new Ajv2020(ajvOptions)
      addFormats(ajv)
      ajvFormatsDraft2019(ajv)
      break
    default:
      throw new Error('No JSON Schema version specified')
  }

  /**
   * In strict mode, Ajv will throw an error if it does not
   * recognize any non-standard formats. That is, unrecognized
   * values of the "format" field. Supply this information to
   * Ajv to prevent errors.
   */
  for (const format of unknownFormats) {
    ajv.addFormat(format, true)
  }

  /**
   * Ditto, but with keywords (ex. "x-intellij-html-description")..
   */
  for (const unknownKeyword of unknownKeywords.concat([
    'allowTrailingCommas',
    'defaultSnippets',
    'markdownDescription',
    'enumDescriptions',
    'markdownEnumDescriptions',
    'x-taplo',
    'x-taplo-info',
    'x-tombi-toml-version',
    'x-tombi-array-values-order',
    'x-tombi-table-keys-order',
    'x-intellij-language-injection',
    'x-intellij-html-description',
    'x-intellij-enum-metadata',
  ])) {
    ajv.addKeyword(unknownKeyword)
  }

  /**
   * Ditto, but with "$ref" URIs to external schemas.
   */
  for (const schemaPath of unknownSchemas) {
    ajv.addSchema(await readJsonFile(schemaPath))
  }

  return ajv
}
Returns the correct and configured Ajv instance for a particular $schema version