validator.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. 'use strict';
  2. import { VERSION } from '../env/data.js';
  3. import AxiosError from '../core/AxiosError.js';
  4. const validators = {};
  5. // eslint-disable-next-line func-names
  6. ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => {
  7. validators[type] = function validator(thing) {
  8. return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;
  9. };
  10. });
  11. const deprecatedWarnings = {};
  12. /**
  13. * Transitional option validator
  14. *
  15. * @param {function|boolean?} validator - set to false if the transitional option has been removed
  16. * @param {string?} version - deprecated version / removed since version
  17. * @param {string?} message - some message with additional info
  18. *
  19. * @returns {function}
  20. */
  21. validators.transitional = function transitional(validator, version, message) {
  22. function formatMessage(opt, desc) {
  23. return (
  24. '[Axios v' +
  25. VERSION +
  26. "] Transitional option '" +
  27. opt +
  28. "'" +
  29. desc +
  30. (message ? '. ' + message : '')
  31. );
  32. }
  33. // eslint-disable-next-line func-names
  34. return (value, opt, opts) => {
  35. if (validator === false) {
  36. throw new AxiosError(
  37. formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')),
  38. AxiosError.ERR_DEPRECATED
  39. );
  40. }
  41. if (version && !deprecatedWarnings[opt]) {
  42. deprecatedWarnings[opt] = true;
  43. // eslint-disable-next-line no-console
  44. console.warn(
  45. formatMessage(
  46. opt,
  47. ' has been deprecated since v' + version + ' and will be removed in the near future'
  48. )
  49. );
  50. }
  51. return validator ? validator(value, opt, opts) : true;
  52. };
  53. };
  54. validators.spelling = function spelling(correctSpelling) {
  55. return (value, opt) => {
  56. // eslint-disable-next-line no-console
  57. console.warn(`${opt} is likely a misspelling of ${correctSpelling}`);
  58. return true;
  59. };
  60. };
  61. /**
  62. * Assert object's properties type
  63. *
  64. * @param {object} options
  65. * @param {object} schema
  66. * @param {boolean?} allowUnknown
  67. *
  68. * @returns {object}
  69. */
  70. function assertOptions(options, schema, allowUnknown) {
  71. if (typeof options !== 'object') {
  72. throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);
  73. }
  74. const keys = Object.keys(options);
  75. let i = keys.length;
  76. while (i-- > 0) {
  77. const opt = keys[i];
  78. // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
  79. // a non-function validator and cause a TypeError. See GHSA-q8qp-cvcw-x6jj.
  80. const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
  81. if (validator) {
  82. const value = options[opt];
  83. const result = value === undefined || validator(value, opt, options);
  84. if (result !== true) {
  85. throw new AxiosError(
  86. 'option ' + opt + ' must be ' + result,
  87. AxiosError.ERR_BAD_OPTION_VALUE
  88. );
  89. }
  90. continue;
  91. }
  92. if (allowUnknown !== true) {
  93. throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION);
  94. }
  95. }
  96. }
  97. export default {
  98. assertOptions,
  99. validators,
  100. };