| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | 'use strict';/* eslint no-param-reassign: 'off' */const optionsSchema = require('./optionsSchema.json');const indent = (str, prefix, firstLine) => {  if (firstLine) {    return prefix + str.replace(/\n(?!$)/g, `\n${prefix}`);  }  return str.replace(/\n(?!$)/g, `\n${prefix}`);};const getSchemaPart = (path, parents, additionalPath) => {  parents = parents || 0;  path = path.split('/');  path = path.slice(0, path.length - parents);  if (additionalPath) {    additionalPath = additionalPath.split('/');    path = path.concat(additionalPath);  }  let schemaPart = optionsSchema;  for (let i = 1; i < path.length; i++) {    const inner = schemaPart[path[i]];    if (inner) { schemaPart = inner; }  }  return schemaPart;};const getSchemaPartText = (schemaPart, additionalPath) => {  if (additionalPath) {    for (let i = 0; i < additionalPath.length; i++) {      const inner = schemaPart[additionalPath[i]];      if (inner) { schemaPart = inner; }    }  }  while (schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref);  let schemaText = OptionsValidationError.formatSchema(schemaPart); // eslint-disable-line  if (schemaPart.description) { schemaText += `\n${schemaPart.description}`; }  return schemaText;};class OptionsValidationError extends Error {  constructor(validationErrors) {    super();    if (Error.hasOwnProperty('captureStackTrace')) { // eslint-disable-line      Error.captureStackTrace(this, this.constructor);    }    this.name = 'WebpackDevServerOptionsValidationError';    this.message = `${'Invalid configuration object. ' +   'webpack-dev-server has been initialised using a configuration object that does not match the API schema.\n'}${      validationErrors.map(err => ` - ${indent(OptionsValidationError.formatValidationError(err), '   ', false)}`).join('\n')}`;    this.validationErrors = validationErrors;  }  static formatSchema(schema, prevSchemas) {    prevSchemas = prevSchemas || [];    const formatInnerSchema = (innerSchema, addSelf) => {      if (!addSelf) return OptionsValidationError.formatSchema(innerSchema, prevSchemas);      if (prevSchemas.indexOf(innerSchema) >= 0) return '(recursive)';      return OptionsValidationError.formatSchema(innerSchema, prevSchemas.concat(schema));    };    if (schema.type === 'string') {      if (schema.minLength === 1) { return 'non-empty string'; } else if (schema.minLength > 1) { return `string (min length ${schema.minLength})`; }      return 'string';    } else if (schema.type === 'boolean') {      return 'boolean';    } else if (schema.type === 'number') {      return 'number';    } else if (schema.type === 'object') {      if (schema.properties) {        const required = schema.required || [];        return `object { ${Object.keys(schema.properties).map((property) => {          if (required.indexOf(property) < 0) return `${property}?`;          return property;        }).concat(schema.additionalProperties ? ['...'] : []).join(', ')} }`;      }      if (schema.additionalProperties) {        return `object { <key>: ${formatInnerSchema(schema.additionalProperties)} }`;      }      return 'object';    } else if (schema.type === 'array') {      return `[${formatInnerSchema(schema.items)}]`;    }    switch (schema.instanceof) {      case 'Function':        return 'function';      case 'RegExp':        return 'RegExp';      default:    }    if (schema.$ref) return formatInnerSchema(getSchemaPart(schema.$ref), true);    if (schema.allOf) return schema.allOf.map(formatInnerSchema).join(' & ');    if (schema.oneOf) return schema.oneOf.map(formatInnerSchema).join(' | ');    if (schema.anyOf) return schema.anyOf.map(formatInnerSchema).join(' | ');    if (schema.enum) return schema.enum.map(item => JSON.stringify(item)).join(' | ');    return JSON.stringify(schema, 0, 2);  }  static formatValidationError(err) {    const dataPath = `configuration${err.dataPath}`;    if (err.keyword === 'additionalProperties') {      return `${dataPath} has an unknown property '${err.params.additionalProperty}'. These properties are valid:\n${getSchemaPartText(err.parentSchema)}`;    } else if (err.keyword === 'oneOf' || err.keyword === 'anyOf') {      if (err.children && err.children.length > 0) {        return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}\n` +     `Details:\n${err.children.map(e => ` * ${indent(OptionsValidationError.formatValidationError(e), '   ', false)}`).join('\n')}`;      }      return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`;    } else if (err.keyword === 'enum') {      if (err.parentSchema && err.parentSchema.enum && err.parentSchema.enum.length === 1) {        return `${dataPath} should be ${getSchemaPartText(err.parentSchema)}`;      }      return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`;    } else if (err.keyword === 'allOf') {      return `${dataPath} should be:\n${getSchemaPartText(err.parentSchema)}`;    } else if (err.keyword === 'type') {      switch (err.params.type) {        case 'object':          return `${dataPath} should be an object.`;        case 'string':          return `${dataPath} should be a string.`;        case 'boolean':          return `${dataPath} should be a boolean.`;        case 'number':          return `${dataPath} should be a number.`;        case 'array':          return `${dataPath} should be an array:\n${getSchemaPartText(err.parentSchema)}`;        default:      }      return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText(err.parentSchema)}`;    } else if (err.keyword === 'instanceof') {      return `${dataPath} should be an instance of ${getSchemaPartText(err.parentSchema)}.`;    } else if (err.keyword === 'required') {      const missingProperty = err.params.missingProperty.replace(/^\./, '');      return `${dataPath} misses the property '${missingProperty}'.\n${getSchemaPartText(err.parentSchema, ['properties', missingProperty])}`;    } else if (err.keyword === 'minLength' || err.keyword === 'minItems') {      if (err.params.limit === 1) { return `${dataPath} should not be empty.`; }      return `${dataPath} ${err.message}`;    }    // eslint-disable-line no-fallthrough    return `${dataPath} ${err.message} (${JSON.stringify(err, 0, 2)}).\n${getSchemaPartText(err.parentSchema)}`;  }}module.exports = OptionsValidationError;
 |