joi-phone-number
Advanced tools
Comparing version 3.1.1 to 4.0.0
@@ -26,7 +26,7 @@ 'use strict'; | ||
expect(schema.validate(undefined).error).toBeNull(); | ||
expect(schema.validate('123').error).toBeNull(); | ||
expect(schema.validate('+32494555890').error).toBeNull(); | ||
expect(schema.validate('494322456').error).toBeNull(); | ||
expect(schema.validate('011 69 37 83').error).toBeNull(); // Should work with the BE fallback | ||
expect(schema.validate(undefined).error).toBeUndefined(); | ||
expect(schema.validate('123').error).toBeUndefined(); | ||
expect(schema.validate('+32494555890').error).toBeUndefined(); | ||
expect(schema.validate('494322456').error).toBeUndefined(); | ||
expect(schema.validate('011 69 37 83').error).toBeUndefined(); // Should work with the BE fallback | ||
}); | ||
@@ -37,36 +37,18 @@ | ||
let schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'e164' | ||
}); | ||
let schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'e164'}); | ||
expect(schema.validate('494322456').value).toBe('+32494322456'); | ||
schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'international' | ||
}); | ||
schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'international'}); | ||
expect(schema.validate('494322456').value).toBe('+32 494 32 24 56'); | ||
schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'national' | ||
}); | ||
schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'national'}); | ||
expect(schema.validate('494322456').value).toBe('0494 32 24 56'); | ||
schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'rfc3966' | ||
}); | ||
schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'rfc3966'}); | ||
expect(schema.validate('494322456').value).toBe('tel:+32-494-32-24-56'); | ||
schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'rfc3966' | ||
}); | ||
schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'rfc3966'}); | ||
expect(schema.validate('494322456', {convert: false}).value).toBe('494322456'); | ||
schema = joi.string().phoneNumber({ | ||
defaultCountry: 'BE', | ||
format: 'rfc3966' | ||
}); | ||
schema = joi.string().phoneNumber({defaultCountry: 'BE', format: 'rfc3966'}); | ||
expect(schema.validate('494322456', {convert: false}).value).toBe('494322456'); | ||
@@ -77,10 +59,12 @@ }); | ||
const joi = Joi.extend(JoiPhoneNumber); | ||
const strict = joi.string().phoneNumber({defaultCountry: 'US', strict: true}); | ||
const strictSchema = joi.string().phoneNumber({defaultCountry: 'US', strict: true}); | ||
const notStrict = joi.string().phoneNumber({defaultCountry: 'US'}); | ||
const numbers = ['7777777777', '1234567890']; | ||
for (const number of numbers) { | ||
expect(strict.validate(number).error.name).toEqual('ValidationError'); | ||
expect(notStrict.validate(number).error).toEqual(null); | ||
} | ||
expect(strictSchema.validate('7777777777').error).toBeInstanceOf(Error); | ||
expect(strictSchema.validate('7777777777').error.name).toEqual('ValidationError'); | ||
expect(notStrict.validate('7777777777').error).toBeUndefined(); | ||
expect(strictSchema.validate('1234567890').error).toBeInstanceOf(Error); | ||
expect(strictSchema.validate('1234567890').error.name).toEqual('ValidationError'); | ||
expect(notStrict.validate('1234567890').error).toBeUndefined(); | ||
}); | ||
@@ -90,8 +74,6 @@ | ||
const joi = Joi.extend(JoiPhoneNumber); | ||
const schema = joi.string().phoneNumber({ | ||
format: 'e164' | ||
}); | ||
const schema = joi.string().phoneNumber({format: 'e164'}); | ||
expect(schema.validate('32494322456').error).toBeInstanceOf(Error); | ||
expect(schema.validate('+32494322456').error).toBeNull(); | ||
expect(schema.validate('+32494322456').error).toBeUndefined(); | ||
}); | ||
@@ -101,8 +83,12 @@ | ||
const joi = Joi.extend(JoiPhoneNumber); | ||
const schema = joi.string().phoneNumber({ | ||
defaultCountry: ['US', 'BE'] | ||
}); | ||
const schema = joi.string().phoneNumber({defaultCountry: ['US', 'BE']}); | ||
expect(schema.validate('011 999 7083').value).toBe('011 999 7083'); | ||
}); | ||
it('should not convert when strict is true', () => { | ||
const joi = Joi.extend(JoiPhoneNumber); | ||
const schema = joi.string().phoneNumber({strict: true}); | ||
expect(schema.validate('011 999 7083').value).toBe('011 999 7083'); | ||
}); | ||
it('errors on wrong format options', () => { | ||
@@ -112,11 +98,15 @@ const joi = Joi.extend(JoiPhoneNumber); | ||
expect(() => { | ||
joi.string().phoneNumber({ | ||
format: 'ppp' | ||
}); | ||
}).toThrow('"format" must be one of [e164, international, national, rfc3966]'); | ||
const schema = joi.string().phoneNumber({defaultCountry: 1}); | ||
schema.validate('011 999 7083'); | ||
}).toThrow('"defaultCountry" must be a string'); | ||
}); | ||
it('errors on wrong format options', () => { | ||
const joi = Joi.extend(JoiPhoneNumber); | ||
expect(() => { | ||
joi.string().phoneNumber({}); | ||
}).toThrow('must have at least 1 children'); | ||
const schema = joi.string().phoneNumber({format: 'ppp'}); | ||
schema.validate('011 999 7083'); | ||
}).toThrow('"format" must be one of [e164, international, national, rfc3966]'); | ||
}); | ||
}); |
'use strict'; | ||
const libphonenumber = require('google-libphonenumber'); | ||
const PhoneUtil = libphonenumber.PhoneNumberUtil.getInstance(); | ||
const PhoneNumberFormat = libphonenumber.PhoneNumberFormat; | ||
const LibPhoneNumber = require('google-libphonenumber'); | ||
const PhoneUtil = LibPhoneNumber.PhoneNumberUtil.getInstance(); | ||
const PhoneNumberFormat = LibPhoneNumber.PhoneNumberFormat; | ||
@@ -15,51 +15,59 @@ const internals = {}; | ||
*/ | ||
module.exports = joi => ({ | ||
base: joi.string(), | ||
name: 'string', | ||
language: { | ||
phonenumber: 'did not seem to be a phone number' | ||
}, | ||
rules: [{ | ||
name: 'phoneNumber', | ||
params: { | ||
opts: joi.object().keys({ | ||
/** | ||
* We will use the specified country code or 'US', with fallback 'BE', if no | ||
* country code provided in phone number (0494...). | ||
* Numbers with country code (+3249...) will use the data from the number and not the default. | ||
*/ | ||
defaultCountry: joi.array().items(joi.string()).single(), | ||
format: joi.string().only('e164', 'international', 'national', 'rfc3966'), | ||
strict: joi.boolean() | ||
}).default({defaultCountry: ['US', 'BE'], strict: false}).min(1) | ||
module.exports = joi => { | ||
const opts = joi.object().keys({ | ||
/** | ||
* We will use the specified country code or 'US', with fallback 'BE', if no | ||
* country code provided in phone number (0494...). | ||
* Numbers with country code (+3249...) will use the data from the number and not the default. | ||
*/ | ||
defaultCountry: joi.array().items(joi.string()).single(), | ||
strict: joi.boolean(), | ||
format: joi.string().valid('e164', 'international', 'national', 'rfc3966') | ||
}).default({defaultCountry: ['US', 'BE']}).min(1); | ||
return { | ||
base: joi.string(), | ||
type: 'string', | ||
messages: { | ||
'phoneNumber.invalid': '"{{#label}}" did not seem to be a phone number' | ||
}, | ||
validate(params, value, state, options) { | ||
try { | ||
const proto = internals.parse(value, params.opts.defaultCountry); | ||
rules: { | ||
phoneNumber: { | ||
method(options) { | ||
return this.$_addRule({name: 'phoneNumber', args: {options}}); | ||
}, | ||
validate(value, {prefs, error}, args) { | ||
const options = joi.attempt(args.options, opts); | ||
if (params.opts.strict && !PhoneUtil.isValidNumber(proto)) { | ||
throw new Error('StrictPhoneNumber'); | ||
} | ||
try { | ||
const proto = internals.parse(value, options.defaultCountry); | ||
if (!options.convert || !params.opts.format) { | ||
return value; | ||
} | ||
if (options.strict && !PhoneUtil.isValidNumber(proto)) { | ||
throw new Error('StrictPhoneNumber'); | ||
} | ||
const format = PhoneNumberFormat[params.opts.format.toUpperCase()]; | ||
return PhoneUtil.format(proto, format); | ||
} catch (err) { | ||
const knownErrors = ['Invalid country calling code', 'The string supplied did not seem to be a phone number', 'StrictPhoneNumber']; | ||
// We ignore the next line for line coverage since we should always hit it but if we have a regression in our code we still want to surface that instead of just returning the default error | ||
/* istanbul ignore next */ | ||
if (knownErrors.includes(err.message)) { | ||
// Generate an error, state and options need to be passed | ||
return this.createError('string.phonenumber', {value}, state, options); | ||
if (!prefs.convert || !options.format) { | ||
return value; | ||
} | ||
const format = PhoneNumberFormat[options.format.toUpperCase()]; | ||
value = PhoneUtil.format(proto, format); | ||
return value; | ||
} catch (err) { | ||
const knownErrors = ['Invalid country calling code', 'The string supplied did not seem to be a phone number', 'StrictPhoneNumber']; | ||
// We ignore the next line for line coverage since we should always hit it but if we have a regression in our code we still want to surface that instead of just returning the default error | ||
/* istanbul ignore next */ | ||
if (knownErrors.includes(err.message)) { | ||
// Generate an error | ||
return error('phoneNumber.invalid'); | ||
} | ||
/* istanbul ignore next */ | ||
throw err; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
throw err; | ||
} | ||
} | ||
}] | ||
}); | ||
}; | ||
}; | ||
@@ -66,0 +74,0 @@ /** |
{ | ||
"name": "joi-phone-number", | ||
"version": "3.1.1", | ||
"version": "4.0.0", | ||
"description": "Phone number validation rule for Joi", | ||
@@ -19,3 +19,2 @@ "homepage": "https://github.com/Salesflare/joi-phone-number", | ||
"prepublishOnly": "npm audit", | ||
"pretest": "eslint . --fix", | ||
"test": "jest" | ||
@@ -54,9 +53,12 @@ }, | ||
"devDependencies": { | ||
"@hapi/joi": "^15.1.1", | ||
"coveralls": "^3.0.7", | ||
"eslint": "^6.5.1", | ||
"eslint-config-xo-space": "^0.21.0", | ||
"@hapi/joi": "^17.0.2", | ||
"coveralls": "^3.0.9", | ||
"eslint": "^6.8.0", | ||
"eslint-config-xo-space": "^0.22.0", | ||
"jest": "^24.9.0", | ||
"jest-cli": "^24.9.0" | ||
}, | ||
"engines": { | ||
"node": ">=12.14.0" | ||
} | ||
} |
12010
163