Socket
Socket
Sign inDemoInstall

aproba

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aproba - npm Package Compare versions

Comparing version 1.0.4 to 1.1.0

96

index.js
'use strict'
function isArguments (thingy) {
return typeof thingy === 'object' && thingy.hasOwnProperty('callee')
return thingy != null && typeof thingy === 'object' && thingy.hasOwnProperty('callee')
}
var types = {
'*': ['any', function () { return true }],
A: ['array', function (thingy) { return Array.isArray(thingy) || isArguments(thingy) }],
S: ['string', function (thingy) { return typeof thingy === 'string' }],
N: ['number', function (thingy) { return typeof thingy === 'number' }],
F: ['function', function (thingy) { return typeof thingy === 'function' }],
O: ['object', function (thingy) { return typeof thingy === 'object' && !types.A[1](thingy) && !types.E[1](thingy) }],
B: ['boolean', function (thingy) { return typeof thingy === 'boolean' }],
E: ['error', function (thingy) { return thingy instanceof Error }]
'*': {label: 'any', check: function () { return true }},
A: {label: 'array', check: function (thingy) { return Array.isArray(thingy) || isArguments(thingy) }},
S: {label: 'string', check: function (thingy) { return typeof thingy === 'string' }},
N: {label: 'number', check: function (thingy) { return typeof thingy === 'number' }},
F: {label: 'function', check: function (thingy) { return typeof thingy === 'function' }},
O: {label: 'object', check: function (thingy) { return typeof thingy === 'object' && thingy != null && !types.A.check(thingy) && !types.E.check(thingy) }},
B: {label: 'boolean', check: function (thingy) { return typeof thingy === 'boolean' }},
E: {label: 'error', check: function (thingy) { return thingy instanceof Error }},
Z: {label: 'null', check: function (thingy) { return thingy == null }}
}
var validate = module.exports = function (schema, args) {
if (!schema) throw missingRequiredArg(0, 'schema')
var validate = module.exports = function (rawSchemas, args) {
if (arguments.length !== 2) throw wrongNumberOfArgs(['SA'], arguments.length)
if (!rawSchemas) throw missingRequiredArg(0, 'rawSchemas')
if (!args) throw missingRequiredArg(1, 'args')
if (!types.S[1](schema)) throw invalidType(0, 'string', schema)
if (!types.A[1](args)) throw invalidType(1, 'array', args)
for (var ii = 0; ii < schema.length; ++ii) {
var type = schema[ii]
if (!types[type]) throw unknownType(ii, type)
var typeLabel = types[type][0]
var typeCheck = types[type][1]
if (type === 'E' && args[ii] == null) continue
if (args[ii] == null) throw missingRequiredArg(ii)
if (!typeCheck(args[ii])) throw invalidType(ii, typeLabel, args[ii])
if (type === 'E') return
if (!types.S.check(rawSchemas)) throw invalidType(0, ['string'], rawSchemas)
if (!types.A.check(args)) throw invalidType(1, ['array'], args)
var schemas = rawSchemas.split('|')
var arity = {}
function addSchema (schema) {
var group = arity[schema.length] = arity[schema.length] || []
if (group.indexOf(schema) === -1) group.push(schema)
}
if (schema.length < args.length) throw tooManyArgs(schema.length, args.length)
schemas.forEach(function (schema) {
for (var ii = 0; ii < schema.length; ++ii) {
var type = schema[ii]
if (!types[type]) throw unknownType(ii, type)
}
if (/E.*E/.test(schema)) throw moreThanOneError(schema)
addSchema(schema)
if (/E/.test(schema)) {
addSchema(schema.replace(/E.*$/, 'E'))
addSchema(schema.replace(/E/, 'Z'))
}
})
var matching = arity[args.length]
if (!matching) {
throw wrongNumberOfArgs(Object.keys(arity), args.length)
}
for (var ii = 0; ii < args.length; ++ii) {
var newMatching = matching.filter(function (schema) {
var type = schema[ii]
var typeCheck = types[type].check
return typeCheck(args[ii])
})
if (!newMatching.length) {
var labels = matching.map(function (schema) {
return types[schema[ii]].label
}).filter(function (schema) { return schema != null })
throw invalidType(ii, labels, args[ii])
}
matching = newMatching
}
}

@@ -44,15 +71,28 @@

function invalidType (num, expectedType, value) {
function invalidType (num, expectedTypes, value) {
var valueType
Object.keys(types).forEach(function (typeCode) {
if (types[typeCode][1](value)) valueType = types[typeCode][0]
if (types[typeCode].check(value)) valueType = types[typeCode].label
})
return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' +
expectedType + ' but got ' + valueType)
englishList(expectedTypes) + ' but got ' + valueType)
}
function tooManyArgs (expected, got) {
return newException('ETOOMANYARGS', 'Too many arguments, expected ' + expected + ' and got ' + got)
function englishList (list) {
return list.join(', ').replace(/, ([^,]+)$/, ' or $1')
}
function wrongNumberOfArgs (expected, got) {
var english = englishList(expected)
var args = expected.every(function (ex) { return ex.length === 1 })
? 'argument'
: 'arguments'
return newException('EWRONGARGCOUNT', 'Expected ' + english + ' ' + args + ' but got ' + got)
}
function moreThanOneError (schema) {
return newException('ETOOMANYERRORTYPES',
'Only one error type per argument signature is allowed, more than one found in "' + schema + '"')
}
function newException (code, msg) {

@@ -59,0 +99,0 @@ var e = new Error(msg)

{
"name": "aproba",
"version": "1.0.4",
"version": "1.1.0",
"description": "A rediculously light-weight argument validator",

@@ -11,4 +11,4 @@ "main": "index.js",

"devDependencies": {
"standard": "^7.1.2",
"tap": "^5.7.3"
"standard": "^8.6.0",
"tap": "^10.0.2"
},

@@ -19,3 +19,3 @@ "files": [

"scripts": {
"test": "standard && tap test/*.js"
"test": "standard && tap -j3 test/*.js"
},

@@ -22,0 +22,0 @@ "repository": {

@@ -32,3 +32,4 @@ aproba

B | typeof == boolean
E | instanceof Error OR null
E | instanceof Error OR null **(special: see below)**
Z | == null

@@ -41,5 +42,34 @@ Validation failures throw one of three exception types, distinguished by a

If an error argument is found and is not null then the remaining arguments
will not be validated.
If an **error** argument is found and is not null then the remaining
arguments are optional. That is, if you say `ESO` then that's like using a
non-magical `E` in: `E|ESO|ZSO`.
### But I have optional arguments?!
You can provide more than one signature by separating them with pipes `|`.
If any signature matches the arguments then they'll be considered valid.
So for example, say you wanted to write a signature for
`fs.createWriteStream`. The docs for it describe it thusly:
```
fs.createWriteStream(path[, options])
```
This would be a signature of `SO|S`. That is, a string and and object, or
just a string.
Now, if you read the full `fs` docs, you'll see that actually path can ALSO
be a buffer. And options can be a string, that is:
```
path <String> | <Buffer>
options <String> | <Object>
```
To reproduce this you have to fully enumerate all of the possible
combinations and that implies a signature of `SO|SS|OO|OS|S|O`. The
awkwardness is a feature: It reminds you of the complexity you're adding to
your API when you do this sort of thing.
### Why this exists

@@ -46,0 +76,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc