Comparing version 2.1.0 to 2.2.0
@@ -11,5 +11,4 @@ module.exports = { | ||
'plugin:@typescript-eslint/recommended', | ||
'plugin:@typescript-eslint/recommended-requiring-type-checking', | ||
'prettier/@typescript-eslint', | ||
// after 2.0 is released: | ||
// 'plugin:@typescript-eslint/recommended-requiring-type-checking', | ||
], | ||
@@ -63,2 +62,4 @@ parser: '@typescript-eslint/parser', | ||
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'], | ||
'@typescript-eslint/prefer-optional-chain': 'error', | ||
'@typescript-eslint/no-explicit-any': 'error', | ||
@@ -65,0 +66,0 @@ // '@typescript-eslint/no-non-null-assertion': 'off', |
@@ -8,2 +8,3 @@ { | ||
"activityBar.background": "#4884b2", | ||
"activityBar.activeBorder": "#712e54", | ||
"activityBar.foreground": "#e7e7e7", | ||
@@ -22,3 +23,3 @@ "activityBar.inactiveForeground": "#e7e7e799", | ||
"peacock.color": "#39698e", | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"typescript.tsdk": ".vscode/pnpify/typescript/lib", | ||
"eslint.alwaysShowStatus": true, | ||
@@ -33,3 +34,6 @@ "eslint.packageManager": "yarn", | ||
"tslint.packageManager": "yarn", | ||
"npm.packageManager": "yarn" | ||
"npm.packageManager": "yarn", | ||
"eslint.nodePath": ".vscode/pnpify", | ||
"prettier.prettierPath": ".vscode/pnpify/prettier", | ||
"eslint.enable": true | ||
} |
@@ -13,14 +13,8 @@ (function (global, factory) { | ||
} | ||
})(typeof globalThis === "object" ? globalThis : typeof self === "object" ? self : this, function (_exports) { | ||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports) { | ||
"use strict"; | ||
_exports.__esModule = true; | ||
_exports.unicodeSubstr = _exports.onlyChars = _exports.withoutChars = _exports.keepUniqueChars = _exports.default = void 0; | ||
_exports.onlyChars = _exports.withoutChars = _exports.keepUnique = _exports.default = void 0; | ||
function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
@@ -54,3 +48,2 @@ | ||
this.salt = salt; | ||
this.minLength = minLength; | ||
@@ -70,4 +63,11 @@ | ||
var uniqueAlphabet = keepUniqueChars(alphabet); | ||
var saltChars = _toConsumableArray(salt); | ||
var alphabetChars = _toConsumableArray(alphabet); | ||
var sepsChars = _toConsumableArray(seps); | ||
this.salt = saltChars; | ||
var uniqueAlphabet = keepUnique(alphabetChars); | ||
if (uniqueAlphabet.length < minAlphabetLength) { | ||
@@ -79,30 +79,38 @@ throw new Error("Hashids: alphabet must contain at least " + minAlphabetLength + " unique characters, provided: " + uniqueAlphabet); | ||
this.alphabet = withoutChars(uniqueAlphabet, seps); | ||
this.alphabet = withoutChars(uniqueAlphabet, sepsChars); | ||
/** `seps` should contain only characters present in `alphabet` */ | ||
var filteredSeps = onlyChars(seps, uniqueAlphabet); | ||
this.seps = shuffle(filteredSeps, salt); | ||
var filteredSeps = onlyChars(sepsChars, uniqueAlphabet); | ||
this.seps = shuffle(filteredSeps, saltChars); | ||
var sepsLength; | ||
var diff; | ||
if (_toConsumableArray(this.seps).length === 0 || _toConsumableArray(this.alphabet).length / _toConsumableArray(this.seps).length > sepDiv) { | ||
sepsLength = Math.ceil(_toConsumableArray(this.alphabet).length / sepDiv); | ||
if (this.seps.length === 0 || this.alphabet.length / this.seps.length > sepDiv) { | ||
sepsLength = Math.ceil(this.alphabet.length / sepDiv); | ||
if (sepsLength > _toConsumableArray(this.seps).length) { | ||
diff = sepsLength - _toConsumableArray(this.seps).length; | ||
this.seps += unicodeSubstr(this.alphabet, 0, diff); | ||
this.alphabet = unicodeSubstr(this.alphabet, diff); | ||
if (sepsLength > this.seps.length) { | ||
var _this$seps; | ||
diff = sepsLength - this.seps.length; | ||
(_this$seps = this.seps).push.apply(_this$seps, _toConsumableArray(this.alphabet.slice(0, diff))); | ||
this.alphabet = this.alphabet.slice(diff); | ||
} | ||
} | ||
this.alphabet = shuffle(this.alphabet, salt); | ||
var guardCount = Math.ceil(_toConsumableArray(this.alphabet).length / guardDiv); | ||
this.alphabet = shuffle(this.alphabet, saltChars); | ||
var guardCount = Math.ceil(this.alphabet.length / guardDiv); | ||
if (_toConsumableArray(this.alphabet).length < 3) { | ||
this.guards = unicodeSubstr(this.seps, 0, guardCount); | ||
this.seps = unicodeSubstr(this.seps, guardCount); | ||
if (this.alphabet.length < 3) { | ||
this.guards = this.seps.slice(0, guardCount); | ||
this.seps = this.seps.slice(guardCount); | ||
} else { | ||
this.guards = unicodeSubstr(this.alphabet, 0, guardCount); | ||
this.alphabet = unicodeSubstr(this.alphabet, guardCount); | ||
this.guards = this.alphabet.slice(0, guardCount); | ||
this.alphabet = this.alphabet.slice(guardCount); | ||
} | ||
this.guardsRegExp = makeAnyOfCharsRegExp(this.guards); | ||
this.sepsRegExp = makeAnyOfCharsRegExp(this.seps); | ||
this.allowedCharsRegExp = makeAtLeastSomeCharRegExp([].concat(_toConsumableArray(this.alphabet), _toConsumableArray(this.guards), _toConsumableArray(this.seps))); | ||
} | ||
@@ -140,3 +148,3 @@ | ||
return this._encode(numbers); | ||
return this._encode(numbers).join(''); | ||
}; | ||
@@ -194,3 +202,2 @@ | ||
var ret; | ||
var alphabet = this.alphabet; | ||
@@ -200,41 +207,48 @@ var numbersIdInt = numbers.reduce(function (last, number, i) { | ||
}, 0); | ||
ret = _toConsumableArray(alphabet)[numbersIdInt % _toConsumableArray(alphabet).length]; | ||
var lottery = ret; | ||
var ret = [alphabet[numbersIdInt % alphabet.length]]; | ||
var lottery = ret.slice(); | ||
var seps = this.seps; | ||
var guards = this.guards; | ||
numbers.forEach(function (number, i) { | ||
var _ret; | ||
var seps = _toConsumableArray(this.seps); | ||
var buffer = lottery.concat(_this.salt, alphabet); | ||
alphabet = shuffle(alphabet, buffer); | ||
var last = toAlphabet(number, alphabet); | ||
var guards = _toConsumableArray(this.guards); | ||
(_ret = ret).push.apply(_ret, _toConsumableArray(last)); | ||
numbers.forEach(function (number, i) { | ||
var buffer = lottery + _this.salt + alphabet; | ||
alphabet = shuffle(alphabet, unicodeSubstr(buffer, 0)); | ||
var last = toAlphabet(number, alphabet); | ||
ret += last; | ||
if (i + 1 < numbers.length) { | ||
var charCode = last.codePointAt(0) + i; | ||
var charCode = last[0].codePointAt(0) + i; | ||
var extraNumber = typeof number === 'bigint' ? Number(number % BigInt(charCode)) : number % charCode; | ||
ret += seps[extraNumber % seps.length]; | ||
ret.push(seps[extraNumber % seps.length]); | ||
} | ||
}); | ||
if (_toConsumableArray(ret).length < this.minLength) { | ||
var prefixGuardIndex = (numbersIdInt + _toConsumableArray(ret)[0].codePointAt(0)) % guards.length; | ||
ret = guards[prefixGuardIndex] + ret; | ||
if (ret.length < this.minLength) { | ||
var prefixGuardIndex = (numbersIdInt + ret[0].codePointAt(0)) % guards.length; | ||
ret.unshift(guards[prefixGuardIndex]); | ||
if (_toConsumableArray(ret).length < this.minLength) { | ||
var suffixGuardIndex = (numbersIdInt + _toConsumableArray(ret)[2].codePointAt(0)) % guards.length; | ||
ret = ret + guards[suffixGuardIndex]; | ||
if (ret.length < this.minLength) { | ||
var suffixGuardIndex = (numbersIdInt + ret[2].codePointAt(0)) % guards.length; | ||
ret.push(guards[suffixGuardIndex]); | ||
} | ||
} | ||
var halfLength = Math.floor(_toConsumableArray(alphabet).length / 2); | ||
var halfLength = Math.floor(alphabet.length / 2); | ||
while (_toConsumableArray(ret).length < this.minLength) { | ||
while (ret.length < this.minLength) { | ||
var _ret2, _ret3; | ||
alphabet = shuffle(alphabet, alphabet); | ||
ret = unicodeSubstr(alphabet, halfLength) + ret + unicodeSubstr(alphabet, 0, halfLength); | ||
var excess = _toConsumableArray(ret).length - this.minLength; | ||
(_ret2 = ret).unshift.apply(_ret2, _toConsumableArray(alphabet.slice(halfLength))); | ||
(_ret3 = ret).push.apply(_ret3, _toConsumableArray(alphabet.slice(0, halfLength))); | ||
var excess = ret.length - this.minLength; | ||
if (excess > 0) { | ||
ret = unicodeSubstr(ret, excess / 2, this.minLength); | ||
var halfOfExcess = excess / 2; | ||
ret = ret.slice(halfOfExcess, halfOfExcess + this.minLength); | ||
} | ||
@@ -247,51 +261,40 @@ } | ||
_proto.isValidId = function isValidId(id) { | ||
var _this2 = this; | ||
return _toConsumableArray(id).every(function (char) { | ||
return _this2.alphabet.includes(char) || _this2.guards.includes(char) || _this2.seps.includes(char); | ||
}); | ||
return this.allowedCharsRegExp.test(id); | ||
}; | ||
_proto._decode = function _decode(id) { | ||
var _this3 = this; | ||
if (!this.isValidId(id)) { | ||
throw new Error("The provided ID (" + id + ") is invalid, as it contains characters that do not exist in the alphabet (" + this.guards + this.seps + this.alphabet + ")"); | ||
throw new Error("The provided ID (" + id + ") is invalid, as it contains characters that do not exist in the alphabet (" + this.guards.join('') + this.seps.join('') + this.alphabet.join('') + ")"); | ||
} | ||
var idGuardsArray = splitAtMatch(id, function (char) { | ||
return _this3.guards.includes(char); | ||
}); | ||
var idGuardsArray = id.split(this.guardsRegExp); | ||
var splitIndex = idGuardsArray.length === 3 || idGuardsArray.length === 2 ? 1 : 0; | ||
var idBreakdown = idGuardsArray[splitIndex]; | ||
if (idBreakdown.length === 0) return []; | ||
var lotteryChar = idBreakdown[Symbol.iterator]().next().value; | ||
var idArray = idBreakdown.slice(lotteryChar.length).split(this.sepsRegExp); | ||
var lastAlphabet = this.alphabet; | ||
var result = []; | ||
var idBreakdownArray = _toConsumableArray(idBreakdown); | ||
for (var _iterator = idArray, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
if (idBreakdownArray.length === 0) return []; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref = _i.value; | ||
} | ||
var _idBreakdownArray = _toArray(idBreakdownArray), | ||
lotteryChar = _idBreakdownArray[0], | ||
chars = _idBreakdownArray.slice(1); | ||
var subId = _ref; | ||
var buffer = [lotteryChar].concat(_toConsumableArray(this.salt), _toConsumableArray(lastAlphabet)); | ||
var nextAlphabet = shuffle(lastAlphabet, buffer.slice(0, lastAlphabet.length)); | ||
result.push(fromAlphabet(_toConsumableArray(subId), nextAlphabet)); | ||
lastAlphabet = nextAlphabet; | ||
} // if the result is different from what we'd expect, we return an empty result (malformed input): | ||
var rest = chars.join(''); | ||
var idArray = splitAtMatch(rest, function (char) { | ||
return _this3.seps.includes(char); | ||
}); | ||
var _idArray$reduce = idArray.reduce(function (_ref, subId) { | ||
var result = _ref.result, | ||
lastAlphabet = _ref.lastAlphabet; | ||
var buffer = lotteryChar + _this3.salt + lastAlphabet; | ||
var nextAlphabet = shuffle(lastAlphabet, unicodeSubstr(buffer, 0, _toConsumableArray(lastAlphabet).length)); | ||
return { | ||
result: [].concat(_toConsumableArray(result), [fromAlphabet(subId, nextAlphabet)]), | ||
lastAlphabet: nextAlphabet | ||
}; | ||
}, { | ||
result: [], | ||
lastAlphabet: this.alphabet | ||
}), | ||
result = _idArray$reduce.result; | ||
if (this._encode(result) !== id) return []; | ||
if (this._encode(result).join('') !== id) return []; | ||
return result; | ||
@@ -308,18 +311,12 @@ }; | ||
var keepUniqueChars = function keepUniqueChars(str) { | ||
return Array.from(new Set(str)).join(''); | ||
var keepUnique = function keepUnique(content) { | ||
return Array.from(new Set(content)); | ||
}; | ||
_exports.keepUniqueChars = keepUniqueChars; | ||
_exports.keepUnique = keepUnique; | ||
var withoutChars = function withoutChars(_ref2, _ref3) { | ||
var _ref4 = _toArray(_ref2), | ||
str = _ref4.slice(0); | ||
var _ref5 = _toArray(_ref3), | ||
without = _ref5.slice(0); | ||
return str.filter(function (char) { | ||
return !without.includes(char); | ||
}).join(''); | ||
var withoutChars = function withoutChars(chars, _withoutChars) { | ||
return chars.filter(function (char) { | ||
return !_withoutChars.includes(char); | ||
}); | ||
}; | ||
@@ -329,12 +326,6 @@ | ||
var onlyChars = function onlyChars(_ref6, _ref7) { | ||
var _ref8 = _toArray(_ref6), | ||
str = _ref8.slice(0); | ||
var _ref9 = _toArray(_ref7), | ||
only = _ref9.slice(0); | ||
return str.filter(function (char) { | ||
return only.includes(char); | ||
}).join(''); | ||
var onlyChars = function onlyChars(chars, keepChars) { | ||
return chars.filter(function (char) { | ||
return keepChars.includes(char); | ||
}); | ||
}; | ||
@@ -344,11 +335,2 @@ | ||
var unicodeSubstr = function unicodeSubstr(_ref10, from, to) { | ||
var _ref11 = _toArray(_ref10), | ||
str = _ref11.slice(0); | ||
return str.slice(from, to === undefined ? undefined : from + to).join(''); | ||
}; | ||
_exports.unicodeSubstr = unicodeSubstr; | ||
var isIntegerNumber = function isIntegerNumber(n) { | ||
@@ -362,38 +344,32 @@ return typeof n === 'bigint' || !Number.isNaN(Number(n)) && Math.floor(Number(n)) === n; | ||
function shuffle(alphabet, _ref12) { | ||
var _ref13 = _toArray(_ref12), | ||
salt = _ref13.slice(0); | ||
function shuffle(alphabetChars, saltChars) { | ||
if (saltChars.length === 0) { | ||
return alphabetChars; | ||
} | ||
var integer; | ||
var transformed = alphabetChars.slice(); | ||
if (!salt.length) { | ||
return alphabet; | ||
} | ||
for (var i = transformed.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= saltChars.length; | ||
p += integer = saltChars[v].codePointAt(0); | ||
var j = (integer + v + p) % i; // swap characters at positions i and j | ||
var alphabetChars = _toConsumableArray(alphabet); | ||
for (var i = alphabetChars.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= salt.length; | ||
p += integer = salt[v].codePointAt(0); | ||
var j = (integer + v + p) % i // swap characters at positions i and j | ||
; | ||
var _ref14 = [alphabetChars[i], alphabetChars[j]]; | ||
alphabetChars[j] = _ref14[0]; | ||
alphabetChars[i] = _ref14[1]; | ||
var a = transformed[i]; | ||
var b = transformed[j]; | ||
transformed[j] = a; | ||
transformed[i] = b; | ||
} | ||
return alphabetChars.join(''); | ||
return transformed; | ||
} | ||
var toAlphabet = function toAlphabet(input, _ref15) { | ||
var _ref16 = _toArray(_ref15), | ||
alphabet = _ref16.slice(0); | ||
var toAlphabet = function toAlphabet(input, alphabetChars) { | ||
var id = []; | ||
var id = ''; | ||
if (typeof input === 'bigint') { | ||
var alphabetLength = BigInt(alphabet.length); | ||
var alphabetLength = BigInt(alphabetChars.length); | ||
do { | ||
id = alphabet[Number(input % alphabetLength)] + id; | ||
id.unshift(alphabetChars[Number(input % alphabetLength)]); | ||
input = input / alphabetLength; | ||
@@ -403,4 +379,4 @@ } while (input > BigInt(0)); | ||
do { | ||
id = alphabet[input % alphabet.length] + id; | ||
input = Math.floor(input / alphabet.length); | ||
id.unshift(alphabetChars[input % alphabetChars.length]); | ||
input = Math.floor(input / alphabetChars.length); | ||
} while (input > 0); | ||
@@ -412,25 +388,15 @@ } | ||
var fromAlphabet = function fromAlphabet(_ref17, _ref18) { | ||
var _ref19 = _toArray(_ref17), | ||
input = _ref19.slice(0); | ||
var fromAlphabet = function fromAlphabet(inputChars, alphabetChars) { | ||
return inputChars.reduce(function (carry, item) { | ||
var index = alphabetChars.indexOf(item); | ||
var _ref20 = _toArray(_ref18), | ||
alphabet = _ref20.slice(0); | ||
return input.map(function (item) { | ||
var index = alphabet.indexOf(item); | ||
if (index === -1) { | ||
var inputString = input.join(''); | ||
var alphabetString = alphabet.join(''); | ||
throw new Error("The provided ID (" + inputString + ") is invalid, as it contains characters that do not exist in the alphabet (" + alphabetString + ")"); | ||
throw new Error("The provided ID (" + inputChars.join('') + ") is invalid, as it contains characters that do not exist in the alphabet (" + alphabetChars.join('') + ")"); | ||
} | ||
return index; | ||
}).reduce(function (carry, index) { | ||
if (typeof carry === 'bigint') { | ||
return carry * BigInt(alphabet.length) + BigInt(index); | ||
return carry * BigInt(alphabetChars.length) + BigInt(index); | ||
} | ||
var value = carry * alphabet.length + index; | ||
var value = carry * alphabetChars.length + index; | ||
var isSafeValue = Number.isSafeInteger(value); | ||
@@ -442,3 +408,3 @@ | ||
if (typeof BigInt === 'function') { | ||
return BigInt(carry) * BigInt(alphabet.length) + BigInt(index); | ||
return BigInt(carry) * BigInt(alphabetChars.length) + BigInt(index); | ||
} else { | ||
@@ -452,11 +418,2 @@ // we do not have support for BigInt: | ||
var splitAtMatch = function splitAtMatch(_ref21, match) { | ||
var _ref22 = _toArray(_ref21), | ||
chars = _ref22.slice(0); | ||
return chars.reduce(function (groups, char) { | ||
return match(char) ? [].concat(_toConsumableArray(groups), ['']) : [].concat(_toConsumableArray(groups.slice(0, -1)), [groups[groups.length - 1] + char]); | ||
}, ['']); | ||
}; | ||
var safeToParseNumberRegExp = /^\+?[0-9]+$/; | ||
@@ -467,5 +424,3 @@ | ||
}; | ||
/** note: this doesn't need to support unicode, since it's used to split hex strings only */ | ||
var splitAtIntervalAndMap = function splitAtIntervalAndMap(str, nth, map) { | ||
@@ -478,4 +433,28 @@ return Array.from({ | ||
}; | ||
var makeAnyOfCharsRegExp = function makeAnyOfCharsRegExp(chars) { | ||
return new RegExp(chars.map(function (char) { | ||
return escapeRegExp(char); | ||
}) // we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort(function (a, b) { | ||
return b.length - a.length; | ||
}).join('|')); | ||
}; | ||
var makeAtLeastSomeCharRegExp = function makeAtLeastSomeCharRegExp(chars) { | ||
return new RegExp("^[" + chars.map(function (char) { | ||
return escapeRegExp(char); | ||
}) // we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort(function (a, b) { | ||
return b.length - a.length; | ||
}).join('') + "]+$"); | ||
}; | ||
var escapeRegExp = function escapeRegExp(text) { | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
}; | ||
}); | ||
//# sourceMappingURL=hashids.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,e){if("function"==typeof define&&define.amd)define("Hashids",["exports"],e);else if("undefined"!=typeof exports)e(exports);else{var n={exports:{}};e(n.exports),t.Hashids=n.exports}}("object"==typeof globalThis?globalThis:"object"==typeof self?self:this,(function(t){"use strict";function e(t){return function(t){if(Array.isArray(t))return t}(t)||r(t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function n(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||r(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function r(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}t.__esModule=!0,t.unicodeSubstr=t.onlyChars=t.withoutChars=t.keepUniqueChars=t.default=void 0;var i=function(){function t(t,e,r,i){if(void 0===t&&(t=""),void 0===e&&(e=0),void 0===r&&(r="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"),void 0===i&&(i="cfhistuCFHISTU"),this.salt=t,this.minLength=e,"number"!=typeof e)throw new TypeError("Hashids: Provided 'minLength' has to be a number (is "+typeof e+")");if("string"!=typeof t)throw new TypeError("Hashids: Provided 'salt' has to be a string (is "+typeof t+")");if("string"!=typeof r)throw new TypeError("Hashids: Provided alphabet has to be a string (is "+typeof r+")");var f=h(r);if(f.length<o)throw new Error("Hashids: alphabet must contain at least "+o+" unique characters, provided: "+f);this.alphabet=u(f,i);var d,p,v=l(i,f);this.seps=g(v,t),(0===n(this.seps).length||n(this.alphabet).length/n(this.seps).length>s)&&(d=Math.ceil(n(this.alphabet).length/s))>n(this.seps).length&&(p=d-n(this.seps).length,this.seps+=c(this.alphabet,0,p),this.alphabet=c(this.alphabet,p)),this.alphabet=g(this.alphabet,t);var b=Math.ceil(n(this.alphabet).length/a);n(this.alphabet).length<3?(this.guards=c(this.seps,0,b),this.seps=c(this.seps,b)):(this.guards=c(this.alphabet,0,b),this.alphabet=c(this.alphabet,b))}var r=t.prototype;return r.encode=function(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;i<e;i++)r[i-1]=arguments[i];var o="";return(r=Array.isArray(t)?t:[].concat(n(null!=t?[t]:[]),n(r))).length?(r.every(f)||(r=r.map((function(t){return"bigint"==typeof t||"number"==typeof t?t:m(String(t))}))),r.every(d)?this._encode(r):o):o},r.decode=function(t){return t&&"string"==typeof t&&0!==t.length?this._decode(t):[]},r.encodeHex=function(t){switch(typeof t){case"bigint":t=t.toString(16);break;case"string":if(!/^[0-9a-fA-F]+$/.test(t))return"";break;default:throw new Error("Hashids: The provided value is neither a string, nor a BigInt (got: "+typeof t+")")}var e=w(t,12,(function(t){return parseInt("1"+t,16)}));return this.encode(e)},r.decodeHex=function(t){return this.decode(t).map((function(t){return t.toString(16).slice(1)})).join("")},r._encode=function(t){var e,r=this,i=this.alphabet,o=t.reduce((function(t,e,n){return t+("bigint"==typeof e?Number(e%BigInt(n+100)):e%(n+100))}),0),s=e=n(i)[o%n(i).length],a=n(this.seps),h=n(this.guards);if(t.forEach((function(n,o){var h=s+r.salt+i;i=g(i,c(h,0));var u=p(n,i);if(e+=u,o+1<t.length){var l=u.codePointAt(0)+o,f="bigint"==typeof n?Number(n%BigInt(l)):n%l;e+=a[f%a.length]}})),n(e).length<this.minLength){var u=(o+n(e)[0].codePointAt(0))%h.length;if(n(e=h[u]+e).length<this.minLength){var l=(o+n(e)[2].codePointAt(0))%h.length;e+=h[l]}}for(var f=Math.floor(n(i).length/2);n(e).length<this.minLength;){i=g(i,i);var d=n(e=c(i,f)+e+c(i,0,f)).length-this.minLength;d>0&&(e=c(e,d/2,this.minLength))}return e},r.isValidId=function(t){var e=this;return n(t).every((function(t){return e.alphabet.includes(t)||e.guards.includes(t)||e.seps.includes(t)}))},r._decode=function(t){var r=this;if(!this.isValidId(t))throw new Error("The provided ID ("+t+") is invalid, as it contains characters that do not exist in the alphabet ("+this.guards+this.seps+this.alphabet+")");var i=b(t,(function(t){return r.guards.includes(t)})),o=n(i[3===i.length||2===i.length?1:0]);if(0===o.length)return[];var s=e(o),a=s[0],h=s.slice(1).join(""),u=b(h,(function(t){return r.seps.includes(t)})).reduce((function(t,e){var i=t.result,o=t.lastAlphabet,s=a+r.salt+o,h=g(o,c(s,0,n(o).length));return{result:[].concat(n(i),[v(e,h)]),lastAlphabet:h}}),{result:[],lastAlphabet:this.alphabet}).result;return this._encode(u)!==t?[]:u},t}();t.default=i;var o=16,s=3.5,a=12,h=function(t){return Array.from(new Set(t)).join("")};t.keepUniqueChars=h;var u=function(t,n){var r=e(t).slice(0),i=e(n).slice(0);return r.filter((function(t){return!i.includes(t)})).join("")};t.withoutChars=u;var l=function(t,n){var r=e(t).slice(0),i=e(n).slice(0);return r.filter((function(t){return i.includes(t)})).join("")};t.onlyChars=l;var c=function(t,n,r){return e(t).slice(0).slice(n,void 0===r?void 0:n+r).join("")};t.unicodeSubstr=c;var f=function(t){return"bigint"==typeof t||!Number.isNaN(Number(t))&&Math.floor(Number(t))===t},d=function(t){return"bigint"==typeof t||t>=0&&Number.isSafeInteger(t)};function g(t,r){var i,o=e(r).slice(0);if(!o.length)return t;for(var s=n(t),a=s.length-1,h=0,u=0;a>0;a--,h++){u+=i=o[h%=o.length].codePointAt(0);var l=(i+h+u)%a,c=[s[a],s[l]];s[l]=c[0],s[a]=c[1]}return s.join("")}var p=function(t,n){var r=e(n).slice(0),i="";if("bigint"==typeof t){var o=BigInt(r.length);do{i=r[Number(t%o)]+i,t/=o}while(t>BigInt(0))}else do{i=r[t%r.length]+i,t=Math.floor(t/r.length)}while(t>0);return i},v=function(t,n){var r=e(t).slice(0),i=e(n).slice(0);return r.map((function(t){var e=i.indexOf(t);if(-1===e){var n=r.join(""),o=i.join("");throw new Error("The provided ID ("+n+") is invalid, as it contains characters that do not exist in the alphabet ("+o+")")}return e})).reduce((function(t,e){if("bigint"==typeof t)return t*BigInt(i.length)+BigInt(e);var n=t*i.length+e;if(Number.isSafeInteger(n))return n;if("function"==typeof BigInt)return BigInt(t)*BigInt(i.length)+BigInt(e);throw new Error("Unable to decode the provided string, due to lack of support for BigInt numbers in the current environment")}),0)},b=function(t,r){return e(t).slice(0).reduce((function(t,e){return r(e)?[].concat(n(t),[""]):[].concat(n(t.slice(0,-1)),[t[t.length-1]+e])}),[""])},y=/^\+?[0-9]+$/,m=function(t){return y.test(t)?parseInt(t,10):NaN},w=function(t,e,n){return Array.from({length:Math.ceil(t.length/e)},(function(r,i){return n(t.slice(i*e,(i+1)*e))}))}})); | ||
!function(t,e){if("function"==typeof define&&define.amd)define("Hashids",["exports"],e);else if("undefined"!=typeof exports)e(exports);else{var n={exports:{}};e(n.exports),t.Hashids=n.exports}}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:this,(function(t){"use strict";function e(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}t.__esModule=!0,t.onlyChars=t.withoutChars=t.keepUnique=t.default=void 0;var n=function(){function t(t,n,l,u){if(void 0===t&&(t=""),void 0===n&&(n=0),void 0===l&&(l="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"),void 0===u&&(u="cfhistuCFHISTU"),this.minLength=n,"number"!=typeof n)throw new TypeError("Hashids: Provided 'minLength' has to be a number (is "+typeof n+")");if("string"!=typeof t)throw new TypeError("Hashids: Provided 'salt' has to be a string (is "+typeof t+")");if("string"!=typeof l)throw new TypeError("Hashids: Provided alphabet has to be a string (is "+typeof l+")");var p=e(t),c=e(l),g=e(u);this.salt=p;var d=o(c);if(d.length<i)throw new Error("Hashids: alphabet must contain at least "+i+" unique characters, provided: "+d);this.alphabet=a(d,g);var b,m,w,I=h(g,d);(this.seps=f(I,p),0===this.seps.length||this.alphabet.length/this.seps.length>r)&&((b=Math.ceil(this.alphabet.length/r))>this.seps.length&&(m=b-this.seps.length,(w=this.seps).push.apply(w,e(this.alphabet.slice(0,m))),this.alphabet=this.alphabet.slice(m)));this.alphabet=f(this.alphabet,p);var x=Math.ceil(this.alphabet.length/s);this.alphabet.length<3?(this.guards=this.seps.slice(0,x),this.seps=this.seps.slice(x)):(this.guards=this.alphabet.slice(0,x),this.alphabet=this.alphabet.slice(x)),this.guardsRegExp=v(this.guards),this.sepsRegExp=v(this.seps),this.allowedCharsRegExp=y([].concat(e(this.alphabet),e(this.guards),e(this.seps)))}var n=t.prototype;return n.encode=function(t){for(var n=arguments.length,i=new Array(n>1?n-1:0),r=1;r<n;r++)i[r-1]=arguments[r];var s="";return(i=Array.isArray(t)?t:[].concat(e(null!=t?[t]:[]),e(i))).length?(i.every(l)||(i=i.map((function(t){return"bigint"==typeof t||"number"==typeof t?t:d(String(t))}))),i.every(u)?this._encode(i).join(""):s):s},n.decode=function(t){return t&&"string"==typeof t&&0!==t.length?this._decode(t):[]},n.encodeHex=function(t){switch(typeof t){case"bigint":t=t.toString(16);break;case"string":if(!/^[0-9a-fA-F]+$/.test(t))return"";break;default:throw new Error("Hashids: The provided value is neither a string, nor a BigInt (got: "+typeof t+")")}var e=b(t,12,(function(t){return parseInt("1"+t,16)}));return this.encode(e)},n.decodeHex=function(t){return this.decode(t).map((function(t){return t.toString(16).slice(1)})).join("")},n._encode=function(t){var n=this,i=this.alphabet,r=t.reduce((function(t,e,n){return t+("bigint"==typeof e?Number(e%BigInt(n+100)):e%(n+100))}),0),s=[i[r%i.length]],o=s.slice(),a=this.seps,h=this.guards;if(t.forEach((function(r,h){var l,u=o.concat(n.salt,i);i=f(i,u);var c=p(r,i);if((l=s).push.apply(l,e(c)),h+1<t.length){var g=c[0].codePointAt(0)+h,d="bigint"==typeof r?Number(r%BigInt(g)):r%g;s.push(a[d%a.length])}})),s.length<this.minLength){var l=(r+s[0].codePointAt(0))%h.length;if(s.unshift(h[l]),s.length<this.minLength){var u=(r+s[2].codePointAt(0))%h.length;s.push(h[u])}}for(var c=Math.floor(i.length/2);s.length<this.minLength;){var g,d;i=f(i,i),(g=s).unshift.apply(g,e(i.slice(c))),(d=s).push.apply(d,e(i.slice(0,c)));var b=s.length-this.minLength;if(b>0){var v=b/2;s=s.slice(v,v+this.minLength)}}return s},n.isValidId=function(t){return this.allowedCharsRegExp.test(t)},n._decode=function(t){if(!this.isValidId(t))throw new Error("The provided ID ("+t+") is invalid, as it contains characters that do not exist in the alphabet ("+this.guards.join("")+this.seps.join("")+this.alphabet.join("")+")");var n=t.split(this.guardsRegExp),i=n[3===n.length||2===n.length?1:0];if(0===i.length)return[];var r=i[Symbol.iterator]().next().value,s=i.slice(r.length).split(this.sepsRegExp),o=this.alphabet,a=[],h=s,l=Array.isArray(h),u=0;for(h=l?h:h[Symbol.iterator]();;){var p;if(l){if(u>=h.length)break;p=h[u++]}else{if((u=h.next()).done)break;p=u.value}var g=p,d=f(o,[r].concat(e(this.salt),e(o)).slice(0,o.length));a.push(c(e(g),d)),o=d}return this._encode(a).join("")!==t?[]:a},t}();t.default=n;var i=16,r=3.5,s=12,o=function(t){return Array.from(new Set(t))};t.keepUnique=o;var a=function(t,e){return t.filter((function(t){return!e.includes(t)}))};t.withoutChars=a;var h=function(t,e){return t.filter((function(t){return e.includes(t)}))};t.onlyChars=h;var l=function(t){return"bigint"==typeof t||!Number.isNaN(Number(t))&&Math.floor(Number(t))===t},u=function(t){return"bigint"==typeof t||t>=0&&Number.isSafeInteger(t)};function f(t,e){if(0===e.length)return t;for(var n,i=t.slice(),r=i.length-1,s=0,o=0;r>0;r--,s++){o+=n=e[s%=e.length].codePointAt(0);var a=(n+s+o)%r,h=i[r],l=i[a];i[a]=h,i[r]=l}return i}var p=function(t,e){var n=[];if("bigint"==typeof t){var i=BigInt(e.length);do{n.unshift(e[Number(t%i)]),t/=i}while(t>BigInt(0))}else do{n.unshift(e[t%e.length]),t=Math.floor(t/e.length)}while(t>0);return n},c=function(t,e){return t.reduce((function(n,i){var r=e.indexOf(i);if(-1===r)throw new Error("The provided ID ("+t.join("")+") is invalid, as it contains characters that do not exist in the alphabet ("+e.join("")+")");if("bigint"==typeof n)return n*BigInt(e.length)+BigInt(r);var s=n*e.length+r;if(Number.isSafeInteger(s))return s;if("function"==typeof BigInt)return BigInt(n)*BigInt(e.length)+BigInt(r);throw new Error("Unable to decode the provided string, due to lack of support for BigInt numbers in the current environment")}),0)},g=/^\+?[0-9]+$/,d=function(t){return g.test(t)?parseInt(t,10):NaN},b=function(t,e,n){return Array.from({length:Math.ceil(t.length/e)},(function(i,r){return n(t.slice(r*e,(r+1)*e))}))},v=function(t){return new RegExp(t.map((function(t){return m(t)})).sort((function(t,e){return e.length-t.length})).join("|"))},y=function(t){return new RegExp("^["+t.map((function(t){return m(t)})).sort((function(t,e){return e.length-t.length})).join("")+"]+$")},m=function(t){return t.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")}})); | ||
//# sourceMappingURL=hashids.min.js.map |
316
esm/index.js
@@ -1,7 +0,1 @@ | ||
function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
@@ -35,3 +29,2 @@ | ||
this.salt = salt; | ||
this.minLength = minLength; | ||
@@ -51,4 +44,11 @@ | ||
var uniqueAlphabet = keepUniqueChars(alphabet); | ||
var saltChars = _toConsumableArray(salt); | ||
var alphabetChars = _toConsumableArray(alphabet); | ||
var sepsChars = _toConsumableArray(seps); | ||
this.salt = saltChars; | ||
var uniqueAlphabet = keepUnique(alphabetChars); | ||
if (uniqueAlphabet.length < minAlphabetLength) { | ||
@@ -60,30 +60,38 @@ throw new Error("Hashids: alphabet must contain at least " + minAlphabetLength + " unique characters, provided: " + uniqueAlphabet); | ||
this.alphabet = withoutChars(uniqueAlphabet, seps); | ||
this.alphabet = withoutChars(uniqueAlphabet, sepsChars); | ||
/** `seps` should contain only characters present in `alphabet` */ | ||
var filteredSeps = onlyChars(seps, uniqueAlphabet); | ||
this.seps = shuffle(filteredSeps, salt); | ||
var filteredSeps = onlyChars(sepsChars, uniqueAlphabet); | ||
this.seps = shuffle(filteredSeps, saltChars); | ||
var sepsLength; | ||
var diff; | ||
if (_toConsumableArray(this.seps).length === 0 || _toConsumableArray(this.alphabet).length / _toConsumableArray(this.seps).length > sepDiv) { | ||
sepsLength = Math.ceil(_toConsumableArray(this.alphabet).length / sepDiv); | ||
if (this.seps.length === 0 || this.alphabet.length / this.seps.length > sepDiv) { | ||
sepsLength = Math.ceil(this.alphabet.length / sepDiv); | ||
if (sepsLength > _toConsumableArray(this.seps).length) { | ||
diff = sepsLength - _toConsumableArray(this.seps).length; | ||
this.seps += unicodeSubstr(this.alphabet, 0, diff); | ||
this.alphabet = unicodeSubstr(this.alphabet, diff); | ||
if (sepsLength > this.seps.length) { | ||
var _this$seps; | ||
diff = sepsLength - this.seps.length; | ||
(_this$seps = this.seps).push.apply(_this$seps, _toConsumableArray(this.alphabet.slice(0, diff))); | ||
this.alphabet = this.alphabet.slice(diff); | ||
} | ||
} | ||
this.alphabet = shuffle(this.alphabet, salt); | ||
var guardCount = Math.ceil(_toConsumableArray(this.alphabet).length / guardDiv); | ||
this.alphabet = shuffle(this.alphabet, saltChars); | ||
var guardCount = Math.ceil(this.alphabet.length / guardDiv); | ||
if (_toConsumableArray(this.alphabet).length < 3) { | ||
this.guards = unicodeSubstr(this.seps, 0, guardCount); | ||
this.seps = unicodeSubstr(this.seps, guardCount); | ||
if (this.alphabet.length < 3) { | ||
this.guards = this.seps.slice(0, guardCount); | ||
this.seps = this.seps.slice(guardCount); | ||
} else { | ||
this.guards = unicodeSubstr(this.alphabet, 0, guardCount); | ||
this.alphabet = unicodeSubstr(this.alphabet, guardCount); | ||
this.guards = this.alphabet.slice(0, guardCount); | ||
this.alphabet = this.alphabet.slice(guardCount); | ||
} | ||
this.guardsRegExp = makeAnyOfCharsRegExp(this.guards); | ||
this.sepsRegExp = makeAnyOfCharsRegExp(this.seps); | ||
this.allowedCharsRegExp = makeAtLeastSomeCharRegExp([].concat(_toConsumableArray(this.alphabet), _toConsumableArray(this.guards), _toConsumableArray(this.seps))); | ||
} | ||
@@ -121,3 +129,3 @@ | ||
return this._encode(numbers); | ||
return this._encode(numbers).join(''); | ||
}; | ||
@@ -175,3 +183,2 @@ | ||
var ret; | ||
var alphabet = this.alphabet; | ||
@@ -181,41 +188,48 @@ var numbersIdInt = numbers.reduce(function (last, number, i) { | ||
}, 0); | ||
ret = _toConsumableArray(alphabet)[numbersIdInt % _toConsumableArray(alphabet).length]; | ||
var lottery = ret; | ||
var ret = [alphabet[numbersIdInt % alphabet.length]]; | ||
var lottery = ret.slice(); | ||
var seps = this.seps; | ||
var guards = this.guards; | ||
numbers.forEach(function (number, i) { | ||
var _ret; | ||
var seps = _toConsumableArray(this.seps); | ||
var buffer = lottery.concat(_this.salt, alphabet); | ||
alphabet = shuffle(alphabet, buffer); | ||
var last = toAlphabet(number, alphabet); | ||
var guards = _toConsumableArray(this.guards); | ||
(_ret = ret).push.apply(_ret, _toConsumableArray(last)); | ||
numbers.forEach(function (number, i) { | ||
var buffer = lottery + _this.salt + alphabet; | ||
alphabet = shuffle(alphabet, unicodeSubstr(buffer, 0)); | ||
var last = toAlphabet(number, alphabet); | ||
ret += last; | ||
if (i + 1 < numbers.length) { | ||
var charCode = last.codePointAt(0) + i; | ||
var charCode = last[0].codePointAt(0) + i; | ||
var extraNumber = typeof number === 'bigint' ? Number(number % BigInt(charCode)) : number % charCode; | ||
ret += seps[extraNumber % seps.length]; | ||
ret.push(seps[extraNumber % seps.length]); | ||
} | ||
}); | ||
if (_toConsumableArray(ret).length < this.minLength) { | ||
var prefixGuardIndex = (numbersIdInt + _toConsumableArray(ret)[0].codePointAt(0)) % guards.length; | ||
ret = guards[prefixGuardIndex] + ret; | ||
if (ret.length < this.minLength) { | ||
var prefixGuardIndex = (numbersIdInt + ret[0].codePointAt(0)) % guards.length; | ||
ret.unshift(guards[prefixGuardIndex]); | ||
if (_toConsumableArray(ret).length < this.minLength) { | ||
var suffixGuardIndex = (numbersIdInt + _toConsumableArray(ret)[2].codePointAt(0)) % guards.length; | ||
ret = ret + guards[suffixGuardIndex]; | ||
if (ret.length < this.minLength) { | ||
var suffixGuardIndex = (numbersIdInt + ret[2].codePointAt(0)) % guards.length; | ||
ret.push(guards[suffixGuardIndex]); | ||
} | ||
} | ||
var halfLength = Math.floor(_toConsumableArray(alphabet).length / 2); | ||
var halfLength = Math.floor(alphabet.length / 2); | ||
while (_toConsumableArray(ret).length < this.minLength) { | ||
while (ret.length < this.minLength) { | ||
var _ret2, _ret3; | ||
alphabet = shuffle(alphabet, alphabet); | ||
ret = unicodeSubstr(alphabet, halfLength) + ret + unicodeSubstr(alphabet, 0, halfLength); | ||
var excess = _toConsumableArray(ret).length - this.minLength; | ||
(_ret2 = ret).unshift.apply(_ret2, _toConsumableArray(alphabet.slice(halfLength))); | ||
(_ret3 = ret).push.apply(_ret3, _toConsumableArray(alphabet.slice(0, halfLength))); | ||
var excess = ret.length - this.minLength; | ||
if (excess > 0) { | ||
ret = unicodeSubstr(ret, excess / 2, this.minLength); | ||
var halfOfExcess = excess / 2; | ||
ret = ret.slice(halfOfExcess, halfOfExcess + this.minLength); | ||
} | ||
@@ -228,51 +242,40 @@ } | ||
_proto.isValidId = function isValidId(id) { | ||
var _this2 = this; | ||
return _toConsumableArray(id).every(function (char) { | ||
return _this2.alphabet.includes(char) || _this2.guards.includes(char) || _this2.seps.includes(char); | ||
}); | ||
return this.allowedCharsRegExp.test(id); | ||
}; | ||
_proto._decode = function _decode(id) { | ||
var _this3 = this; | ||
if (!this.isValidId(id)) { | ||
throw new Error("The provided ID (" + id + ") is invalid, as it contains characters that do not exist in the alphabet (" + this.guards + this.seps + this.alphabet + ")"); | ||
throw new Error("The provided ID (" + id + ") is invalid, as it contains characters that do not exist in the alphabet (" + this.guards.join('') + this.seps.join('') + this.alphabet.join('') + ")"); | ||
} | ||
var idGuardsArray = splitAtMatch(id, function (char) { | ||
return _this3.guards.includes(char); | ||
}); | ||
var idGuardsArray = id.split(this.guardsRegExp); | ||
var splitIndex = idGuardsArray.length === 3 || idGuardsArray.length === 2 ? 1 : 0; | ||
var idBreakdown = idGuardsArray[splitIndex]; | ||
if (idBreakdown.length === 0) return []; | ||
var lotteryChar = idBreakdown[Symbol.iterator]().next().value; | ||
var idArray = idBreakdown.slice(lotteryChar.length).split(this.sepsRegExp); | ||
var lastAlphabet = this.alphabet; | ||
var result = []; | ||
var idBreakdownArray = _toConsumableArray(idBreakdown); | ||
for (var _iterator = idArray, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
if (idBreakdownArray.length === 0) return []; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref = _i.value; | ||
} | ||
var _idBreakdownArray = _toArray(idBreakdownArray), | ||
lotteryChar = _idBreakdownArray[0], | ||
chars = _idBreakdownArray.slice(1); | ||
var subId = _ref; | ||
var buffer = [lotteryChar].concat(_toConsumableArray(this.salt), _toConsumableArray(lastAlphabet)); | ||
var nextAlphabet = shuffle(lastAlphabet, buffer.slice(0, lastAlphabet.length)); | ||
result.push(fromAlphabet(_toConsumableArray(subId), nextAlphabet)); | ||
lastAlphabet = nextAlphabet; | ||
} // if the result is different from what we'd expect, we return an empty result (malformed input): | ||
var rest = chars.join(''); | ||
var idArray = splitAtMatch(rest, function (char) { | ||
return _this3.seps.includes(char); | ||
}); | ||
var _idArray$reduce = idArray.reduce(function (_ref, subId) { | ||
var result = _ref.result, | ||
lastAlphabet = _ref.lastAlphabet; | ||
var buffer = lotteryChar + _this3.salt + lastAlphabet; | ||
var nextAlphabet = shuffle(lastAlphabet, unicodeSubstr(buffer, 0, _toConsumableArray(lastAlphabet).length)); | ||
return { | ||
result: [].concat(_toConsumableArray(result), [fromAlphabet(subId, nextAlphabet)]), | ||
lastAlphabet: nextAlphabet | ||
}; | ||
}, { | ||
result: [], | ||
lastAlphabet: this.alphabet | ||
}), | ||
result = _idArray$reduce.result; | ||
if (this._encode(result) !== id) return []; | ||
if (this._encode(result).join('') !== id) return []; | ||
return result; | ||
@@ -288,34 +291,16 @@ }; | ||
var guardDiv = 12; | ||
export var keepUniqueChars = function keepUniqueChars(str) { | ||
return Array.from(new Set(str)).join(''); | ||
export var keepUnique = function keepUnique(content) { | ||
return Array.from(new Set(content)); | ||
}; | ||
export var withoutChars = function withoutChars(_ref2, _ref3) { | ||
var _ref4 = _toArray(_ref2), | ||
str = _ref4.slice(0); | ||
var _ref5 = _toArray(_ref3), | ||
without = _ref5.slice(0); | ||
return str.filter(function (char) { | ||
return !without.includes(char); | ||
}).join(''); | ||
export var withoutChars = function withoutChars(chars, _withoutChars) { | ||
return chars.filter(function (char) { | ||
return !_withoutChars.includes(char); | ||
}); | ||
}; | ||
export var onlyChars = function onlyChars(_ref6, _ref7) { | ||
var _ref8 = _toArray(_ref6), | ||
str = _ref8.slice(0); | ||
var _ref9 = _toArray(_ref7), | ||
only = _ref9.slice(0); | ||
return str.filter(function (char) { | ||
return only.includes(char); | ||
}).join(''); | ||
export var onlyChars = function onlyChars(chars, keepChars) { | ||
return chars.filter(function (char) { | ||
return keepChars.includes(char); | ||
}); | ||
}; | ||
export var unicodeSubstr = function unicodeSubstr(_ref10, from, to) { | ||
var _ref11 = _toArray(_ref10), | ||
str = _ref11.slice(0); | ||
return str.slice(from, to === undefined ? undefined : from + to).join(''); | ||
}; | ||
var isIntegerNumber = function isIntegerNumber(n) { | ||
@@ -329,38 +314,32 @@ return typeof n === 'bigint' || !Number.isNaN(Number(n)) && Math.floor(Number(n)) === n; | ||
function shuffle(alphabet, _ref12) { | ||
var _ref13 = _toArray(_ref12), | ||
salt = _ref13.slice(0); | ||
function shuffle(alphabetChars, saltChars) { | ||
if (saltChars.length === 0) { | ||
return alphabetChars; | ||
} | ||
var integer; | ||
var transformed = alphabetChars.slice(); | ||
if (!salt.length) { | ||
return alphabet; | ||
} | ||
for (var i = transformed.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= saltChars.length; | ||
p += integer = saltChars[v].codePointAt(0); | ||
var j = (integer + v + p) % i; // swap characters at positions i and j | ||
var alphabetChars = _toConsumableArray(alphabet); | ||
for (var i = alphabetChars.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= salt.length; | ||
p += integer = salt[v].codePointAt(0); | ||
var j = (integer + v + p) % i // swap characters at positions i and j | ||
; | ||
var _ref14 = [alphabetChars[i], alphabetChars[j]]; | ||
alphabetChars[j] = _ref14[0]; | ||
alphabetChars[i] = _ref14[1]; | ||
var a = transformed[i]; | ||
var b = transformed[j]; | ||
transformed[j] = a; | ||
transformed[i] = b; | ||
} | ||
return alphabetChars.join(''); | ||
return transformed; | ||
} | ||
var toAlphabet = function toAlphabet(input, _ref15) { | ||
var _ref16 = _toArray(_ref15), | ||
alphabet = _ref16.slice(0); | ||
var toAlphabet = function toAlphabet(input, alphabetChars) { | ||
var id = []; | ||
var id = ''; | ||
if (typeof input === 'bigint') { | ||
var alphabetLength = BigInt(alphabet.length); | ||
var alphabetLength = BigInt(alphabetChars.length); | ||
do { | ||
id = alphabet[Number(input % alphabetLength)] + id; | ||
id.unshift(alphabetChars[Number(input % alphabetLength)]); | ||
input = input / alphabetLength; | ||
@@ -370,4 +349,4 @@ } while (input > BigInt(0)); | ||
do { | ||
id = alphabet[input % alphabet.length] + id; | ||
input = Math.floor(input / alphabet.length); | ||
id.unshift(alphabetChars[input % alphabetChars.length]); | ||
input = Math.floor(input / alphabetChars.length); | ||
} while (input > 0); | ||
@@ -379,25 +358,15 @@ } | ||
var fromAlphabet = function fromAlphabet(_ref17, _ref18) { | ||
var _ref19 = _toArray(_ref17), | ||
input = _ref19.slice(0); | ||
var fromAlphabet = function fromAlphabet(inputChars, alphabetChars) { | ||
return inputChars.reduce(function (carry, item) { | ||
var index = alphabetChars.indexOf(item); | ||
var _ref20 = _toArray(_ref18), | ||
alphabet = _ref20.slice(0); | ||
return input.map(function (item) { | ||
var index = alphabet.indexOf(item); | ||
if (index === -1) { | ||
var inputString = input.join(''); | ||
var alphabetString = alphabet.join(''); | ||
throw new Error("The provided ID (" + inputString + ") is invalid, as it contains characters that do not exist in the alphabet (" + alphabetString + ")"); | ||
throw new Error("The provided ID (" + inputChars.join('') + ") is invalid, as it contains characters that do not exist in the alphabet (" + alphabetChars.join('') + ")"); | ||
} | ||
return index; | ||
}).reduce(function (carry, index) { | ||
if (typeof carry === 'bigint') { | ||
return carry * BigInt(alphabet.length) + BigInt(index); | ||
return carry * BigInt(alphabetChars.length) + BigInt(index); | ||
} | ||
var value = carry * alphabet.length + index; | ||
var value = carry * alphabetChars.length + index; | ||
var isSafeValue = Number.isSafeInteger(value); | ||
@@ -409,3 +378,3 @@ | ||
if (typeof BigInt === 'function') { | ||
return BigInt(carry) * BigInt(alphabet.length) + BigInt(index); | ||
return BigInt(carry) * BigInt(alphabetChars.length) + BigInt(index); | ||
} else { | ||
@@ -419,11 +388,2 @@ // we do not have support for BigInt: | ||
var splitAtMatch = function splitAtMatch(_ref21, match) { | ||
var _ref22 = _toArray(_ref21), | ||
chars = _ref22.slice(0); | ||
return chars.reduce(function (groups, char) { | ||
return match(char) ? [].concat(_toConsumableArray(groups), ['']) : [].concat(_toConsumableArray(groups.slice(0, -1)), [groups[groups.length - 1] + char]); | ||
}, ['']); | ||
}; | ||
var safeToParseNumberRegExp = /^\+?[0-9]+$/; | ||
@@ -434,5 +394,3 @@ | ||
}; | ||
/** note: this doesn't need to support unicode, since it's used to split hex strings only */ | ||
var splitAtIntervalAndMap = function splitAtIntervalAndMap(str, nth, map) { | ||
@@ -446,2 +404,26 @@ return Array.from({ | ||
var makeAnyOfCharsRegExp = function makeAnyOfCharsRegExp(chars) { | ||
return new RegExp(chars.map(function (char) { | ||
return escapeRegExp(char); | ||
}) // we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort(function (a, b) { | ||
return b.length - a.length; | ||
}).join('|')); | ||
}; | ||
var makeAtLeastSomeCharRegExp = function makeAtLeastSomeCharRegExp(chars) { | ||
return new RegExp("^[" + chars.map(function (char) { | ||
return escapeRegExp(char); | ||
}) // we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort(function (a, b) { | ||
return b.length - a.length; | ||
}).join('') + "]+$"); | ||
}; | ||
var escapeRegExp = function escapeRegExp(text) { | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
}; | ||
//# sourceMappingURL=index.js.map |
type NumberLike = number | bigint | ||
export default class Hashids { | ||
private alphabet: string | ||
private seps: string | ||
private guards: string | ||
private alphabet: string[] | ||
private seps: string[] | ||
private guards: string[] | ||
private salt: string[] | ||
private guardsRegExp: RegExp | ||
private sepsRegExp: RegExp | ||
private allowedCharsRegExp: RegExp | ||
public constructor( | ||
private salt = '', | ||
salt = '', | ||
private minLength = 0, | ||
@@ -30,4 +34,10 @@ alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', | ||
const uniqueAlphabet = keepUniqueChars(alphabet) | ||
const saltChars = [...salt] | ||
const alphabetChars = [...alphabet] | ||
const sepsChars = [...seps] | ||
this.salt = saltChars | ||
const uniqueAlphabet = keepUnique(alphabetChars) | ||
if (uniqueAlphabet.length < minAlphabetLength) { | ||
@@ -40,6 +50,6 @@ throw new Error( | ||
/** `alphabet` should not contains `seps` */ | ||
this.alphabet = withoutChars(uniqueAlphabet, seps) | ||
this.alphabet = withoutChars(uniqueAlphabet, sepsChars) | ||
/** `seps` should contain only characters present in `alphabet` */ | ||
const filteredSeps = onlyChars(seps, uniqueAlphabet) | ||
this.seps = shuffle(filteredSeps, salt) | ||
const filteredSeps = onlyChars(sepsChars, uniqueAlphabet) | ||
this.seps = shuffle(filteredSeps, saltChars) | ||
@@ -50,24 +60,32 @@ let sepsLength | ||
if ( | ||
[...this.seps].length === 0 || | ||
[...this.alphabet].length / [...this.seps].length > sepDiv | ||
this.seps.length === 0 || | ||
this.alphabet.length / this.seps.length > sepDiv | ||
) { | ||
sepsLength = Math.ceil([...this.alphabet].length / sepDiv) | ||
sepsLength = Math.ceil(this.alphabet.length / sepDiv) | ||
if (sepsLength > [...this.seps].length) { | ||
diff = sepsLength - [...this.seps].length | ||
this.seps += unicodeSubstr(this.alphabet, 0, diff) | ||
this.alphabet = unicodeSubstr(this.alphabet, diff) | ||
if (sepsLength > this.seps.length) { | ||
diff = sepsLength - this.seps.length | ||
this.seps.push(...this.alphabet.slice(0, diff)) | ||
this.alphabet = this.alphabet.slice(diff) | ||
} | ||
} | ||
this.alphabet = shuffle(this.alphabet, salt) | ||
const guardCount = Math.ceil([...this.alphabet].length / guardDiv) | ||
this.alphabet = shuffle(this.alphabet, saltChars) | ||
const guardCount = Math.ceil(this.alphabet.length / guardDiv) | ||
if ([...this.alphabet].length < 3) { | ||
this.guards = unicodeSubstr(this.seps, 0, guardCount) | ||
this.seps = unicodeSubstr(this.seps, guardCount) | ||
if (this.alphabet.length < 3) { | ||
this.guards = this.seps.slice(0, guardCount) | ||
this.seps = this.seps.slice(guardCount) | ||
} else { | ||
this.guards = unicodeSubstr(this.alphabet, 0, guardCount) | ||
this.alphabet = unicodeSubstr(this.alphabet, guardCount) | ||
this.guards = this.alphabet.slice(0, guardCount) | ||
this.alphabet = this.alphabet.slice(guardCount) | ||
} | ||
this.guardsRegExp = makeAnyOfCharsRegExp(this.guards) | ||
this.sepsRegExp = makeAnyOfCharsRegExp(this.seps) | ||
this.allowedCharsRegExp = makeAtLeastSomeCharRegExp([ | ||
...this.alphabet, | ||
...this.guards, | ||
...this.seps, | ||
]) | ||
} | ||
@@ -109,3 +127,3 @@ | ||
return this._encode(numbers as number[]) | ||
return this._encode(numbers as number[]).join('') | ||
} | ||
@@ -159,4 +177,3 @@ | ||
private _encode(numbers: NumberLike[]): string { | ||
let ret: string | ||
private _encode(numbers: NumberLike[]): string[] { | ||
let alphabet = this.alphabet | ||
@@ -173,18 +190,18 @@ | ||
ret = [...alphabet][numbersIdInt % [...alphabet].length] | ||
const lottery = ret | ||
let ret: string[] = [alphabet[numbersIdInt % alphabet.length]] | ||
const lottery = ret.slice() | ||
const seps = [...this.seps] | ||
const guards = [...this.guards] | ||
const seps = this.seps | ||
const guards = this.guards | ||
numbers.forEach((number, i) => { | ||
const buffer = lottery + this.salt + alphabet | ||
const buffer = lottery.concat(this.salt, alphabet) | ||
alphabet = shuffle(alphabet, unicodeSubstr(buffer, 0)) | ||
alphabet = shuffle(alphabet, buffer) | ||
const last = toAlphabet(number, alphabet) | ||
ret += last | ||
ret.push(...last) | ||
if (i + 1 < numbers.length) { | ||
const charCode = last.codePointAt(0)! + i | ||
const charCode = last[0].codePointAt(0)! + i | ||
const extraNumber = | ||
@@ -194,29 +211,28 @@ typeof number === 'bigint' | ||
: number % charCode | ||
ret += seps[extraNumber % seps.length] | ||
ret.push(seps[extraNumber % seps.length]) | ||
} | ||
}) | ||
if ([...ret].length < this.minLength) { | ||
if (ret.length < this.minLength) { | ||
const prefixGuardIndex = | ||
(numbersIdInt + [...ret][0].codePointAt(0)!) % guards.length | ||
ret = guards[prefixGuardIndex] + ret | ||
(numbersIdInt + ret[0].codePointAt(0)!) % guards.length | ||
ret.unshift(guards[prefixGuardIndex]) | ||
if ([...ret].length < this.minLength) { | ||
if (ret.length < this.minLength) { | ||
const suffixGuardIndex = | ||
(numbersIdInt + [...ret][2].codePointAt(0)!) % guards.length | ||
ret = ret + guards[suffixGuardIndex] | ||
(numbersIdInt + ret[2].codePointAt(0)!) % guards.length | ||
ret.push(guards[suffixGuardIndex]) | ||
} | ||
} | ||
const halfLength = Math.floor([...alphabet].length / 2) | ||
while ([...ret].length < this.minLength) { | ||
const halfLength = Math.floor(alphabet.length / 2) | ||
while (ret.length < this.minLength) { | ||
alphabet = shuffle(alphabet, alphabet) | ||
ret = | ||
unicodeSubstr(alphabet, halfLength) + | ||
ret + | ||
unicodeSubstr(alphabet, 0, halfLength) | ||
ret.unshift(...alphabet.slice(halfLength)) | ||
ret.push(...alphabet.slice(0, halfLength)) | ||
const excess = [...ret].length - this.minLength | ||
const excess = ret.length - this.minLength | ||
if (excess > 0) { | ||
ret = unicodeSubstr(ret, excess / 2, this.minLength) | ||
const halfOfExcess = excess / 2 | ||
ret = ret.slice(halfOfExcess, halfOfExcess + this.minLength) | ||
} | ||
@@ -229,8 +245,3 @@ } | ||
public isValidId(id: string): boolean { | ||
return [...id].every( | ||
(char) => | ||
this.alphabet.includes(char) || | ||
this.guards.includes(char) || | ||
this.seps.includes(char), | ||
) | ||
return this.allowedCharsRegExp.test(id) | ||
} | ||
@@ -241,6 +252,8 @@ | ||
throw new Error( | ||
`The provided ID (${id}) is invalid, as it contains characters that do not exist in the alphabet (${this.guards}${this.seps}${this.alphabet})`, | ||
`The provided ID (${id}) is invalid, as it contains characters that do not exist in the alphabet (${this.guards.join( | ||
'', | ||
)}${this.seps.join('')}${this.alphabet.join('')})`, | ||
) | ||
} | ||
const idGuardsArray = splitAtMatch(id, (char) => this.guards.includes(char)) | ||
const idGuardsArray = id.split(this.guardsRegExp) | ||
const splitIndex = | ||
@@ -250,25 +263,22 @@ idGuardsArray.length === 3 || idGuardsArray.length === 2 ? 1 : 0 | ||
const idBreakdown = idGuardsArray[splitIndex] | ||
const idBreakdownArray = [...idBreakdown] | ||
if (idBreakdownArray.length === 0) return [] | ||
if (idBreakdown.length === 0) return [] | ||
const [lotteryChar, ...chars] = idBreakdownArray | ||
const rest = chars.join('') | ||
const idArray = splitAtMatch(rest, (char) => this.seps.includes(char)) | ||
const lotteryChar = idBreakdown[Symbol.iterator]().next().value as string | ||
const idArray = idBreakdown.slice(lotteryChar.length).split(this.sepsRegExp) | ||
const {result} = idArray.reduce( | ||
({result, lastAlphabet}, subId) => { | ||
const buffer = lotteryChar + this.salt + lastAlphabet | ||
const nextAlphabet = shuffle( | ||
lastAlphabet, | ||
unicodeSubstr(buffer, 0, [...lastAlphabet].length), | ||
) | ||
return { | ||
result: [...result, fromAlphabet(subId, nextAlphabet)], | ||
lastAlphabet: nextAlphabet, | ||
} | ||
}, | ||
{result: [] as NumberLike[], lastAlphabet: this.alphabet}, | ||
) | ||
let lastAlphabet: string[] = this.alphabet | ||
const result: NumberLike[] = [] | ||
if (this._encode(result) !== id) return [] | ||
for (const subId of idArray) { | ||
const buffer = [lotteryChar, ...this.salt, ...lastAlphabet] | ||
const nextAlphabet = shuffle( | ||
lastAlphabet, | ||
buffer.slice(0, lastAlphabet.length), | ||
) | ||
result.push(fromAlphabet([...subId], nextAlphabet)) | ||
lastAlphabet = nextAlphabet | ||
} | ||
// if the result is different from what we'd expect, we return an empty result (malformed input): | ||
if (this._encode(result).join('') !== id) return [] | ||
return result | ||
@@ -282,14 +292,13 @@ } | ||
export const keepUniqueChars = (str: string) => | ||
Array.from(new Set(str)).join('') | ||
export const keepUnique = <T>(content: Iterable<T>): T[] => | ||
Array.from(new Set(content)) | ||
export const withoutChars = ([...str]: string, [...without]: string) => | ||
str.filter((char) => !without.includes(char)).join('') | ||
export const withoutChars = ( | ||
chars: string[], | ||
withoutChars: string[], | ||
): string[] => chars.filter((char) => !withoutChars.includes(char)) | ||
export const onlyChars = ([...str]: string, [...only]: string) => | ||
str.filter((char) => only.includes(char)).join('') | ||
export const onlyChars = (chars: string[], keepChars: string[]): string[] => | ||
chars.filter((char) => keepChars.includes(char)) | ||
export const unicodeSubstr = ([...str]: string, from: number, to?: number) => | ||
str.slice(from, to === undefined ? undefined : from + to).join('') | ||
const isIntegerNumber = (n: NumberLike | string) => | ||
@@ -302,30 +311,32 @@ typeof n === 'bigint' || | ||
function shuffle(alphabet: string, [...salt]: string) { | ||
let integer: number | ||
if (!salt.length) { | ||
return alphabet | ||
function shuffle(alphabetChars: string[], saltChars: string[]): string[] { | ||
if (saltChars.length === 0) { | ||
return alphabetChars | ||
} | ||
const alphabetChars = [...alphabet] | ||
let integer: number | ||
const transformed = alphabetChars.slice() | ||
for (let i = alphabetChars.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= salt.length | ||
p += integer = salt[v].codePointAt(0)! | ||
for (let i = transformed.length - 1, v = 0, p = 0; i > 0; i--, v++) { | ||
v %= saltChars.length | ||
p += integer = saltChars[v].codePointAt(0)! | ||
const j = (integer + v + p) % i | ||
// swap characters at positions i and j | ||
;[alphabetChars[j], alphabetChars[i]] = [alphabetChars[i], alphabetChars[j]] | ||
// swap characters at positions i and j | ||
const a = transformed[i] | ||
const b = transformed[j] | ||
transformed[j] = a | ||
transformed[i] = b | ||
} | ||
return alphabetChars.join('') | ||
return transformed | ||
} | ||
const toAlphabet = (input: NumberLike, [...alphabet]: string) => { | ||
let id = '' | ||
const toAlphabet = (input: NumberLike, alphabetChars: string[]): string[] => { | ||
const id: string[] = [] | ||
if (typeof input === 'bigint') { | ||
const alphabetLength = BigInt(alphabet.length) | ||
const alphabetLength = BigInt(alphabetChars.length) | ||
do { | ||
id = alphabet[Number(input % alphabetLength)] + id | ||
id.unshift(alphabetChars[Number(input % alphabetLength)]) | ||
input = input / alphabetLength | ||
@@ -335,4 +346,4 @@ } while (input > BigInt(0)) | ||
do { | ||
id = alphabet[input % alphabet.length] + id | ||
input = Math.floor(input / alphabet.length) | ||
id.unshift(alphabetChars[input % alphabetChars.length]) | ||
input = Math.floor(input / alphabetChars.length) | ||
} while (input > 0) | ||
@@ -344,47 +355,36 @@ } | ||
const fromAlphabet = ([...input]: string, [...alphabet]: string) => | ||
input | ||
.map((item) => { | ||
const index = alphabet.indexOf(item) | ||
if (index === -1) { | ||
const inputString = input.join('') | ||
const alphabetString = alphabet.join('') | ||
const fromAlphabet = ( | ||
inputChars: string[], | ||
alphabetChars: string[], | ||
): NumberLike => | ||
inputChars.reduce((carry, item) => { | ||
const index = alphabetChars.indexOf(item) | ||
if (index === -1) { | ||
throw new Error( | ||
`The provided ID (${inputChars.join( | ||
'', | ||
)}) is invalid, as it contains characters that do not exist in the alphabet (${alphabetChars.join( | ||
'', | ||
)})`, | ||
) | ||
} | ||
if (typeof carry === 'bigint') { | ||
return carry * BigInt(alphabetChars.length) + BigInt(index) | ||
} | ||
const value = carry * alphabetChars.length + index | ||
const isSafeValue = Number.isSafeInteger(value) | ||
if (isSafeValue) { | ||
return value | ||
} else { | ||
if (typeof BigInt === 'function') { | ||
return BigInt(carry) * BigInt(alphabetChars.length) + BigInt(index) | ||
} else { | ||
// we do not have support for BigInt: | ||
throw new Error( | ||
`The provided ID (${inputString}) is invalid, as it contains characters that do not exist in the alphabet (${alphabetString})`, | ||
`Unable to decode the provided string, due to lack of support for BigInt numbers in the current environment`, | ||
) | ||
} | ||
return index | ||
}) | ||
.reduce( | ||
(carry, index) => { | ||
if (typeof carry === 'bigint') { | ||
return carry * BigInt(alphabet.length) + BigInt(index) | ||
} | ||
const value = carry * alphabet.length + index | ||
const isSafeValue = Number.isSafeInteger(value) | ||
if (isSafeValue) { | ||
return value | ||
} else { | ||
if (typeof BigInt === 'function') { | ||
return BigInt(carry) * BigInt(alphabet.length) + BigInt(index) | ||
} else { | ||
// we do not have support for BigInt: | ||
throw new Error( | ||
`Unable to decode the provided string, due to lack of support for BigInt numbers in the current environment`, | ||
) | ||
} | ||
} | ||
}, | ||
0 as NumberLike, | ||
) | ||
} | ||
}, 0 as NumberLike) | ||
const splitAtMatch = ([...chars]: string, match: (char: string) => boolean) => | ||
chars.reduce( | ||
(groups, char) => | ||
match(char) | ||
? [...groups, ''] | ||
: [...groups.slice(0, -1), groups[groups.length - 1] + char], | ||
[''], | ||
) | ||
const safeToParseNumberRegExp = /^\+?[0-9]+$/ | ||
@@ -394,3 +394,2 @@ const safeParseInt10 = (str: string) => | ||
/** note: this doesn't need to support unicode, since it's used to split hex strings only */ | ||
const splitAtIntervalAndMap = <T>( | ||
@@ -404,1 +403,24 @@ str: string, | ||
) | ||
const makeAnyOfCharsRegExp = (chars: string[]) => | ||
new RegExp( | ||
chars | ||
.map((char) => escapeRegExp(char)) | ||
// we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort((a, b) => b.length - a.length) | ||
.join('|'), | ||
) | ||
const makeAtLeastSomeCharRegExp = (chars: string[]) => | ||
new RegExp( | ||
`^[${chars | ||
.map((char) => escapeRegExp(char)) | ||
// we need to sort these from longest to shortest, | ||
// as they may contain multibyte unicode characters (these should come first) | ||
.sort((a, b) => b.length - a.length) | ||
.join('')}]+$`, | ||
) | ||
const escapeRegExp = (text: string) => | ||
text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') |
@@ -17,3 +17,3 @@ { | ||
], | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"homepage": "http://hashids.org/javascript", | ||
@@ -30,2 +30,7 @@ "repository": { | ||
"browser": "dist/hashids.min", | ||
"exports": { | ||
"import": "./esm/index.js", | ||
"require": "./cjs/index.js", | ||
"browser": "dist/hashids.min" | ||
}, | ||
"scripts": { | ||
@@ -43,3 +48,4 @@ "lint": "eslint lib/* tests/*", | ||
"all": "yarn run lint && yarn run coverage && yarn run build && yarn run clean", | ||
"semantic-release": "semantic-release" | ||
"semantic-release": "semantic-release", | ||
"benchmark": "yarn ts-node -O '{\"module\": \"commonjs\"}' -T tests/benchmark" | ||
}, | ||
@@ -57,27 +63,32 @@ "husky": { | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.7.0", | ||
"@babel/core": "^7.7.2", | ||
"@babel/plugin-syntax-bigint": "^7.4.4", | ||
"@babel/preset-env": "^7.7.1", | ||
"@babel/preset-typescript": "^7.7.2", | ||
"@babel/register": "^7.7.0", | ||
"@types/jest": "^24.0.22", | ||
"@types/node": "^12.12.7", | ||
"@typescript-eslint/eslint-plugin": "^2.6.1", | ||
"@typescript-eslint/parser": "^2.6.1", | ||
"coveralls": "^3.0.7", | ||
"eslint": "^6.6.0", | ||
"eslint-config-prettier": "^6.5.0", | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.8.4", | ||
"@babel/plugin-syntax-bigint": "^7.8.3", | ||
"@babel/plugin-transform-destructuring": "^7.8.3", | ||
"@babel/plugin-transform-spread": "^7.8.3", | ||
"@babel/preset-env": "^7.8.4", | ||
"@babel/preset-typescript": "^7.8.3", | ||
"@babel/register": "^7.8.3", | ||
"@types/jest": "^25.1.1", | ||
"@types/node": "^13.7.0", | ||
"@typescript-eslint/eslint-plugin": "^2.19.0", | ||
"@typescript-eslint/parser": "^2.19.0", | ||
"@yarnpkg/pnpify": "^2.0.0-rc.17", | ||
"coveralls": "^3.0.9", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.10.0", | ||
"eslint-import-resolver-node": "^0.3.3", | ||
"eslint-plugin-eslint-comments": "^3.1.2", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-jest": "^23.0.3", | ||
"husky": "^3.0.9", | ||
"jest": "^24.9.0", | ||
"eslint-plugin-import": "^2.20.1", | ||
"eslint-plugin-jest": "^23.6.0", | ||
"husky": "^4.2.1", | ||
"jest": "^25.1.0", | ||
"nodemark": "^0.3.0", | ||
"prettier": "^1.19.1", | ||
"semantic-release": "^16.0.0-beta.31", | ||
"terser": "^4.3.9", | ||
"ts-node": "^8.4.1", | ||
"typescript": "^3.7.2" | ||
"require-from-web": "^1.1.1", | ||
"semantic-release": "^17.0.2", | ||
"terser": "^4.6.3", | ||
"ts-node": "^8.6.2", | ||
"typescript": "^3.7.5" | ||
}, | ||
@@ -84,0 +95,0 @@ "license": "MIT", |
@@ -7,3 +7,2 @@ [![hashids](http://hashids.org/public/img/hashids.gif 'Hashids')](http://hashids.org/) | ||
[![NPM version][npm-version-image]][npm-url] | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/niieani/hashids.js.svg)](https://greenkeeper.io/) | ||
[![License][license-image]][license-url] | ||
@@ -14,2 +13,4 @@ [![Chat][chat-image]][chat-url] | ||
[![Play with it using CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/hashids-demo-54qvc?fontsize=14&hidenavigation=1&module=%2Fsrc%2Findex.ts&theme=dark) | ||
## Getting started | ||
@@ -19,9 +20,9 @@ | ||
- [node.js](https://nodejs.org): `yarn add hashids` | ||
- [bower](http://bower.io/): `bower install hashids` | ||
- [jam](http://jamjs.org/): `jam install hashids` | ||
```shell | ||
yarn add hashids | ||
``` | ||
(or just use the code at `dist/hashids.js`) | ||
Use in **ESM-compatible** environments (webpack, modern browsers): | ||
#### Use in **ESM-compatible** environments (webpack, modern browsers) | ||
@@ -35,3 +36,3 @@ ```javascript | ||
Use in **Node.js**: | ||
#### Use in **CommonJS** environments (most often **Node.js**) | ||
@@ -45,4 +46,6 @@ ```javascript | ||
Use in the browser without ESM (wherever **ES5** is supported; 5KB): | ||
Note: When using Node that supports [conditional exports](https://nodejs.org/api/esm.html#esm_conditional_exports), `require('hashids')` will also work. | ||
#### Use as global in the browser (wherever **ES5** is supported; 5KB) | ||
```javascript | ||
@@ -58,11 +61,6 @@ <script type="text/javascript" src="hashids.min.js"></script> | ||
Use in **TypeScript**: | ||
#### Use in **TypeScript**: | ||
```typescript | ||
import Hashids from 'hashids'; | ||
Import or require based on the environment (see above). | ||
const hashids = new Hashids(); | ||
console.log(hashids.encode(1)); | ||
``` | ||
If you get errors stating: `Cannot find name 'BigInt'`, add [`"esnext.bigint"`](https://github.com/microsoft/TypeScript/blob/master/src/lib/esnext.bigint.d.ts) or [`"esnext"`](https://github.com/microsoft/TypeScript/blob/master/src/lib/esnext.d.ts) to your `tsconfig.json` file, under `"lib"`: | ||
@@ -69,0 +67,0 @@ |
@@ -7,17 +7,22 @@ // this will only parse and run if you're using node >= 12 with the --experimental-modules flag | ||
const supportsEsm = /^v\d[2-9]/.test(process.version) | ||
const supportsEsm = /^v\d[3-9]/.test(process.version) | ||
const describeIfEsm = supportsEsm ? describe : describe.skip | ||
// only run on node >= v12: | ||
// only run on node >= v13: | ||
describeIfEsm('importing', () => { | ||
test('loads via .mjs', async () => { | ||
expect.assertions(1) | ||
const p = childProcess.spawn( | ||
'node', | ||
['--experimental-modules', './importing.mjs'], | ||
{cwd: __dirname}, | ||
) | ||
const p = childProcess.spawn('node', ['./importing.mjs'], { | ||
cwd: __dirname, | ||
env: { | ||
PATH: process.env.PATH, | ||
}, | ||
}) | ||
// eslint-disable-next-line no-console | ||
p.stderr.on('data', (d) => console.log(d.toString())) | ||
p.stderr.on('data', (d) => { | ||
if (!d.toString().includes('ExperimentalWarning:')) { | ||
// eslint-disable-next-line no-console | ||
console.log(d.toString()) | ||
} | ||
}) | ||
@@ -24,0 +29,0 @@ const code = await new Promise((resolve) => { |
@@ -78,2 +78,7 @@ import Hashids from '../lib/hashids' | ||
test(`should return an empty array when decoding an empty string`, () => { | ||
const numbers = hashids.decode('') | ||
expect(numbers).toEqual([]) | ||
}) | ||
test(`should return an empty string when encoding non-numeric input`, () => { | ||
@@ -100,3 +105,3 @@ const id = hashids.encode('z') | ||
// reproduction from https://github.com/niieani/hashids.js/issues/126 | ||
test(`should throw an error when an id to be decoded contains chars that do not exist in the alphabet`, () => { | ||
test(`should throw an error when an id to be decoded contains chars that do not exist in the alphabet (multiple)`, () => { | ||
const hashids = new Hashids('', 6, 'abcdefghjklmnpqrstuvwxyz23456789') | ||
@@ -108,2 +113,11 @@ expect(hashids.isValidId('[object Object]')).toBe(false) | ||
}) | ||
// reproduction from https://github.com/niieani/hashids.js/issues/126 | ||
test(`should throw an error when an id to be decoded contains chars that do not exist in the alphabet (single)`, () => { | ||
const hashids = new Hashids('', 6, 'abcdefghjklmnpqrstuvwxyz23456789') | ||
expect(hashids.isValidId('a1bcdef')).toBe(false) | ||
expect(() => { | ||
hashids.decode('a1bcdef') | ||
}).toThrow(Error) | ||
}) | ||
}) |
@@ -51,2 +51,7 @@ import Hashids from '../lib/hashids' | ||
}) | ||
test(`should work with alphabet that contains emojis that are subsets of each other`, () => { | ||
testAlphabet('ππ§π½βπ¦³π§π·π©πΏβπ¦°π©πΎβπ¦°π©π½βπ¦°π©π»βπ¦°βπΎππ½π©π»π¦·π€¦ββοΈ') | ||
testAlphabet('ππ§π§π½βπ¦³π·π©π»βπ¦°π©πΏβπ¦°π©π½βπ¦°π©πΎβπ¦°βπΎππ½π©π»π¦·π€¦ββοΈ') | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3203525
50
10196
29
248
18
1