lepu-test-platform-web/node_modules/webpack-dev-server/lib/OptionsValidationError.js

153 lines
6.3 KiB
JavaScript

'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;