Initial commit

parents
Pipeline #76 canceled with stages
const parameters = {
database: {
DBNAME: "mcafee_multiterritorios",
DBHOST: "dbtesting.gearlabs.cl",
DBPORT: 3306,
DBUSER: "mcafee_admin_territorios",
DBPSSW: "HSuwshhuw43&%1253",
},
};
module.exports.parameters = parameters;
const mysql = require('mysql');
const configuration = require('../config/parameters');
var con = mysql.createPool({
host: configuration.parameters.database.DBHOST,
database: configuration.parameters.database.DBNAME,
user: configuration.parameters.database.DBUSER,
password: configuration.parameters.database.DBPSSW,
port: configuration.parameters.database.DBPORT
});
module.exports.con = con;
\ No newline at end of file
This diff is collapsed.
const app = require('./endpoints_modules/endpoints');
const dbConn = require('./database_modules/database');
//Trick para problema con eventListeners maximos
require('events').EventEmitter.prototype._maxListeners = 100;
/**
* Se activa la conexion a la base de datos en modalidad pool
*/
dbConn.con.getConnection((err, connection) => {
if(err) {
console.log("Ha ocurrido un error con la conexion...");
throw err;
}else console.log("Conectado!...") ;
});
const endPointContenidoManager = new app.endPointContenidoManager(dbConn.con);
/*
* Solo en ambientes de desarrollo locales se coloca el puerto directamente al iniciar la aplicacion
* en servidores, se debe obtener del objeto global "process"
*/
const port = process.env.PORT || 3000;
app.listen(port);
//Definicion de rutas para las api endpoint
endPointContenidoManager.getHtmlContent('/api/campania/obtener/contenido');
\ No newline at end of file
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../mime/cli.js" "$@"
ret=$?
else
node "$basedir/../mime/cli.js" "$@"
ret=$?
fi
exit $ret
@ECHO off
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
"%_prog%" "%dp0%\..\mime\cli.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
& "$basedir/node$exe" "$basedir/../mime/cli.js" $args
$ret=$LASTEXITCODE
} else {
& "node$exe" "$basedir/../mime/cli.js" $args
$ret=$LASTEXITCODE
}
exit $ret
Copyright (c) 2019-2020, Project contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
# @hapi/address
#### Validate email address and domain.
**address** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) they work even better together.
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
## Useful resources
- [Documentation and API](https://hapi.dev/family/address/)
- [Versions status](https://hapi.dev/resources/status/#address)
- [Changelog](https://hapi.dev/family/address/changelog/)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)
'use strict';
// Adapted from:
// Copyright (c) 2017-2019 Justin Ridgewell, MIT Licensed, https://github.com/jridgewell/safe-decode-string-component
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>, MIT Licensed, http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
const internals = {};
exports.decode = function (string) {
let percentPos = string.indexOf('%');
if (percentPos === -1) {
return string;
}
let decoded = '';
let last = 0;
let codepoint = 0;
let startOfOctets = percentPos;
let state = internals.utf8.accept;
while (percentPos > -1 &&
percentPos < string.length) {
const high = internals.resolveHex(string[percentPos + 1], 4);
const low = internals.resolveHex(string[percentPos + 2], 0);
const byte = high | low;
const type = internals.utf8.data[byte];
state = internals.utf8.data[256 + state + type];
codepoint = (codepoint << 6) | (byte & internals.utf8.data[364 + type]);
if (state === internals.utf8.accept) {
decoded += string.slice(last, startOfOctets);
decoded += codepoint <= 0xFFFF
? String.fromCharCode(codepoint)
: String.fromCharCode(0xD7C0 + (codepoint >> 10), 0xDC00 + (codepoint & 0x3FF));
codepoint = 0;
last = percentPos + 3;
percentPos = string.indexOf('%', last);
startOfOctets = percentPos;
continue;
}
if (state === internals.utf8.reject) {
return null;
}
percentPos += 3;
if (percentPos >= string.length ||
string[percentPos] !== '%') {
return null;
}
}
return decoded + string.slice(last);
};
internals.resolveHex = function (char, shift) {
const i = internals.hex[char];
return i === undefined ? 255 : i << shift;
};
internals.hex = {
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
'5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
'a': 10, 'A': 10, 'b': 11, 'B': 11, 'c': 12,
'C': 12, 'd': 13, 'D': 13, 'e': 14, 'E': 14,
'f': 15, 'F': 15
};
internals.utf8 = {
accept: 12,
reject: 0,
data: [
// Maps bytes to character to a transition
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7,
10, 9, 9, 9, 11, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
// Maps a state to a new state when adding a transition
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12, 0, 0, 0, 0, 24, 36, 48, 60, 72, 84, 96,
0, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0,
0, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0,
0, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0,
0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Maps the current transition to a mask that needs to apply to the byte
0x7F, 0x3F, 0x3F, 0x3F, 0x00, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07
]
};
'use strict';
const Url = require('url');
const Errors = require('./errors');
const internals = {
minDomainSegments: 2,
nonAsciiRx: /[^\x00-\x7f]/,
domainControlRx: /[\x00-\x20@\:\/]/, // Control + space + separators
tldSegmentRx: /^[a-zA-Z](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/,
domainSegmentRx: /^[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/,
URL: Url.URL || URL // $lab:coverage:ignore$
};
exports.analyze = function (domain, options = {}) {
if (typeof domain !== 'string') {
throw new Error('Invalid input: domain must be a string');
}
if (!domain) {
return Errors.code('DOMAIN_NON_EMPTY_STRING');
}
if (domain.length > 256) {
return Errors.code('DOMAIN_TOO_LONG');
}
const ascii = !internals.nonAsciiRx.test(domain);
if (!ascii) {
if (options.allowUnicode === false) { // Defaults to true
return Errors.code('DOMAIN_INVALID_UNICODE_CHARS');
}
domain = domain.normalize('NFC');
}
if (internals.domainControlRx.test(domain)) {
return Errors.code('DOMAIN_INVALID_CHARS');
}
domain = internals.punycode(domain);
// https://tools.ietf.org/html/rfc1035 section 2.3.1
const minDomainSegments = options.minDomainSegments || internals.minDomainSegments;
const segments = domain.split('.');
if (segments.length < minDomainSegments) {
return Errors.code('DOMAIN_SEGMENTS_COUNT');
}
if (options.maxDomainSegments) {
if (segments.length > options.maxDomainSegments) {
return Errors.code('DOMAIN_SEGMENTS_COUNT_MAX');
}
}
const tlds = options.tlds;
if (tlds) {
const tld = segments[segments.length - 1].toLowerCase();
if (tlds.deny && tlds.deny.has(tld) ||
tlds.allow && !tlds.allow.has(tld)) {
return Errors.code('DOMAIN_FORBIDDEN_TLDS');
}
}
for (let i = 0; i < segments.length; ++i) {
const segment = segments[i];
if (!segment.length) {
return Errors.code('DOMAIN_EMPTY_SEGMENT');
}
if (segment.length > 63) {
return Errors.code('DOMAIN_LONG_SEGMENT');
}
if (i < segments.length - 1) {
if (!internals.domainSegmentRx.test(segment)) {
return Errors.code('DOMAIN_INVALID_CHARS');
}
}
else {
if (!internals.tldSegmentRx.test(segment)) {
return Errors.code('DOMAIN_INVALID_TLDS_CHARS');
}
}
}
return null;
};
exports.isValid = function (domain, options) {
return !exports.analyze(domain, options);
};
internals.punycode = function (domain) {
try {
return new internals.URL(`http://${domain}`).host;
}
catch (err) {
return domain;
}
};
'use strict';
const Util = require('util');
const Domain = require('./domain');
const Errors = require('./errors');
const internals = {
nonAsciiRx: /[^\x00-\x7f]/,
encoder: new (Util.TextEncoder || TextEncoder)() // $lab:coverage:ignore$
};
exports.analyze = function (email, options) {
return internals.email(email, options);
};
exports.isValid = function (email, options) {
return !internals.email(email, options);
};
internals.email = function (email, options = {}) {
if (typeof email !== 'string') {
throw new Error('Invalid input: email must be a string');
}
if (!email) {
return Errors.code('EMPTY_STRING');
}
// Unicode
const ascii = !internals.nonAsciiRx.test(email);
if (!ascii) {
if (options.allowUnicode === false) { // Defaults to true
return Errors.code('FORBIDDEN_UNICODE');
}
email = email.normalize('NFC');
}
// Basic structure
const parts = email.split('@');
if (parts.length !== 2) {
return parts.length > 2 ? Errors.code('MULTIPLE_AT_CHAR') : Errors.code('MISSING_AT_CHAR');
}
const [local, domain] = parts;
if (!local) {
return Errors.code('EMPTY_LOCAL');
}
if (!options.ignoreLength) {
if (email.length > 254) { // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3
return Errors.code('ADDRESS_TOO_LONG');
}
if (internals.encoder.encode(local).length > 64) { // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1
return Errors.code('LOCAL_TOO_LONG');
}
}
// Validate parts
return internals.local(local, ascii) || Domain.analyze(domain, options);
};
internals.local = function (local, ascii) {
const segments = local.split('.');
for (const segment of segments) {
if (!segment.length) {
return Errors.code('EMPTY_LOCAL_SEGMENT');
}
if (ascii) {
if (!internals.atextRx.test(segment)) {
return Errors.code('INVALID_LOCAL_CHARS');
}
continue;
}
for (const char of segment) {
if (internals.atextRx.test(char)) {
continue;
}
const binary = internals.binary(char);
if (!internals.atomRx.test(binary)) {
return Errors.code('INVALID_LOCAL_CHARS');
}
}
}
};
internals.binary = function (char) {
return Array.from(internals.encoder.encode(char)).map((v) => String.fromCharCode(v)).join('');
};
/*
From RFC 5321:
Mailbox = Local-part "@" ( Domain / address-literal )
Local-part = Dot-string / Quoted-string
Dot-string = Atom *("." Atom)
Atom = 1*atext
atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
Domain = sub-domain *("." sub-domain)
sub-domain = Let-dig [Ldh-str]
Let-dig = ALPHA / DIGIT
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
ALPHA = %x41-5A / %x61-7A ; a-z, A-Z
DIGIT = %x30-39 ; 0-9
From RFC 6531:
sub-domain =/ U-label
atext =/ UTF8-non-ascii
UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4
UTF8-2 = %xC2-DF UTF8-tail
UTF8-3 = %xE0 %xA0-BF UTF8-tail /
%xE1-EC 2( UTF8-tail ) /
%xED %x80-9F UTF8-tail /
%xEE-EF 2( UTF8-tail )
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) /
%xF1-F3 3( UTF8-tail ) /
%xF4 %x80-8F 2( UTF8-tail )
UTF8-tail = %x80-BF
Note: The following are not supported:
RFC 5321: address-literal, Quoted-string
RFC 5322: obs-*, CFWS
*/
internals.atextRx = /^[\w!#\$%&'\*\+\-/=\?\^`\{\|\}~]+$/; // _ included in \w
internals.atomRx = new RegExp([
// %xC2-DF UTF8-tail
'(?:[\\xc2-\\xdf][\\x80-\\xbf])',
// %xE0 %xA0-BF UTF8-tail %xE1-EC 2( UTF8-tail ) %xED %x80-9F UTF8-tail %xEE-EF 2( UTF8-tail )
'(?:\\xe0[\\xa0-\\xbf][\\x80-\\xbf])|(?:[\\xe1-\\xec][\\x80-\\xbf]{2})|(?:\\xed[\\x80-\\x9f][\\x80-\\xbf])|(?:[\\xee-\\xef][\\x80-\\xbf]{2})',
// %xF0 %x90-BF 2( UTF8-tail ) %xF1-F3 3( UTF8-tail ) %xF4 %x80-8F 2( UTF8-tail )
'(?:\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2})|(?:[\\xf1-\\xf3][\\x80-\\xbf]{3})|(?:\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2})'
].join('|'));
'use strict';
exports.codes = {
EMPTY_STRING: 'Address must be a non-empty string',
FORBIDDEN_UNICODE: 'Address contains forbidden Unicode characters',
MULTIPLE_AT_CHAR: 'Address cannot contain more than one @ character',
MISSING_AT_CHAR: 'Address must contain one @ character',
EMPTY_LOCAL: 'Address local part cannot be empty',
ADDRESS_TOO_LONG: 'Address too long',
LOCAL_TOO_LONG: 'Address local part too long',
EMPTY_LOCAL_SEGMENT: 'Address local part contains empty dot-separated segment',
INVALID_LOCAL_CHARS: 'Address local part contains invalid character',
DOMAIN_NON_EMPTY_STRING: 'Domain must be a non-empty string',
DOMAIN_TOO_LONG: 'Domain too long',
DOMAIN_INVALID_UNICODE_CHARS: 'Domain contains forbidden Unicode characters',
DOMAIN_INVALID_CHARS: 'Domain contains invalid character',
DOMAIN_INVALID_TLDS_CHARS: 'Domain contains invalid tld character',
DOMAIN_SEGMENTS_COUNT: 'Domain lacks the minimum required number of segments',
DOMAIN_SEGMENTS_COUNT_MAX: 'Domain contains too many segments',
DOMAIN_FORBIDDEN_TLDS: 'Domain uses forbidden TLD',
DOMAIN_EMPTY_SEGMENT: 'Domain contains empty dot-separated segment',
DOMAIN_LONG_SEGMENT: 'Domain contains dot-separated segment that is too long'
};
exports.code = function (code) {
return { code, error: exports.codes[code] };
};
/// <reference types="node" />
import * as Hoek from '@hapi/hoek';
export namespace domain {
/**
* Analyzes a string to verify it is a valid domain name.
*
* @param domain - the domain name to validate.
* @param options - optional settings.
*
* @return - undefined when valid, otherwise an object with single error key with a string message value.
*/
function analyze(domain: string, options?: Options): Analysis | null;
/**
* Analyzes a string to verify it is a valid domain name.
*
* @param domain - the domain name to validate.
* @param options - optional settings.
*
* @return - true when valid, otherwise false.
*/
function isValid(domain: string, options?: Options): boolean;
interface Options {
/**
* Determines whether Unicode characters are allowed.
*
* @default true
*/
readonly allowUnicode?: boolean;
/**
* The minimum number of domain segments (e.g. `x.y.z` has 3 segments) required.
*
* @default 2
*/
readonly minDomainSegments?: number;
/**
* Top-level-domain options
*
* @default true
*/
readonly tlds?: Tlds.Allow | Tlds.Deny | boolean;
}
namespace Tlds {
interface Allow {
readonly allow: Set<string> | true;
}
interface Deny {
readonly deny: Set<string>;
}
}
}
export namespace email {
/**
* Analyzes a string to verify it is a valid email address.
*
* @param email - the email address to validate.
* @param options - optional settings.
*
* @return - undefined when valid, otherwise an object with single error key with a string message value.
*/
function analyze(email: string, options?: Options): Analysis | null;
/**
* Analyzes a string to verify it is a valid email address.
*
* @param email - the email address to validate.
* @param options - optional settings.
*
* @return - true when valid, otherwise false.
*/
function isValid(email: string, options?: Options): boolean;
interface Options extends domain.Options {
/**
* Determines whether to ignore the standards maximum email length limit.
*
* @default false
*/
readonly ignoreLength?: boolean;
}
}
export interface Analysis {
/**
* The reason validation failed.
*/
error: string;
/**
* The error code.
*/
code: string;
}
export const errors: Record<string, string>;
export namespace ip {
/**
* Generates a regular expression used to validate IP addresses.
*
* @param options - optional settings.
*
* @returns an object with the regular expression and meta data.
*/
function regex(options?: Options): Expression;
interface Options {
/**
* The required CIDR mode.
*
* @default 'optional'
*/
readonly cidr?: Cidr;
/**
* The allowed versions.
*
* @default ['ipv4', 'ipv6', 'ipvfuture']
*/
readonly version?: Version | Version[];
}
type Cidr = 'optional' | 'required' | 'forbidden';
type Version = 'ipv4' | 'ipv6' | 'ipvfuture';
interface Expression {
/**
* The CIDR mode.
*/
cidr: Cidr;
/**
* The raw regular expression string.
*/
raw: string;
/**
* The regular expression.
*/
regex: RegExp;
/**
* The array of versions allowed.
*/
versions: Version[];
}
}
export namespace uri {
/**
* Faster version of decodeURIComponent() that does not throw.
*
* @param string - the URL string to decode.
*
* @returns the decoded string or null if invalid.
*/
function decode(string: string): string | null;
/**
* Generates a regular expression used to validate URI addresses.
*
* @param options - optional settings.
*
* @returns an object with the regular expression and meta data.
*/
function regex(options?: Options): Expression;
type Options = Hoek.ts.XOR<Options.Options, Options.Relative>;
namespace Options {
interface Query {
/**
* Allow the use of [] in query parameters.
*
* @default false
*/
readonly allowQuerySquareBrackets?: boolean;
}
interface Relative extends Query {
/**
* Requires the URI to be relative.
*
* @default false
*/
readonly relativeOnly?: boolean;
}
interface Options extends Query {
/**
* Allow relative URIs.
*
* @default false
*/
readonly allowRelative?: boolean;
/**
* Capture domain segment ($1).
*
* @default false
*/
readonly domain?: boolean;
/**
* The allowed URI schemes.
*/
readonly scheme?: Scheme | Scheme[];
}
type Scheme = string | RegExp;
}
interface Expression {
/**
* The raw regular expression string.
*/
raw: string;
/**
* The regular expression.
*/
regex: RegExp;
}
}
'use strict';
const Decode = require('./decode');
const Domain = require('./domain');
const Email = require('./email');
const Errors = require('./errors');
const Ip = require('./ip');
const Tlds = require('./tlds');
const Uri = require('./uri');
const internals = {
defaultTlds: { allow: Tlds, deny: null }
};
module.exports = {
errors: Errors.codes,
domain: {
analyze(domain, options) {
options = internals.options(options);
return Domain.analyze(domain, options);
},
isValid(domain, options) {
options = internals.options(options);
return Domain.isValid(domain, options);
}
},
email: {
analyze(email, options) {
options = internals.options(options);
return Email.analyze(email, options);
},
isValid(email, options) {
options = internals.options(options);
return Email.isValid(email, options);
}
},
ip: {
regex: Ip.regex
},
uri: {
decode: Decode.decode,
regex: Uri.regex
}
};
internals.options = function (options) {
if (!options) {
return { tlds: internals.defaultTlds };
}
if (options.tlds === false) { // Defaults to true
return options;
}
if (!options.tlds ||
options.tlds === true) {
return Object.assign({}, options, { tlds: internals.defaultTlds });
}
if (typeof options.tlds !== 'object') {
throw new Error('Invalid options: tlds must be a boolean or an object');
}
if (options.tlds.deny) {
if (options.tlds.deny instanceof Set === false) {
throw new Error('Invalid options: tlds.deny must be a Set object');
}
if (options.tlds.allow) {
throw new Error('Invalid options: cannot specify both tlds.allow and tlds.deny lists');
}
return options;
}
if (options.tlds.allow === true) {
return Object.assign({}, options, { tlds: internals.defaultTlds });
}
if (options.tlds.allow instanceof Set === false) {
throw new Error('Invalid options: tlds.allow must be a Set object or true');
}
return options;
};
'use strict';
const Assert = require('@hapi/hoek/lib/assert');
const Uri = require('./uri');
const internals = {};
exports.regex = function (options = {}) {
// CIDR
Assert(options.cidr === undefined || typeof options.cidr === 'string', 'options.cidr must be a string');
const cidr = options.cidr ? options.cidr.toLowerCase() : 'optional';
Assert(['required', 'optional', 'forbidden'].includes(cidr), 'options.cidr must be one of required, optional, forbidden');
// Versions
Assert(options.version === undefined || typeof options.version === 'string' || Array.isArray(options.version), 'options.version must be a string or an array of string');
let versions = options.version || ['ipv4', 'ipv6', 'ipvfuture'];
if (!Array.isArray(versions)) {
versions = [versions];
}
Assert(versions.length >= 1, 'options.version must have at least 1 version specified');
for (let i = 0; i < versions.length; ++i) {
Assert(typeof versions[i] === 'string', 'options.version must only contain strings');
versions[i] = versions[i].toLowerCase();
Assert(['ipv4', 'ipv6', 'ipvfuture'].includes(versions[i]), 'options.version contains unknown version ' + versions[i] + ' - must be one of ipv4, ipv6, ipvfuture');
}
versions = Array.from(new Set(versions));
// Regex
const parts = versions.map((version) => {
// Forbidden
if (cidr === 'forbidden') {
return Uri.ip[version];
}
// Required
const cidrpart = `\\/${version === 'ipv4' ? Uri.ip.v4Cidr : Uri.ip.v6Cidr}`;
if (cidr === 'required') {
return `${Uri.ip[version]}${cidrpart}`;
}
// Optional
return `${Uri.ip[version]}(?:${cidrpart})?`;
});
const raw = `(?:${parts.join('|')})`;
const regex = new RegExp(`^${raw}$`);
return { cidr, versions, regex, raw };
};
This diff is collapsed.
'use strict';
const Assert = require('@hapi/hoek/lib/assert');
const EscapeRegex = require('@hapi/hoek/lib/escapeRegex');
const internals = {};
internals.generate = function () {
const rfc3986 = {};
const hexDigit = '\\dA-Fa-f'; // HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
const hexDigitOnly = '[' + hexDigit + ']';
const unreserved = '\\w-\\.~'; // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
const subDelims = '!\\$&\'\\(\\)\\*\\+,;='; // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
const pctEncoded = '%' + hexDigit; // pct-encoded = "%" HEXDIG HEXDIG
const pchar = unreserved + pctEncoded + subDelims + ':@'; // pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
const pcharOnly = '[' + pchar + ']';
const decOctect = '(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])'; // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 ; 0-9 / 10-99 / 100-199 / 200-249 / 250-255
rfc3986.ipv4address = '(?:' + decOctect + '\\.){3}' + decOctect; // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
/*
h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal
ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address
IPv6address = 6( h16 ":" ) ls32
/ "::" 5( h16 ":" ) ls32
/ [ h16 ] "::" 4( h16 ":" ) ls32
/ [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
/ [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
/ [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
/ [ *4( h16 ":" ) h16 ] "::" ls32
/ [ *5( h16 ":" ) h16 ] "::" h16
/ [ *6( h16 ":" ) h16 ] "::"
*/
const h16 = hexDigitOnly + '{1,4}';
const ls32 = '(?:' + h16 + ':' + h16 + '|' + rfc3986.ipv4address + ')';
const IPv6SixHex = '(?:' + h16 + ':){6}' + ls32;
const IPv6FiveHex = '::(?:' + h16 + ':){5}' + ls32;
const IPv6FourHex = '(?:' + h16 + ')?::(?:' + h16 + ':){4}' + ls32;
const IPv6ThreeHex = '(?:(?:' + h16 + ':){0,1}' + h16 + ')?::(?:' + h16 + ':){3}' + ls32;
const IPv6TwoHex = '(?:(?:' + h16 + ':){0,2}' + h16 + ')?::(?:' + h16 + ':){2}' + ls32;
const IPv6OneHex = '(?:(?:' + h16 + ':){0,3}' + h16 + ')?::' + h16 + ':' + ls32;
const IPv6NoneHex = '(?:(?:' + h16 + ':){0,4}' + h16 + ')?::' + ls32;
const IPv6NoneHex2 = '(?:(?:' + h16 + ':){0,5}' + h16 + ')?::' + h16;
const IPv6NoneHex3 = '(?:(?:' + h16 + ':){0,6}' + h16 + ')?::';
rfc3986.ipv4Cidr = '(?:\\d|[1-2]\\d|3[0-2])'; // IPv4 cidr = DIGIT / %x31-32 DIGIT / "3" %x30-32 ; 0-9 / 10-29 / 30-32
rfc3986.ipv6Cidr = '(?:0{0,2}\\d|0?[1-9]\\d|1[01]\\d|12[0-8])'; // IPv6 cidr = DIGIT / %x31-39 DIGIT / "1" %x0-1 DIGIT / "12" %x0-8; 0-9 / 10-99 / 100-119 / 120-128
rfc3986.ipv6address = '(?:' + IPv6SixHex + '|' + IPv6FiveHex + '|' + IPv6FourHex + '|' + IPv6ThreeHex + '|' + IPv6TwoHex + '|' + IPv6OneHex + '|' + IPv6NoneHex + '|' + IPv6NoneHex2 + '|' + IPv6NoneHex3 + ')';
rfc3986.ipvFuture = 'v' + hexDigitOnly + '+\\.[' + unreserved + subDelims + ':]+'; // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
rfc3986.scheme = '[a-zA-Z][a-zA-Z\\d+-\\.]*'; // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
rfc3986.schemeRegex = new RegExp(rfc3986.scheme);
const userinfo = '[' + unreserved + pctEncoded + subDelims + ':]*'; // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
const IPLiteral = '\\[(?:' + rfc3986.ipv6address + '|' + rfc3986.ipvFuture + ')\\]'; // IP-literal = "[" ( IPv6address / IPvFuture ) "]"
const regName = '[' + unreserved + pctEncoded + subDelims + ']{1,255}'; // reg-name = *( unreserved / pct-encoded / sub-delims )
const host = '(?:' + IPLiteral + '|' + rfc3986.ipv4address + '|' + regName + ')'; // host = IP-literal / IPv4address / reg-name
const port = '\\d*'; // port = *DIGIT
const authority = '(?:' + userinfo + '@)?' + host + '(?::' + port + ')?'; // authority = [ userinfo "@" ] host [ ":" port ]
const authorityCapture = '(?:' + userinfo + '@)?(' + host + ')(?::' + port + ')?';
/*
segment = *pchar
segment-nz = 1*pchar
path = path-abempty ; begins with "/" '|' is empty
/ path-absolute ; begins with "/" but not "//"
/ path-noscheme ; begins with a non-colon segment
/ path-rootless ; begins with a segment
/ path-empty ; zero characters
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-rootless = segment-nz *( "/" segment )
*/
const segment = pcharOnly + '*';
const segmentNz = pcharOnly + '+';
const segmentNzNc = '[' + unreserved + pctEncoded + subDelims + '@' + ']+';
const pathEmpty = '';
const pathAbEmpty = '(?:\\/' + segment + ')*';
const pathAbsolute = '\\/(?:' + segmentNz + pathAbEmpty + ')?';
const pathRootless = segmentNz + pathAbEmpty;
const pathNoScheme = segmentNzNc + pathAbEmpty;
const pathAbNoAuthority = '(?:\\/\\/\\/' + segment + pathAbEmpty + ')'; // Used by file:///
// hier-part = "//" authority path
rfc3986.hierPart = '(?:' + '(?:\\/\\/' + authority + pathAbEmpty + ')' + '|' + pathAbsolute + '|' + pathRootless + '|' + pathAbNoAuthority + ')';
rfc3986.hierPartCapture = '(?:' + '(?:\\/\\/' + authorityCapture + pathAbEmpty + ')' + '|' + pathAbsolute + '|' + pathRootless + ')';
// relative-part = "//" authority path-abempty / path-absolute / path-noscheme / path-empty
rfc3986.relativeRef = '(?:' + '(?:\\/\\/' + authority + pathAbEmpty + ')' + '|' + pathAbsolute + '|' + pathNoScheme + '|' + pathEmpty + ')';
rfc3986.relativeRefCapture = '(?:' + '(?:\\/\\/' + authorityCapture + pathAbEmpty + ')' + '|' + pathAbsolute + '|' + pathNoScheme + '|' + pathEmpty + ')';
// query = *( pchar / "/" / "?" )
// query = *( pchar / "[" / "]" / "/" / "?" )
rfc3986.query = '[' + pchar + '\\/\\?]*(?=#|$)'; //Finish matching either at the fragment part '|' end of the line.
rfc3986.queryWithSquareBrackets = '[' + pchar + '\\[\\]\\/\\?]*(?=#|$)';
// fragment = *( pchar / "/" / "?" )
rfc3986.fragment = '[' + pchar + '\\/\\?]*';
return rfc3986;
};
internals.rfc3986 = internals.generate();
exports.ip = {
v4Cidr: internals.rfc3986.ipv4Cidr,
v6Cidr: internals.rfc3986.ipv6Cidr,
ipv4: internals.rfc3986.ipv4address,
ipv6: internals.rfc3986.ipv6address,
ipvfuture: internals.rfc3986.ipvFuture
};
internals.createRegex = function (options) {
const rfc = internals.rfc3986;
// Construct expression
const query = options.allowQuerySquareBrackets ? rfc.queryWithSquareBrackets : rfc.query;
const suffix = '(?:\\?' + query + ')?' + '(?:#' + rfc.fragment + ')?';
// relative-ref = relative-part [ "?" query ] [ "#" fragment ]
const relative = options.domain ? rfc.relativeRefCapture : rfc.relativeRef;
if (options.relativeOnly) {
return internals.wrap(relative + suffix);
}
// Custom schemes
let customScheme = '';
if (options.scheme) {
Assert(options.scheme instanceof RegExp || typeof options.scheme === 'string' || Array.isArray(options.scheme), 'scheme must be a RegExp, String, or Array');
const schemes = [].concat(options.scheme);
Assert(schemes.length >= 1, 'scheme must have at least 1 scheme specified');
// Flatten the array into a string to be used to match the schemes
const selections = [];
for (let i = 0; i < schemes.length; ++i) {
const scheme = schemes[i];
Assert(scheme instanceof RegExp || typeof scheme === 'string', 'scheme at position ' + i + ' must be a RegExp or String');
if (scheme instanceof RegExp) {
selections.push(scheme.source.toString());
}
else {
Assert(rfc.schemeRegex.test(scheme), 'scheme at position ' + i + ' must be a valid scheme');
selections.push(EscapeRegex(scheme));
}
}
customScheme = selections.join('|');
}
// URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
const scheme = customScheme ? '(?:' + customScheme + ')' : rfc.scheme;
const absolute = '(?:' + scheme + ':' + (options.domain ? rfc.hierPartCapture : rfc.hierPart) + ')';
const prefix = options.allowRelative ? '(?:' + absolute + '|' + relative + ')' : absolute;
return internals.wrap(prefix + suffix, customScheme);
};
internals.wrap = function (raw, scheme) {
raw = `(?=.)(?!https?\:/$)${raw}`; // Require at least one character and explicitly forbid 'http:/'
return {
raw,
regex: new RegExp(`^${raw}$`),
scheme
};
};
internals.uriRegex = internals.createRegex({});
exports.regex = function (options = {}) {
if (options.scheme ||
options.allowRelative ||
options.relativeOnly ||
options.allowQuerySquareBrackets ||
options.domain) {
return internals.createRegex(options);
}
return internals.uriRegex;
};
{
"_from": "@hapi/address@^4.1.0",
"_id": "@hapi/address@4.1.0",
"_inBundle": false,
"_integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==",
"_location": "/@hapi/address",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@hapi/address@^4.1.0",
"name": "@hapi/address",
"escapedName": "@hapi%2faddress",
"scope": "@hapi",
"rawSpec": "^4.1.0",
"saveSpec": null,
"fetchSpec": "^4.1.0"
},
"_requiredBy": [
"/joi"
],
"_resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz",
"_shasum": "d60c5c0d930e77456fdcde2598e77302e2955e1d",
"_spec": "@hapi/address@^4.1.0",
"_where": "C:\\Users\\cdiaz\\Documents\\node proyects\\vidly\\node_modules\\joi",
"bugs": {
"url": "https://github.com/hapijs/address/issues"
},
"bundleDependencies": false,
"dependencies": {
"@hapi/hoek": "^9.0.0"
},
"deprecated": false,
"description": "Email address and domain validation",
"devDependencies": {
"@hapi/code": "8.x.x",
"@hapi/lab": "22.x.x"
},
"files": [
"lib"
],
"homepage": "https://github.com/hapijs/address#readme",
"keywords": [
"email",
"domain",
"address",
"validation"
],
"license": "BSD-3-Clause",
"main": "lib/index.js",
"name": "@hapi/address",
"repository": {
"type": "git",
"url": "git://github.com/hapijs/address.git"
},
"scripts": {
"test": "lab -a @hapi/code -t 100 -L -Y",
"test-cov-html": "lab -a @hapi/code -t 100 -L -r html -o coverage.html"
},
"types": "lib/index.d.ts",
"version": "4.1.0"
}
Breaking changes are documented using GitHub issues, see [issues labeled "release notes"](https://github.com/hapijs/formula/issues?q=is%3Aissue+label%3A%22release+notes%22).
If you want changes of a specific minor or patch release, you can browse the [GitHub milestones](https://github.com/hapijs/formula/milestones?state=closed&direction=asc&sort=due_date).
Copyright (c) 2019, Project contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
# @hapi/formula
#### Math and string formula parser.
**formula** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) they work even better together.
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
## Useful resources
- [Documentation and API](https://hapi.dev/family/formula/)
- [Version status](https://hapi.dev/resources/status/#formula) (builds, dependencies, node versions, licenses, eol)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)
## Acknowledgements
Inspired by [**fparse**](https://github.com/bylexus/fparse), copyright 2012-2018 Alexander Schenkel <alex@alexi.ch>
/**
* Formula parser
*/
export class Parser<T extends (string | number)> {
/**
* Create a new formula parser.
*
* @param formula - the formula string to parse.
* @param options - optional settings.
*/
constructor(formula: string, options?: Options);
/**
* Evaluate the formula.
*
* @param context - optional object with runtime formula context used to resolve variables.
*
* @returns the string or number outcome of the resolved formula.
*/
evaluate(context?: any): T;
}
export interface Options {
/**
* A hash of key - value pairs used to convert constants to values.
*/
readonly constants?: Record<string, any>;
/**
* A regular expression used to validate token variables.
*/
readonly tokenRx?: RegExp;
/**
* A variable resolver factory function.
*/
readonly reference?: Options.Reference;
/**
* A hash of key-value pairs used to resolve formula functions.
*/
readonly functions?: Record<string, Function>;
}
export namespace Options {
type Reference = (name: string) => (context: any) => any;
}
This diff is collapsed.
{
"_from": "@hapi/formula@^2.0.0",
"_id": "@hapi/formula@2.0.0",
"_inBundle": false,
"_integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==",
"_location": "/@hapi/formula",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@hapi/formula@^2.0.0",
"name": "@hapi/formula",
"escapedName": "@hapi%2fformula",
"scope": "@hapi",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/joi"
],
"_resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz",
"_shasum": "edade0619ed58c8e4f164f233cda70211e787128",
"_spec": "@hapi/formula@^2.0.0",
"_where": "C:\\Users\\cdiaz\\Documents\\node proyects\\vidly\\node_modules\\joi",
"bugs": {
"url": "https://github.com/hapijs/formula/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": "This version has been deprecated and is no longer supported or maintained",
"description": "Math and string formula parser.",
"devDependencies": {
"@hapi/code": "6.x.x",
"@hapi/lab": "20.x.x"
},
"files": [
"lib"
],
"homepage": "https://github.com/hapijs/formula#readme",
"keywords": [
"formula",
"parser",
"math",
"string"
],
"license": "BSD-3-Clause",
"main": "lib/index.js",
"name": "@hapi/formula",
"repository": {
"type": "git",
"url": "git://github.com/hapijs/formula.git"
},
"scripts": {
"test": "lab -a @hapi/code -t 100 -L -Y",
"test-cov-html": "lab -a @hapi/code -t 100 -L -r html -o coverage.html"
},
"types": "lib/index.d.ts",
"version": "2.0.0"
}
Copyright (c) 2011-2020, Sideway Inc, and project contributors
Copyright (c) 2011-2014, Walmart
Copyright (c) 2011, Yahoo Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
# @hapi/hoek
#### Utility methods for the hapi ecosystem.
**hoek** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together.
This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash).
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
## Useful resources
- [Documentation and API](https://hapi.dev/family/hoek/)
- [Version status](https://hapi.dev/resources/status/#hoek) (builds, dependencies, node versions, licenses, eol)
- [Changelog](https://hapi.dev/family/hoek/changelog/)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)
'use strict';
const Assert = require('./assert');
const Clone = require('./clone');
const Merge = require('./merge');
const Reach = require('./reach');
const internals = {};
module.exports = function (defaults, source, options = {}) {
Assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object');
Assert(!source || source === true || typeof source === 'object', 'Invalid source value: must be true, falsy or an object');
Assert(typeof options === 'object', 'Invalid options: must be an object');
if (!source) { // If no source, return null
return null;
}
if (options.shallow) {
return internals.applyToDefaultsWithShallow(defaults, source, options);
}
const copy = Clone(defaults);
if (source === true) { // If source is set to true, use defaults
return copy;
}
const nullOverride = options.nullOverride !== undefined ? options.nullOverride : false;
return Merge(copy, source, { nullOverride, mergeArrays: false });
};
internals.applyToDefaultsWithShallow = function (defaults, source, options) {
const keys = options.shallow;
Assert(Array.isArray(keys), 'Invalid keys');
const seen = new Map();
const merge = source === true ? null : new Set();
for (let key of keys) {
key = Array.isArray(key) ? key : key.split('.'); // Pre-split optimization
const ref = Reach(defaults, key);
if (ref &&
typeof ref === 'object') {
seen.set(ref, merge && Reach(source, key) || ref);
}
else if (merge) {
merge.add(key);
}
}
const copy = Clone(defaults, {}, seen);
if (!merge) {
return copy;
}
for (const key of merge) {
internals.reachCopy(copy, source, key);
}
return Merge(copy, source, { mergeArrays: false, nullOverride: false });
};
internals.reachCopy = function (dst, src, path) {
for (const segment of path) {
if (!(segment in src)) {
return;
}
src = src[segment];
}
const value = src;
let ref = dst;
for (let i = 0; i < path.length - 1; ++i) {
const segment = path[i];
if (typeof ref[segment] !== 'object') {
ref[segment] = {};
}
ref = ref[segment];
}
ref[path[path.length - 1]] = value;
};
'use strict';
const AssertError = require('./error');
const internals = {};
module.exports = function (condition, ...args) {
if (condition) {
return;
}
if (args.length === 1 &&
args[0] instanceof Error) {
throw args[0];
}
throw new AssertError(args);
};
'use strict';
const internals = {};
module.exports = internals.Bench = class {
constructor() {
this.ts = 0;
this.reset();
}
reset() {
this.ts = internals.Bench.now();
}
elapsed() {
return internals.Bench.now() - this.ts;
}
static now() {
const ts = process.hrtime();
return (ts[0] * 1e3) + (ts[1] / 1e6);
}
};
'use strict';
const Ignore = require('./ignore');
const internals = {};
module.exports = function () {
return new Promise(Ignore);
};
'use strict';
const Reach = require('./reach');
const Types = require('./types');
const Utils = require('./utils');
const internals = {
needsProtoHack: new Set([Types.set, Types.map, Types.weakSet, Types.weakMap])
};
module.exports = internals.clone = function (obj, options = {}, _seen = null) {
if (typeof obj !== 'object' ||
obj === null) {
return obj;
}
let clone = internals.clone;
let seen = _seen;
if (options.shallow) {
if (options.shallow !== true) {
return internals.cloneWithShallow(obj, options);
}
clone = (value) => value;
}
else if (seen) {
const lookup = seen.get(obj);
if (lookup) {
return lookup;
}
}
else {
seen = new Map();
}
// Built-in object types
const baseProto = Types.getInternalProto(obj);
if (baseProto === Types.buffer) {
return Buffer && Buffer.from(obj); // $lab:coverage:ignore$
}
if (baseProto === Types.date) {
return new Date(obj.getTime());
}
if (baseProto === Types.regex) {
return new RegExp(obj);
}
// Generic objects
const newObj = internals.base(obj, baseProto, options);
if (newObj === obj) {
return obj;
}
if (seen) {
seen.set(obj, newObj); // Set seen, since obj could recurse
}
if (baseProto === Types.set) {
for (const value of obj) {
newObj.add(clone(value, options, seen));
}
}
else if (baseProto === Types.map) {
for (const [key, value] of obj) {
newObj.set(key, clone(value, options, seen));
}
}
const keys = Utils.keys(obj, options);
for (const key of keys) {
if (key === '__proto__') {
continue;
}
if (baseProto === Types.array &&
key === 'length') {
newObj.length = obj.length;
continue;
}
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor) {
if (descriptor.get ||
descriptor.set) {
Object.defineProperty(newObj, key, descriptor);
}
else if (descriptor.enumerable) {
newObj[key] = clone(obj[key], options, seen);
}
else {
Object.defineProperty(newObj, key, { enumerable: false, writable: true, configurable: true, value: clone(obj[key], options, seen) });
}
}
else {
Object.defineProperty(newObj, key, {
enumerable: true,
writable: true,
configurable: true,
value: clone(obj[key], options, seen)
});
}
}
return newObj;
};
internals.cloneWithShallow = function (source, options) {
const keys = options.shallow;
options = Object.assign({}, options);
options.shallow = false;
const seen = new Map();
for (const key of keys) {
const ref = Reach(source, key);
if (typeof ref === 'object' ||
typeof ref === 'function') {
seen.set(ref, ref);
}
}
return internals.clone(source, options, seen);
};
internals.base = function (obj, baseProto, options) {
if (options.prototype === false) { // Defaults to true
if (internals.needsProtoHack.has(baseProto)) {
return new baseProto.constructor();
}
return baseProto === Types.array ? [] : {};
}
const proto = Object.getPrototypeOf(obj);
if (proto &&
proto.isImmutable) {
return obj;
}
if (baseProto === Types.array) {
const newObj = [];
if (proto !== baseProto) {
Object.setPrototypeOf(newObj, proto);
}
return newObj;
}
if (internals.needsProtoHack.has(baseProto)) {
const newObj = new proto.constructor();
if (proto !== baseProto) {
Object.setPrototypeOf(newObj, proto);
}
return newObj;
}
return Object.create(proto);
};
'use strict';
const Assert = require('./assert');
const DeepEqual = require('./deepEqual');
const EscapeRegex = require('./escapeRegex');
const Utils = require('./utils');
const internals = {};
module.exports = function (ref, values, options = {}) { // options: { deep, once, only, part, symbols }
/*
string -> string(s)
array -> item(s)
object -> key(s)
object -> object (key:value)
*/
if (typeof values !== 'object') {
values = [values];
}
Assert(!Array.isArray(values) || values.length, 'Values array cannot be empty');
// String
if (typeof ref === 'string') {
return internals.string(ref, values, options);
}
// Array
if (Array.isArray(ref)) {
return internals.array(ref, values, options);
}
// Object
Assert(typeof ref === 'object', 'Reference must be string or an object');
return internals.object(ref, values, options);
};
internals.array = function (ref, values, options) {
if (!Array.isArray(values)) {
values = [values];
}
if (!ref.length) {
return false;
}
if (options.only &&
options.once &&
ref.length !== values.length) {
return false;
}
let compare;
// Map values
const map = new Map();
for (const value of values) {
if (!options.deep ||
!value ||
typeof value !== 'object') {
const existing = map.get(value);
if (existing) {
++existing.allowed;
}
else {
map.set(value, { allowed: 1, hits: 0 });
}
}
else {
compare = compare || internals.compare(options);
let found = false;
for (const [key, existing] of map.entries()) {
if (compare(key, value)) {
++existing.allowed;
found = true;
break;
}
}
if (!found) {
map.set(value, { allowed: 1, hits: 0 });
}
}
}
// Lookup values
let hits = 0;
for (const item of ref) {
let match;
if (!options.deep ||
!item ||
typeof item !== 'object') {
match = map.get(item);
}
else {
compare = compare || internals.compare(options);
for (const [key, existing] of map.entries()) {
if (compare(key, item)) {
match = existing;
break;
}
}
}
if (match) {
++match.hits;
++hits;
if (options.once &&
match.hits > match.allowed) {
return false;
}
}
}
// Validate results
if (options.only &&
hits !== ref.length) {
return false;
}
for (const match of map.values()) {
if (match.hits === match.allowed) {
continue;
}
if (match.hits < match.allowed &&
!options.part) {
return false;
}
}
return !!hits;
};
internals.object = function (ref, values, options) {
Assert(options.once === undefined, 'Cannot use option once with object');
const keys = Utils.keys(ref, options);
if (!keys.length) {
return false;
}
// Keys list
if (Array.isArray(values)) {
return internals.array(keys, values, options);
}
// Key value pairs
const symbols = Object.getOwnPropertySymbols(values).filter((sym) => values.propertyIsEnumerable(sym));
const targets = [...Object.keys(values), ...symbols];
const compare = internals.compare(options);
const set = new Set(targets);
for (const key of keys) {
if (!set.has(key)) {
if (options.only) {
return false;
}
continue;
}
if (!compare(values[key], ref[key])) {
return false;
}
set.delete(key);
}
if (set.size) {
return options.part ? set.size < targets.length : false;
}
return true;
};
internals.string = function (ref, values, options) {
// Empty string
if (ref === '') {
return values.length === 1 && values[0] === '' || // '' contains ''
!options.once && !values.some((v) => v !== ''); // '' contains multiple '' if !once
}
// Map values
const map = new Map();
const patterns = [];
for (const value of values) {
Assert(typeof value === 'string', 'Cannot compare string reference to non-string value');
if (value) {
const existing = map.get(value);
if (existing) {
++existing.allowed;
}
else {
map.set(value, { allowed: 1, hits: 0 });
patterns.push(EscapeRegex(value));
}
}
else if (options.once ||
options.only) {
return false;
}
}
if (!patterns.length) { // Non-empty string contains unlimited empty string
return true;
}
// Match patterns
const regex = new RegExp(`(${patterns.join('|')})`, 'g');
const leftovers = ref.replace(regex, ($0, $1) => {
++map.get($1).hits;
return ''; // Remove from string
});
// Validate results
if (options.only &&
leftovers) {
return false;
}
let any = false;
for (const match of map.values()) {
if (match.hits) {
any = true;
}
if (match.hits === match.allowed) {
continue;
}
if (match.hits < match.allowed &&
!options.part) {
return false;
}
// match.hits > match.allowed
if (options.once) {
return false;
}
}
return !!any;
};
internals.compare = function (options) {
if (!options.deep) {
return internals.shallow;
}
const hasOnly = options.only !== undefined;
const hasPart = options.part !== undefined;
const flags = {
prototype: hasOnly ? options.only : hasPart ? !options.part : false,
part: hasOnly ? !options.only : hasPart ? options.part : false
};
return (a, b) => DeepEqual(a, b, flags);
};
internals.shallow = function (a, b) {
return a === b;
};
'use strict';
const Types = require('./types');
const internals = {
mismatched: null
};
module.exports = function (obj, ref, options) {
options = Object.assign({ prototype: true }, options);
return !!internals.isDeepEqual(obj, ref, options, []);
};
internals.isDeepEqual = function (obj, ref, options, seen) {
if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql
return obj !== 0 || 1 / obj === 1 / ref;
}
const type = typeof obj;
if (type !== typeof ref) {
return false;
}
if (obj === null ||
ref === null) {
return false;
}
if (type === 'function') {
if (!options.deepFunction ||
obj.toString() !== ref.toString()) {
return false;
}
// Continue as object
}
else if (type !== 'object') {
return obj !== obj && ref !== ref; // NaN
}
const instanceType = internals.getSharedType(obj, ref, !!options.prototype);
switch (instanceType) {
case Types.buffer:
return Buffer && Buffer.prototype.equals.call(obj, ref); // $lab:coverage:ignore$
case Types.promise:
return obj === ref;
case Types.regex:
return obj.toString() === ref.toString();
case internals.mismatched:
return false;
}
for (let i = seen.length - 1; i >= 0; --i) {
if (seen[i].isSame(obj, ref)) {
return true; // If previous comparison failed, it would have stopped execution
}
}
seen.push(new internals.SeenEntry(obj, ref));
try {
return !!internals.isDeepEqualObj(instanceType, obj, ref, options, seen);
}
finally {
seen.pop();
}
};
internals.getSharedType = function (obj, ref, checkPrototype) {
if (checkPrototype) {
if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) {
return internals.mismatched;
}
return Types.getInternalProto(obj);
}
const type = Types.getInternalProto(obj);
if (type !== Types.getInternalProto(ref)) {
return internals.mismatched;
}
return type;
};
internals.valueOf = function (obj) {
const objValueOf = obj.valueOf;
if (objValueOf === undefined) {
return obj;
}
try {
return objValueOf.call(obj);
}
catch (err) {
return err;
}
};
internals.hasOwnEnumerableProperty = function (obj, key) {
return Object.prototype.propertyIsEnumerable.call(obj, key);
};
internals.isSetSimpleEqual = function (obj, ref) {
for (const entry of Set.prototype.values.call(obj)) {
if (!Set.prototype.has.call(ref, entry)) {
return false;
}
}
return true;
};
internals.isDeepEqualObj = function (instanceType, obj, ref, options, seen) {
const { isDeepEqual, valueOf, hasOwnEnumerableProperty } = internals;
const { keys, getOwnPropertySymbols } = Object;
if (instanceType === Types.array) {
if (options.part) {
// Check if any index match any other index
for (const objValue of obj) {
for (const refValue of ref) {
if (isDeepEqual(objValue, refValue, options, seen)) {
return true;
}
}
}
}
else {
if (obj.length !== ref.length) {
return false;
}
for (let i = 0; i < obj.length; ++i) {
if (!isDeepEqual(obj[i], ref[i], options, seen)) {
return false;
}
}
return true;
}
}
else if (instanceType === Types.set) {
if (obj.size !== ref.size) {
return false;
}
if (!internals.isSetSimpleEqual(obj, ref)) {
// Check for deep equality
const ref2 = new Set(Set.prototype.values.call(ref));
for (const objEntry of Set.prototype.values.call(obj)) {
if (ref2.delete(objEntry)) {
continue;
}
let found = false;
for (const refEntry of ref2) {
if (isDeepEqual(objEntry, refEntry, options, seen)) {
ref2.delete(refEntry);
found = true;
break;
}
}
if (!found) {
return false;
}
}
}
}
else if (instanceType === Types.map) {
if (obj.size !== ref.size) {
return false;
}
for (const [key, value] of Map.prototype.entries.call(obj)) {
if (value === undefined && !Map.prototype.has.call(ref, key)) {
return false;
}
if (!isDeepEqual(value, Map.prototype.get.call(ref, key), options, seen)) {
return false;
}
}
}
else if (instanceType === Types.error) {
// Always check name and message
if (obj.name !== ref.name ||
obj.message !== ref.message) {
return false;
}
}
// Check .valueOf()
const valueOfObj = valueOf(obj);
const valueOfRef = valueOf(ref);
if ((obj !== valueOfObj || ref !== valueOfRef) &&
!isDeepEqual(valueOfObj, valueOfRef, options, seen)) {
return false;
}
// Check properties
const objKeys = keys(obj);
if (!options.part &&
objKeys.length !== keys(ref).length &&
!options.skip) {
return false;
}
let skipped = 0;
for (const key of objKeys) {
if (options.skip &&
options.skip.includes(key)) {
if (ref[key] === undefined) {
++skipped;
}
continue;
}
if (!hasOwnEnumerableProperty(ref, key)) {
return false;
}
if (!isDeepEqual(obj[key], ref[key], options, seen)) {
return false;
}
}
if (!options.part &&
objKeys.length - skipped !== keys(ref).length) {
return false;
}
// Check symbols
if (options.symbols !== false) { // Defaults to true
const objSymbols = getOwnPropertySymbols(obj);
const refSymbols = new Set(getOwnPropertySymbols(ref));
for (const key of objSymbols) {
if (!options.skip ||
!options.skip.includes(key)) {
if (hasOwnEnumerableProperty(obj, key)) {
if (!hasOwnEnumerableProperty(ref, key)) {
return false;
}
if (!isDeepEqual(obj[key], ref[key], options, seen)) {
return false;
}
}
else if (hasOwnEnumerableProperty(ref, key)) {
return false;
}
}
refSymbols.delete(key);
}
for (const key of refSymbols) {
if (hasOwnEnumerableProperty(ref, key)) {
return false;
}
}
}
return true;
};
internals.SeenEntry = class {
constructor(obj, ref) {
this.obj = obj;
this.ref = ref;
}
isSame(obj, ref) {
return this.obj === obj && this.ref === ref;
}
};
'use strict';
const Stringify = require('./stringify');
const internals = {};
module.exports = class extends Error {
constructor(args) {
const msgs = args
.filter((arg) => arg !== '')
.map((arg) => {
return typeof arg === 'string' ? arg : arg instanceof Error ? arg.message : Stringify(arg);
});
super(msgs.join(' ') || 'Unknown error');
if (typeof Error.captureStackTrace === 'function') { // $lab:coverage:ignore$
Error.captureStackTrace(this, exports.assert);
}
}
};
'use strict';
const Assert = require('./assert');
const internals = {};
module.exports = function (attribute) {
// Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
Assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')');
return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash
};
'use strict';
const internals = {};
module.exports = function (input) {
if (!input) {
return '';
}
let escaped = '';
for (let i = 0; i < input.length; ++i) {
const charCode = input.charCodeAt(i);
if (internals.isSafe(charCode)) {
escaped += input[i];
}
else {
escaped += internals.escapeHtmlChar(charCode);
}
}
return escaped;
};
internals.escapeHtmlChar = function (charCode) {
const namedEscape = internals.namedHtml[charCode];
if (typeof namedEscape !== 'undefined') {
return namedEscape;
}
if (charCode >= 256) {
return '&#' + charCode + ';';
}
const hexValue = charCode.toString(16).padStart(2, '0');
return `&#x${hexValue};`;
};
internals.isSafe = function (charCode) {
return (typeof internals.safeCharCodes[charCode] !== 'undefined');
};
internals.namedHtml = {
'38': '&amp;',
'60': '&lt;',
'62': '&gt;',
'34': '&quot;',
'160': '&nbsp;',
'162': '&cent;',
'163': '&pound;',
'164': '&curren;',
'169': '&copy;',
'174': '&reg;'
};
internals.safeCharCodes = (function () {
const safe = {};
for (let i = 32; i < 123; ++i) {
if ((i >= 97) || // a-z
(i >= 65 && i <= 90) || // A-Z
(i >= 48 && i <= 57) || // 0-9
i === 32 || // space
i === 46 || // .
i === 44 || // ,
i === 45 || // -
i === 58 || // :
i === 95) { // _
safe[i] = null;
}
}
return safe;
}());
'use strict';
const internals = {};
module.exports = function (input) {
if (!input) {
return '';
}
const lessThan = 0x3C;
const greaterThan = 0x3E;
const andSymbol = 0x26;
const lineSeperator = 0x2028;
// replace method
let charCode;
return input.replace(/[<>&\u2028\u2029]/g, (match) => {
charCode = match.charCodeAt(0);
if (charCode === lessThan) {
return '\\u003c';
}
if (charCode === greaterThan) {
return '\\u003e';
}
if (charCode === andSymbol) {
return '\\u0026';
}
if (charCode === lineSeperator) {
return '\\u2028';
}
return '\\u2029';
});
};
'use strict';
const internals = {};
module.exports = function (string) {
// Escape ^$.*+-?=!:|\/()[]{},
return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
};
'use strict';
const internals = {};
module.exports = internals.flatten = function (array, target) {
const result = target || [];
for (let i = 0; i < array.length; ++i) {
if (Array.isArray(array[i])) {
internals.flatten(array[i], result);
}
else {
result.push(array[i]);
}
}
return result;
};
'use strict';
const internals = {};
module.exports = function () { };
This diff is collapsed.
'use strict';
const internals = {};
module.exports = {
applyToDefaults: require('./applyToDefaults'),
assert: require('./assert'),
Bench: require('./bench'),
block: require('./block'),
clone: require('./clone'),
contain: require('./contain'),
deepEqual: require('./deepEqual'),
Error: require('./error'),
escapeHeaderAttribute: require('./escapeHeaderAttribute'),
escapeHtml: require('./escapeHtml'),
escapeJson: require('./escapeJson'),
escapeRegex: require('./escapeRegex'),
flatten: require('./flatten'),
ignore: require('./ignore'),
intersect: require('./intersect'),
isPromise: require('./isPromise'),
merge: require('./merge'),
once: require('./once'),
reach: require('./reach'),
reachTemplate: require('./reachTemplate'),
stringify: require('./stringify'),
wait: require('./wait')
};
This diff is collapsed.
'use strict';
const internals = {};
module.exports = function (promise) {
return !!promise && typeof promise.then === 'function';
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment