mosquito-transport
Version:
Quickly spawn server infrastructure along robust authentication, database, storage, and cross-platform compatibility
214 lines (173 loc) • 5.42 kB
JavaScript
import { Buffer } from "buffer";
import { Validator } from "guard-object";
import { BSON } from 'mongodb/lib/bson';
const { BSONError, BSONOffsetError, BSONRegExp, BSONRuntimeError, BSONSymbol, BSONValue, BSONVersionError, Binary, Code, DBRef, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID } = BSON;
const ErrorInstances = [
niceReturn(() => ReferenceError),
niceReturn(() => SyntaxError),
niceReturn(() => RangeError),
niceReturn(() => TypeError),
niceReturn(() => EvalError),
Error
].filter(v => v);
/**
* @template T
* @param {T} obj
* @returns {T}
*/
export function basicClone(obj) {
if ([NaN, undefined, Infinity, null].includes(obj)) {
return obj;
}
if (typeof obj === 'bigint')
return BigInt(obj);
if (
['number', 'string', 'boolean', 'function'].includes(typeof obj) ||
obj instanceof Promise
) return obj;
for (const e of [Date, RegExp]) {
if (isDirectInstance(obj, e))
return new e(obj);
}
if (isDirectInstance(obj, ArrayBuffer))
return obj.slice(0);
if (
typeof SharedArrayBuffer !== 'undefined' &&
isDirectInstance(obj, SharedArrayBuffer)
) return obj.slice(0);
if (Buffer.isBuffer(obj)) return Buffer.from(obj);
for (const instance of ErrorInstances) {
if (isDirectInstance(obj, instance)) {
const n = new instance(obj.message);
n.stack = obj.stack;
// n.name = obj.name;
return n;
}
}
for (const e of [Map, Set]) {
if (isDirectInstance(obj, e))
return new e([...obj].map(basicClone));
}
for (
const e of
[
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
BigInt64Array,
BigUint64Array
]
) {
if (isDirectInstance(obj, e))
return new e(Buffer.from(obj));
}
if (isDirectInstance(obj, BSONOffsetError)) {
const n = new BSONOffsetError(obj.message, obj.offset);
// n.name = obj.name;
n.stack = obj.stack;
return n;
}
for (
const instance of
[
BSONRuntimeError,
BSONVersionError,
BSONError
]
) {
if (isDirectInstance(obj, instance)) {
const n = new instance(obj.message);
n.stack = obj.stack;
// n.name = obj.name;
return n;
}
}
if (
typeof Response !== 'undefined' &&
isDirectInstance(obj, Response)
) return obj.clone();
if (
typeof Headers !== 'undefined' &&
isDirectInstance(obj, Headers)
) return new Headers(obj);
if (
typeof Blob !== 'undefined' &&
isDirectInstance(obj, Blob)
) return obj.slice(0, obj.size, obj.type);
if (isDirectInstance(obj, BSONRegExp))
return new BSONRegExp(obj.pattern, obj.options);
if (isDirectInstance(obj, BSONSymbol))
return new BSONSymbol(obj.value);
if (isDirectInstance(obj, Binary))
return new Binary(obj.buffer, obj.sub_type);
if (isDirectInstance(obj, Code))
return new Code(obj.code, obj.scope);
if (isDirectInstance(obj, DBRef))
return new DBRef(obj.collection, obj.oid, obj.db, obj.fields);
if (isDirectInstance(obj, Decimal128))
return new Decimal128(obj.bytes);
if (isDirectInstance(obj, Double))
return new Double(obj.value);
if (isDirectInstance(obj, Int32))
return new Int32(obj.value);
if (isDirectInstance(obj, Long))
return new Long(obj.low, obj.high, obj.unsigned);
if (isDirectInstance(obj, Timestamp))
return new Timestamp({ t: obj.t, i: obj.i });
if (isDirectInstance(obj, MaxKey))
return new MaxKey();
if (isDirectInstance(obj, MinKey))
return new MinKey();
if (isDirectInstance(obj, ObjectId))
return new ObjectId(obj.id);
if (isDirectInstance(obj, UUID)) return new UUID(obj);
if (isDirectInstance(obj, BSONValue)) return obj;
if (Validator.ARRAY(obj))
return [...obj.map(basicClone)];
if (Validator.OBJECT(obj)) {
const newObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = basicClone(obj[key]);
}
}
return newObj;
}
if (ArrayBuffer.isView(obj)) return Buffer.from(obj);
if (obj instanceof Error) {
// general errors
try {
const n = new obj.constructor(obj.message);
n.stack = obj.stack;
return n;
} catch (error) {
const n = new Error(obj.message);
n.stack = obj.stack;
try {
n.name = obj.name;
} catch (_) { }
return n;
}
}
throw `${obj} cannot be cloned`;
}
/**
* @template T
* @param {unknown} obj
* @param {new (...args: any[]) => T} Class
* @returns {obj is T}
*/
function isDirectInstance(obj, Class) {
return typeof obj === "object" && obj !== null && obj.constructor === Class;
}
function niceReturn(func) {
try {
return func();
} catch (_) { }
}