index.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. 'use strict'
  2. function isArguments (thingy) {
  3. return typeof thingy === 'object' && thingy.hasOwnProperty('callee')
  4. }
  5. var types = {
  6. '*': ['any', function () { return true }],
  7. A: ['array', function (thingy) { return Array.isArray(thingy) || isArguments(thingy) }],
  8. S: ['string', function (thingy) { return typeof thingy === 'string' }],
  9. N: ['number', function (thingy) { return typeof thingy === 'number' }],
  10. F: ['function', function (thingy) { return typeof thingy === 'function' }],
  11. O: ['object', function (thingy) { return typeof thingy === 'object' && !types.A[1](thingy) && !types.E[1](thingy) }],
  12. B: ['boolean', function (thingy) { return typeof thingy === 'boolean' }],
  13. E: ['error', function (thingy) { return thingy instanceof Error }]
  14. }
  15. var validate = module.exports = function (schema, args) {
  16. if (!schema) throw missingRequiredArg(0, 'schema')
  17. if (!args) throw missingRequiredArg(1, 'args')
  18. if (!types.S[1](schema)) throw invalidType(0, 'string', schema)
  19. if (!types.A[1](args)) throw invalidType(1, 'array', args)
  20. for (var ii = 0; ii < schema.length; ++ii) {
  21. var type = schema[ii]
  22. if (!types[type]) throw unknownType(ii, type)
  23. var typeLabel = types[type][0]
  24. var typeCheck = types[type][1]
  25. if (type === 'E' && args[ii] == null) continue
  26. if (args[ii] == null) throw missingRequiredArg(ii)
  27. if (!typeCheck(args[ii])) throw invalidType(ii, typeLabel, args[ii])
  28. if (type === 'E') return
  29. }
  30. if (schema.length < args.length) throw tooManyArgs(schema.length, args.length)
  31. }
  32. function missingRequiredArg (num) {
  33. return newException('EMISSINGARG', 'Missing required argument #' + (num + 1))
  34. }
  35. function unknownType (num, type) {
  36. return newException('EUNKNOWNTYPE', 'Unknown type ' + type + ' in argument #' + (num + 1))
  37. }
  38. function invalidType (num, expectedType, value) {
  39. var valueType
  40. Object.keys(types).forEach(function (typeCode) {
  41. if (types[typeCode][1](value)) valueType = types[typeCode][0]
  42. })
  43. return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' +
  44. expectedType + ' but got ' + valueType)
  45. }
  46. function tooManyArgs (expected, got) {
  47. return newException('ETOOMANYARGS', 'Too many arguments, expected ' + expected + ' and got ' + got)
  48. }
  49. function newException (code, msg) {
  50. var e = new Error(msg)
  51. e.code = code
  52. Error.captureStackTrace(e, validate)
  53. return e
  54. }