184 lines
4.9 KiB
JavaScript
184 lines
4.9 KiB
JavaScript
import { digest } from "ohash";
|
|
const Hasher = /* @__PURE__ */ (() => {
|
|
class Hasher2 {
|
|
buff = "";
|
|
#context = /* @__PURE__ */ new Map();
|
|
write(str) {
|
|
this.buff += str;
|
|
}
|
|
dispatch(value) {
|
|
const type = value === null ? "null" : typeof value;
|
|
return this[type](value);
|
|
}
|
|
object(object) {
|
|
if (object && typeof object.toJSON === "function") {
|
|
return this.object(object.toJSON());
|
|
}
|
|
const objString = Object.prototype.toString.call(object);
|
|
let objType = "";
|
|
const objectLength = objString.length;
|
|
objType = objectLength < 10 ? "unknown:[" + objString + "]" : objString.slice(8, objectLength - 1);
|
|
objType = objType.toLowerCase();
|
|
let objectNumber = null;
|
|
if ((objectNumber = this.#context.get(object)) === void 0) {
|
|
this.#context.set(object, this.#context.size);
|
|
} else {
|
|
return this.dispatch("[CIRCULAR:" + objectNumber + "]");
|
|
}
|
|
if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
this.write("buffer:");
|
|
return this.write(object.toString("utf8"));
|
|
}
|
|
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
|
|
if (this[objType]) {
|
|
this[objType](object);
|
|
} else {
|
|
this.unknown(object, objType);
|
|
}
|
|
} else {
|
|
const keys = Object.keys(object).sort();
|
|
const extraKeys = [];
|
|
this.write("object:" + (keys.length + extraKeys.length) + ":");
|
|
const dispatchForKey = (key) => {
|
|
this.dispatch(key);
|
|
this.write(":");
|
|
this.dispatch(object[key]);
|
|
this.write(",");
|
|
};
|
|
for (const key of keys) {
|
|
dispatchForKey(key);
|
|
}
|
|
for (const key of extraKeys) {
|
|
dispatchForKey(key);
|
|
}
|
|
}
|
|
}
|
|
array(arr, unordered) {
|
|
unordered = unordered === void 0 ? false : unordered;
|
|
this.write("array:" + arr.length + ":");
|
|
if (!unordered || arr.length <= 1) {
|
|
for (const entry of arr) {
|
|
this.dispatch(entry);
|
|
}
|
|
return;
|
|
}
|
|
const contextAdditions = /* @__PURE__ */ new Map();
|
|
const entries = arr.map((entry) => {
|
|
const hasher = new Hasher2();
|
|
hasher.dispatch(entry);
|
|
for (const [key, value] of hasher.#context) {
|
|
contextAdditions.set(key, value);
|
|
}
|
|
return hasher.toString();
|
|
});
|
|
this.#context = contextAdditions;
|
|
entries.sort();
|
|
return this.array(entries, false);
|
|
}
|
|
date(date) {
|
|
return this.write("date:" + date.toJSON());
|
|
}
|
|
symbol(sym) {
|
|
return this.write("symbol:" + sym.toString());
|
|
}
|
|
unknown(value, type) {
|
|
this.write(type);
|
|
if (!value) {
|
|
return;
|
|
}
|
|
this.write(":");
|
|
if (value && typeof value.entries === "function") {
|
|
return this.array(
|
|
[...value.entries()],
|
|
true
|
|
/* ordered */
|
|
);
|
|
}
|
|
}
|
|
error(err) {
|
|
return this.write("error:" + err.toString());
|
|
}
|
|
boolean(bool) {
|
|
return this.write("bool:" + bool);
|
|
}
|
|
string(string) {
|
|
this.write("string:" + string.length + ":");
|
|
this.write(string);
|
|
}
|
|
function(fn) {
|
|
this.write("fn:");
|
|
if (isNativeFunction(fn)) {
|
|
this.dispatch("[native]");
|
|
} else {
|
|
this.dispatch(fn.toString());
|
|
}
|
|
}
|
|
number(number) {
|
|
return this.write("number:" + number);
|
|
}
|
|
null() {
|
|
return this.write("Null");
|
|
}
|
|
undefined() {
|
|
return this.write("Undefined");
|
|
}
|
|
regexp(regex) {
|
|
return this.write("regex:" + regex.toString());
|
|
}
|
|
arraybuffer(arr) {
|
|
this.write("arraybuffer:");
|
|
return this.dispatch(new Uint8Array(arr));
|
|
}
|
|
url(url) {
|
|
return this.write("url:" + url.toString());
|
|
}
|
|
map(map) {
|
|
this.write("map:");
|
|
const arr = [...map];
|
|
return this.array(arr, false);
|
|
}
|
|
set(set) {
|
|
this.write("set:");
|
|
const arr = [...set];
|
|
return this.array(arr, false);
|
|
}
|
|
bigint(number) {
|
|
return this.write("bigint:" + number.toString());
|
|
}
|
|
}
|
|
for (const type of [
|
|
"uint8array",
|
|
"uint8clampedarray",
|
|
"unt8array",
|
|
"uint16array",
|
|
"unt16array",
|
|
"uint32array",
|
|
"unt32array",
|
|
"float32array",
|
|
"float64array"
|
|
]) {
|
|
Hasher2.prototype[type] = function(arr) {
|
|
this.write(type + ":");
|
|
return this.array([...arr], false);
|
|
};
|
|
}
|
|
function isNativeFunction(f) {
|
|
if (typeof f !== "function") {
|
|
return false;
|
|
}
|
|
return Function.prototype.toString.call(f).slice(
|
|
-15
|
|
/* "[native code] }".length */
|
|
) === "[native code] }";
|
|
}
|
|
return Hasher2;
|
|
})();
|
|
export function serialize(object) {
|
|
const hasher = new Hasher();
|
|
hasher.dispatch(object);
|
|
return hasher.buff;
|
|
}
|
|
export function hash(value) {
|
|
return digest(typeof value === "string" ? value : serialize(value)).replace(/[-_]/g, "").slice(0, 10);
|
|
}
|