UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks

65 lines (64 loc) 2.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.wrap = wrap; exports.createWrappedFunction = createWrappedFunction; exports.isWrapped = isWrapped; function wrap(module, name, wrapper) { if (!module[name]) { throw new Error(`no original function ${name} to wrap`); } if (typeof module[name] !== "function") { throw new Error(`original must be a function, instead found: ${typeof module[name]}`); } const original = module[name]; const wrapped = createWrappedFunction(original, wrapper); defineProperty(module, name, wrapped); return wrapped; } function createWrappedFunction(original, wrapper) { const wrapped = wrapper(original); defineProperty(wrapped, "__original", original); defineProperty(wrapped, "__wrapped", true); // Copy over all properties from the original function to the wrapped one. // e.g. fs.realpath.native // .inspect("realpath", (args) => {...}) // We don't want to lose the original function's properties. // Most of the functions we're wrapping don't have any properties, so this is a rare case. // Inspired by https://github.com/DataDog/dd-trace-js/blob/master/packages/datadog-shimmer/src/shimmer.js#L8 Object.setPrototypeOf(wrapped, original); const props = Object.getOwnPropertyDescriptors(original); const keys = Reflect.ownKeys(props); for (const key of keys) { try { // Define the property on the wrapped function, keeping the original property's attributes. Object.defineProperty(wrapped, key, props[key]); } catch { // } } return wrapped; } // Sets a property on an object, preserving its enumerability. // This function assumes that the property is already writable. function defineProperty(obj, name, value) { const enumerable = // @ts-expect-error We don't know the type of obj !!obj[name] && Object.prototype.propertyIsEnumerable.call(obj, name); Object.defineProperty(obj, name, { configurable: true, enumerable: enumerable, writable: true, value: value, }); } /** * Check if a function is wrapped */ function isWrapped(fn) { return (fn instanceof Function && "__wrapped" in fn && fn.__wrapped === true && "__original" in fn && fn.__original instanceof Function); }