"use strict";
const MARKER = "alef:error-info:";
const SKIP = new Set(["constructor", "length", "name", "prototype", "caller", "arguments"]);
const patched = new WeakSet();
const iterables = new WeakSet();
function decorate(error) {
if (error === null || typeof error !== "object") return error;
const cause = error.cause;
if (cause === null || typeof cause !== "object" || typeof cause.message !== "string") return error;
if (!cause.message.startsWith(MARKER)) return error;
let info;
try {
info = JSON.parse(cause.message.slice(MARKER.length));
} catch {
return error;
}
for (const [name, value] of Object.entries(info)) {
Object.defineProperty(error, name, { value, enumerable: true, writable: true, configurable: true });
}
try {
delete error.cause;
} catch {
}
return error;
}
function rethrow(error) {
throw decorate(error);
}
function wrapIterator(iterator) {
if (iterator === null || typeof iterator !== "object") return iterator;
for (const name of ["next", "return", "throw"]) {
const original = iterator[name];
if (typeof original !== "function") continue;
try {
Object.defineProperty(iterator, name, {
configurable: true,
writable: true,
value: function (...args) {
return Promise.resolve(original.apply(this, args)).then(undefined, rethrow);
},
});
} catch {
}
}
return iterator;
}
function wrapIterable(value) {
if (value === null || typeof value !== "object") return value;
const open = value[Symbol.asyncIterator];
if (typeof open !== "function" || iterables.has(value)) return value;
iterables.add(value);
try {
Object.defineProperty(value, Symbol.asyncIterator, {
configurable: true,
writable: true,
value: function () {
return wrapIterator(open.call(this));
},
});
} catch {
return value;
}
wrapIterator(value);
return value;
}
function settle(result) {
if (result !== null && typeof result === "object" && typeof result.then === "function") {
return result.then(wrapIterable, rethrow);
}
return wrapIterable(result);
}
function wrapFunction(fn) {
return function (...args) {
let result;
try {
result = fn.apply(this, args);
} catch (error) {
throw decorate(error);
}
return settle(result);
};
}
function patchMethods(target) {
if (target === null || (typeof target !== "object" && typeof target !== "function")) return;
if (patched.has(target)) return;
patched.add(target);
for (const key of Reflect.ownKeys(target)) {
if (typeof key === "string" && SKIP.has(key)) continue;
const descriptor = Object.getOwnPropertyDescriptor(target, key);
if (!descriptor || typeof descriptor.value !== "function" || !descriptor.configurable) continue;
try {
Object.defineProperty(target, key, { ...descriptor, value: wrapFunction(descriptor.value) });
} catch {
}
}
}
function wrapExport(value) {
if (typeof value !== "function") return value;
patchMethods(value);
patchMethods(value.prototype);
return new Proxy(value, {
apply(target, thisArg, args) {
return wrapFunction(target).apply(thisArg, args);
},
});
}
module.exports = function decorateBinding(native) {
const decorated = {};
for (const key of Object.keys(native)) {
decorated[key] = wrapExport(native[key]);
}
return decorated;
};
module.exports.decorate = decorate;