UNPKG

@oxog/kindof

Version:

Zero-dependency advanced type detection library with TypeScript support, plugin system, and 100% test coverage

732 lines (723 loc) 18.8 kB
'use strict'; const TYPE_TAG_MAP = { "[object Arguments]": "arguments", "[object Array]": "array", "[object ArrayBuffer]": "arraybuffer", "[object AsyncFunction]": "asyncfunction", "[object AsyncGeneratorFunction]": "asyncgeneratorfunction", "[object BigInt]": "bigint", "[object BigInt64Array]": "bigint64array", "[object BigUint64Array]": "biguint64array", "[object Boolean]": "boolean", "[object DataView]": "dataview", "[object Date]": "date", "[object Error]": "error", "[object Float32Array]": "float32array", "[object Float64Array]": "float64array", "[object Function]": "function", "[object GeneratorFunction]": "generatorfunction", "[object Int8Array]": "int8array", "[object Int16Array]": "int16array", "[object Int32Array]": "int32array", "[object Map]": "map", "[object Number]": "number", "[object Object]": "object", "[object Promise]": "promise", "[object Proxy]": "proxy", "[object RegExp]": "regexp", "[object Set]": "set", "[object SharedArrayBuffer]": "sharedarraybuffer", "[object String]": "string", "[object Symbol]": "symbol", "[object Uint8Array]": "uint8array", "[object Uint8ClampedArray]": "uint8clampedarray", "[object Uint16Array]": "uint16array", "[object Uint32Array]": "uint32array", "[object WeakMap]": "weakmap", "[object WeakSet]": "weakset", "[object Window]": "window", "[object HTMLDocument]": "document", "[object Document]": "document", "[object Null]": "null", "[object Undefined]": "undefined" }; const toString$1 = Object.prototype.toString; const toStringTag = Symbol.toStringTag; function getNativeType(value) { if (value === void 0) return "undefined"; if (value === null) return "null"; const primitiveType = typeof value; switch (primitiveType) { case "boolean": return "boolean"; case "number": return "number"; case "string": return "string"; case "symbol": return "symbol"; case "bigint": return "bigint"; case "function": return getFunctionType(value); case "object": return getObjectType(value); default: return null; } } function getFunctionType(fn) { const fnString = fn.toString(); if (/^class\s/.test(fnString)) { return "function"; } if (/^async\s*function\s*\*/.test(fnString) || /^async\s*\*/.test(fnString)) { return "asyncgeneratorfunction"; } if (/^async\s/.test(fnString)) { return "asyncfunction"; } if (/^function\s*\*/.test(fnString) || /^\*/.test(fnString)) { return "generatorfunction"; } const ctorName = fn.constructor?.name; if (ctorName === "AsyncFunction") return "asyncfunction"; if (ctorName === "GeneratorFunction") return "generatorfunction"; if (ctorName === "AsyncGeneratorFunction") return "asyncgeneratorfunction"; return "function"; } function getObjectType(obj) { const tag = toString$1.call(obj); const mappedType = TYPE_TAG_MAP[tag]; if (mappedType) { return mappedType; } if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(obj)) { return "buffer"; } if (typeof obj === "object" && "callee" in obj && typeof obj.callee === "function") { return "arguments"; } if (isStream(obj)) { return "stream"; } if (isEventEmitter(obj)) { return "eventemitter"; } if (tag === "[object Object]") { const customTag = obj[toStringTag]; if (typeof customTag === "string") { return customTag.toLowerCase(); } const ctor = obj.constructor; if (ctor && ctor !== Object) { const ctorName = ctor.name; if (ctorName && ctorName !== "Object") { return ctorName.toLowerCase(); } } } if (isDOMElement(obj)) { return "element"; } if (isDOMNode(obj)) { return "node"; } if (isGlobal(obj)) { return "global"; } return "object"; } function isStream(obj) { return obj !== null && typeof obj === "object" && typeof obj.pipe === "function"; } function isEventEmitter(obj) { return obj !== null && typeof obj === "object" && typeof obj.on === "function" && typeof obj.emit === "function" && typeof obj.removeListener === "function"; } function isDOMElement(obj) { if (typeof HTMLElement === "undefined") return false; return obj instanceof HTMLElement; } function isDOMNode(obj) { if (typeof Node === "undefined") return false; return obj instanceof Node; } function isGlobal(obj) { if (typeof globalThis !== "undefined" && obj === globalThis) return true; if (typeof global !== "undefined" && obj === global) return true; if (typeof window !== "undefined" && obj === window) return true; if (typeof self !== "undefined" && obj === self) return true; return false; } const WeakMapPrototype = WeakMap.prototype; const WeakSetPrototype = WeakSet.prototype; const MapPrototype = Map.prototype; const SetPrototype = Set.prototype; const ArrayBufferPrototype = ArrayBuffer.prototype; const DataViewPrototype = DataView.prototype; const SharedArrayBufferPrototype = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer.prototype : null; function checkModernType(value) { if (value === null || value === void 0) { return null; } try { if (value instanceof Promise || isThenable(value)) { return "promise"; } if (value instanceof Map || value.__proto__ === MapPrototype) { return "map"; } if (value instanceof Set || value.__proto__ === SetPrototype) { return "set"; } if (value instanceof WeakMap || value.__proto__ === WeakMapPrototype) { return "weakmap"; } if (value instanceof WeakSet || value.__proto__ === WeakSetPrototype) { return "weakset"; } if (value instanceof ArrayBuffer || value.__proto__ === ArrayBufferPrototype) { return "arraybuffer"; } if (SharedArrayBufferPrototype && (value instanceof SharedArrayBuffer || value.__proto__ === SharedArrayBufferPrototype)) { return "sharedarraybuffer"; } if (value instanceof DataView || value.__proto__ === DataViewPrototype) { return "dataview"; } if (isProxy(value)) { return "proxy"; } } catch { } return null; } function isThenable(value) { return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function"; } function isProxy(value) { try { if (typeof value !== "object" && typeof value !== "function") { return false; } new Proxy({}, value); const descriptor = Object.getOwnPropertyDescriptor(value, Symbol.toStringTag); if (descriptor && !descriptor.configurable && descriptor.value === "Proxy") { return true; } return false; } catch { return false; } } function getTypedArrayType(value) { if (!ArrayBuffer.isView(value)) { return null; } const proto = Object.getPrototypeOf(value); const ctorName = proto?.constructor?.name; switch (ctorName) { case "Int8Array": return "int8array"; case "Uint8Array": return "uint8array"; case "Uint8ClampedArray": return "uint8clampedarray"; case "Int16Array": return "int16array"; case "Uint16Array": return "uint16array"; case "Int32Array": return "int32array"; case "Uint32Array": return "uint32array"; case "Float32Array": return "float32array"; case "Float64Array": return "float64array"; case "BigInt64Array": return "bigint64array"; case "BigUint64Array": return "biguint64array"; default: return null; } } let typeCache = null; let cacheEnabled = true; function kindOfCore(value) { if (value === void 0) return "undefined"; if (value === null) return "null"; const primitiveType = getPrimitiveType(value); if (primitiveType) return primitiveType; if (typeof value === "object" && cacheEnabled && typeCache) { const cached = typeCache.get(value); if (cached) return cached; } let type = getNativeType(value); if (!type || type === "object") { const modernType = checkModernType(value); if (modernType) { type = modernType; } else { const arrayType = getTypedArrayType(value); if (arrayType) { type = arrayType; } else { type = getCustomType(value) || type || "object"; } } } if (typeof value === "object" && cacheEnabled && type) { if (!typeCache) typeCache = /* @__PURE__ */ new WeakMap(); typeCache.set(value, type); } return type || "object"; } function getPrimitiveType(value) { const type = typeof value; switch (type) { case "boolean": case "number": case "string": case "symbol": case "bigint": return type; default: return null; } } function getCustomType(value) { try { const toStringTag = value[Symbol.toStringTag]; if (typeof toStringTag === "string") { return toStringTag.toLowerCase(); } if (value.constructor && value.constructor !== Object) { const ctorName = value.constructor.name; if (ctorName && ctorName !== "Object") { return ctorName.toLowerCase(); } } } catch { } return null; } function toString(value) { const type = kindOfCore(value); switch (type) { case "string": return value; case "number": case "boolean": case "bigint": return String(value); case "symbol": return value.toString(); case "undefined": return "undefined"; case "null": return "null"; case "date": return value.toISOString(); case "regexp": return value.toString(); case "function": return value.toString(); case "array": return JSON.stringify(value); case "object": try { return JSON.stringify(value); } catch { return Object.prototype.toString.call(value); } default: return String(value); } } function toNumber(value) { const type = kindOfCore(value); switch (type) { case "number": return value; case "string": { const num = Number(value); return isNaN(num) ? null : num; } case "boolean": return value ? 1 : 0; case "null": return 0; case "bigint": { const bigIntValue = Number(value); return bigIntValue > Number.MAX_SAFE_INTEGER || bigIntValue < Number.MIN_SAFE_INTEGER ? null : bigIntValue; } case "date": return value.getTime(); default: return null; } } function toBoolean(value) { const type = kindOfCore(value); switch (type) { case "boolean": return value; case "string": { const str = value.toLowerCase(); return str !== "" && str !== "false" && str !== "0" && str !== "no" && str !== "null" && str !== "undefined"; } case "number": return value !== 0 && !isNaN(value); case "null": case "undefined": return false; case "array": return value.length > 0; case "object": return Object.keys(value).length > 0; default: return !!value; } } function toBigInt(value) { const type = kindOfCore(value); switch (type) { case "bigint": return value; case "number": if (Number.isInteger(value)) { return BigInt(value); } return null; case "string": try { return BigInt(value); } catch { return null; } case "boolean": return BigInt(value ? 1 : 0); default: return null; } } function toSymbol(value) { const type = kindOfCore(value); switch (type) { case "symbol": return value; case "string": return Symbol(value); case "number": return Symbol(String(value)); default: return Symbol(toString(value)); } } function toArray(value) { const type = kindOfCore(value); switch (type) { case "array": return value; case "string": return Array.from(value); case "set": return Array.from(value); case "map": return Array.from(value); case "arguments": return Array.from(value); case "null": case "undefined": return []; default: if (value !== null && typeof value === "object" && "length" in value) { return Array.from(value); } return [value]; } } function toObject(value) { const type = kindOfCore(value); switch (type) { case "object": return value; case "array": { const arr = value; const obj = {}; arr.forEach((item, index) => { obj[index] = item; }); return obj; } case "map": { const map = value; const obj = {}; for (const [key, val] of map) { obj[String(key)] = val; } return obj; } case "set": { const set = value; const obj = {}; let index = 0; for (const item of set) { obj[index++] = item; } return obj; } case "string": { const str = value; const obj = {}; for (let i = 0; i < str.length; i++) { obj[i] = str[i]; } return obj; } case "null": case "undefined": return {}; default: return { value }; } } function toMap(value) { const type = kindOfCore(value); switch (type) { case "map": return value; case "object": { const obj = value; const map = /* @__PURE__ */ new Map(); for (const [key, val] of Object.entries(obj)) { map.set(key, val); } return map; } case "array": { const arr = value; const map = /* @__PURE__ */ new Map(); arr.forEach((item, index) => { map.set(index, item); }); return map; } case "set": { const set = value; const map = /* @__PURE__ */ new Map(); let index = 0; for (const item of set) { map.set(index++, item); } return map; } default: return null; } } function toSet(value) { const type = kindOfCore(value); switch (type) { case "set": return value; case "array": return new Set(value); case "string": return new Set(Array.from(value)); case "map": return new Set(value.values()); case "object": return new Set(Object.values(value)); default: return value !== null && value !== void 0 ? /* @__PURE__ */ new Set([value]) : /* @__PURE__ */ new Set(); } } function toDate(value) { const type = kindOfCore(value); switch (type) { case "date": return value; case "string": { const date = new Date(value); return isNaN(date.getTime()) ? null : date; } case "number": { const date = new Date(value); return isNaN(date.getTime()) ? null : date; } default: return null; } } function toRegExp(value) { const type = kindOfCore(value); switch (type) { case "regexp": return value; case "string": try { return new RegExp(value); } catch { return null; } default: return null; } } function toError(value) { const type = kindOfCore(value); switch (type) { case "error": return value; case "string": return new Error(value); case "object": if (value && typeof value === "object" && "message" in value) { return new Error(String(value.message)); } return new Error(String(value)); default: return new Error(String(value)); } } function toFunction(value) { const type = kindOfCore(value); switch (type) { case "function": case "asyncfunction": case "generatorfunction": case "asyncgeneratorfunction": return value; case "string": try { return new Function("return " + String(value)); } catch { return null; } default: return null; } } function toPromise(value) { const type = kindOfCore(value); switch (type) { case "promise": return value; case "function": try { const result = value(); return Promise.resolve(result); } catch (error) { return Promise.reject(error); } default: return Promise.resolve(value); } } function toBuffer(value) { if (typeof Buffer === "undefined") { return null; } const type = kindOfCore(value); switch (type) { case "buffer": return value; case "string": return Buffer.from(value); case "array": return Buffer.from(value); case "uint8array": return Buffer.from(value); case "arraybuffer": return Buffer.from(value); default: return null; } } function toTypedArray(value, TypedArrayConstructor) { const type = kindOfCore(value); switch (type) { case "arraybuffer": return new TypedArrayConstructor(value); case "array": { const arr = value; const buffer = new ArrayBuffer(arr.length * 4); const view = new TypedArrayConstructor(buffer); for (let i = 0; i < arr.length; i++) { view[i] = arr[i]; } return view; } default: if (type.includes("array") && value instanceof ArrayBuffer) { return new TypedArrayConstructor(value); } return null; } } function coerceType(value, targetType) { const currentType = kindOfCore(value); if (currentType === targetType) { return value; } switch (targetType) { case "string": return toString(value); case "number": return toNumber(value); case "boolean": return toBoolean(value); case "bigint": return toBigInt(value); case "symbol": return toSymbol(value); case "undefined": return void 0; case "null": return null; case "array": if (currentType === "object" && value !== null) { const arr = Array.from(value); return arr.length > 0 ? arr : null; } return null; case "object": if (currentType === "array") { const obj = {}; value.forEach((item, index) => { obj[index] = item; }); return obj; } return null; case "date": if (currentType === "string") { const date = new Date(value); return isNaN(date.getTime()) ? null : date; } return null; default: return null; } } exports.coerceType = coerceType; exports.toArray = toArray; exports.toBigInt = toBigInt; exports.toBoolean = toBoolean; exports.toBuffer = toBuffer; exports.toDate = toDate; exports.toError = toError; exports.toFunction = toFunction; exports.toMap = toMap; exports.toNumber = toNumber; exports.toObject = toObject; exports.toPromise = toPromise; exports.toRegExp = toRegExp; exports.toSet = toSet; exports.toString = toString; exports.toSymbol = toSymbol; exports.toTypedArray = toTypedArray; //# sourceMappingURL=index.cjs.map