npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@karmaniverous/controlled-proxy

v0.1.3

Published

Control & modify the behavior of any object non-destructively at runtime.

Downloads

272

Readme

controlled-proxy

controlled-proxy

controlledProxy allows the behavior of any object to be modified & controlled non-destructively at runtime.

The developer can:

  • Alter the proxy's endpoint controls at runtime.

  • Specify a context-aware handler for disabled endpoints, also at runtime.

  • Create multiple proxies of an underlying object, each controlled differently.

  • Inject proxies into dependent code & control them from the outside.

Easy use case:

  • You have a utility library with extensive logging.

  • You consume that library from an application that uses a custom logger like winston.

  • You want your utility library also to log to winston.

  • You normally want debug logging from the utility library disabled, even when it is enabed in the outer application, but you want to enable it selectively to help debug the outer app.

API DocumentationCHANGELOG

Installation

npm install @karmaniverous/controlled-proxy

Basic Usage

The controlledProxy function creates a type-safe proxy of any object.

The options parameter is an object with the following properties:

| Property | Type | Default | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | defaultControls | Record<PropertyKey, boolean> | {} | A map of controlled property keys to boolean values. When this value is true or the property is uncontrolled, the property will behave normally. When this value is false, the property will execute the disabled member handler or return undefined. | | defaultDisabledMemberHandler | DisabledMemberHandler | () => undefined | A function that is called when a disabled controlled property is accessed. | | target | object | required | The object to proxy. |

Example

import { controlledProxy } from '@karmaniverous/controlled-proxy';

// Create a controlled console logger. Info messages are disabled by default.
const controlledConsoleLogger = controlledProxy({
  defaultControls: { debug: true, info: false },
  target: console,
});

// Log messages.
controlledConsoleLogger.debug('debug log');
controlledConsoleLogger.info('info log');
// > debug log

Runtime Control

The proxy object has two special properties, keyed with symbols that can be imported from the package:

| Property | Type | Description | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [controlProp] | Record<PropertyKey, boolean> | A map of controlled property keys to boolean values. When this value is true or the property is uncontrolled, the property will behave normally. When this value is false, the property will execute the disabled member handler or return undefined. | | [disabledMemberHandlerProp] | DisabledMemberHandler | A function that is called when a disabled controlled property is accessed. Defaults to () => undefined. |

Example

import {
  controlledProxy,
  controlProp,
  disabledMemberHandlerProp,
} from '@karmaniverous/controlled-proxy';

// Create a controlled console logger. Info messages are disabled by default.
const controlledConsoleLogger = controlledProxy({
  defaultControls: { debug: true, info: false },
  target: console,
});

// Disable debug messages & enable info messages at runtime.
controlledConsoleLogger[controlProp].debug = false;
controlledConsoleLogger[controlProp].info = true;

// Log messages.
controlledConsoleLogger.debug('debug log');
controlledConsoleLogger.info('info log');
// > info log

// Change the disabled member handler.
controlledConsoleLogger[disabledMemberHandlerProp] = (
  target: Console,
  prop: PropertyKey,
) => target.log(`Accessed disabled member: ${prop.toString()}`);

// Log messages again.
controlledConsoleLogger.debug('debug log');
controlledConsoleLogger.info('info log');
// > Accessed disabled member: debug
// > info log

Proxy Injection

Here's an example of the real power of the library: let's inject a controlled proxy into a class!

Example

import { controlledProxy, controlProp } from '@karmaniverous/controlled-proxy';

// Create a class that accepts a proxied logger as a constructor argument.
class MyClass {
  // Proxied logger must be compatible with console.debug & console.info.
  constructor(private logger: Pick<Console, 'debug' | 'info'>) {}

  // Exercise the proxied logger.
  myMethod() {
    this.logger.debug('debug log');
    this.logger.info('info log');
  }
}

// Create a controlled console logger, with all messages enabled by default
// and a custom disabled member handler.
const controlledConsoleLogger = controlledProxy({
  defaultControls: { debug: false, info: true },
  defaultDisabledMemberHandler: (target: Console, prop: PropertyKey) =>
    target.log(`Accessed disabled member: ${prop.toString()}`),
  target: console,
});

// Instantiate the class with the controlled console logger.
const myConsoleInstance = new MyClass(controlledConsoleLogger);

// Disable console debug messages at runtime.
controlledConsoleLogger[controlProp].debug = false;

// Exercise the proxied console logger from within the class.
myConsoleInstance.myMethod();
// > Accessed disabled member: debug
// > info log

// Create an equivalent controlled winston logger, with all messages enabled by
// default and a custom disabled member handler.
import { createLogger, type Logger } from 'winston';

const controlledWinstonLogger = controlledProxy({
  defaultControls: { debug: true, info: true },
  defaultDisabledMemberHandler: (target: Logger, prop: PropertyKey) =>
    target.log('warn', `Accessed disabled member: ${prop.toString()}`),
  target: createLogger(),
});

// Instantiate the class again with the controlled winston logger.
const myWinstonInstance = new MyClass(controlledWinstonLogger);

// Disable winston debug messages at runtime.
controlledWinstonLogger[controlProp].debug = false;

// Exercise the proxied winston logger from within the class.
myWinstonInstance.myMethod();
// > [winston] { "level":"warn", "message":"Accessed disabled member: debug" }
// > [winston] { "level":"info", "message":"info log" }

Built for you with ❤️ on Bali! Find more great tools & templates on my GitHub Profile.