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

laxy

v1.0.0

Published

Proxies for lazy loading expensive objects.

Downloads

820

Readme

laxy Build Status codecov

Proxies for lazy loading expensive objects. Lazy + Proxy === Laxy

Install

$ npm install laxy

Usage

const laxy = require('laxy');

const proxy = laxy(generatorFn)(...argsToPass);

// generatorFn will only be called once, but not until you interact with the proxy in some way:
proxy();
proxy.foo;
Object.keys(proxy); // etc...

// Can be used as a lazy require
const _ = laxy(require)('lodash');

// lodash won't be loaded until you do something with it:
_.isNumber(3);

Basic API

laxy(generatorFn)(...argsToPass)

generatorFn

Type: fn

The function that should be called to generate the object being proxied. This function will be called lazily and only once.

...argsToPass

Type: anything

Any number of arguments may be provided and will be passed to the function if/when it is called.

Providing Type Hints

The Javscript Proxying API sets a few things in stone at the time of Proxy creation (like the response to typeof). Since we are lazy loading, and can't know these at creation time, laxy provides a hint system to help you customize the Proxy to better reflect the object you will return from your generator function. In many cases, you will not care, and the default type hint of func will be sufficient (even if your generator will return an object). Hints are provided with property chaining, the API remains the same:

laxy.func(generatorFn)(...args);    // generator returns a function or class 
laxy.obj(generatorFn)(...args);     // generator returns an object
laxy.arrow(genneratorFn)(...args);  // generator returns an arrow function
laxy.class(generatorFn)(...args);   // generator *is* a class function

Each of the type hint options are described in detail below:

  • obj - Indicates your generator function will return an object. If you actually do return a function, you won't be able to invoke it, but you will be able to access and invoke members of the function. Your proxy will respond to typeof proxy with 'object' regardless of what the actual proxied type is.

  • func - The default. This is the only option that allows for invocation of new (meaning your generator function returns a constructor). It works for most situations (even if you aren't returning a function), with a few caveats:

    • It will respond to typeof with function, regardless of the actual underlying type.
    • functions have a non-enumerable, and non-configurable prototype property. The Proxy API insists that non-configurable properties are reflected in the proxy, so Object.getOwnPropertyNames(proxy) will include 'prototype'. Note that the property is non-enumerable, so it won't show up in Object.keys(proxy), etc.
  • arrow - Represents an arrow function. It is invocable, but can't be invoked with new. Does not suffer from the forced prototype property like func does.

  • class - While all the other hints suggest what the return type of your generator function will be. The class hint declares that your generator function is a class function, and should be invoked with new. This should not be confused to mean your generator will return a class function (in that case, use func);

| Hint | typeof proxy | invocable | with new | Caveats | |-----------|:--------------:|:---------:|:-----------:|--------------------------------------------------------------| | obj | 'object' | No | No | | | func | 'function' | Yes | Yes | prototype member is enforced and non-configurable | | arrow | 'function' | Yes | No | Avoids prototype issue, but can't be invoked with new. | | class * | 'object' | No | No | Causes your generator function to be invoked with new. |

Revocable Proxies

The Proxy API allows for revocable proxies. Calling the revoke method will invalidate the proxy, and any future access of the proxy will cause a TypeError. You can chain the revocable modifier to create a revocable proxy.

const {revoke, proxy} = laxy.revocable(generatorFunc)(...args);
// or chain it with a type hint
const {revoke, proxy} = laxy.obj.revocable(generatorFunc)(...args);

The frozen Modifier

It's simply not possible for laxy to modify the isExtensible state of the underlying object. Calling Object.preventExtensions or Object.freeze on the proxy will not have the desired effect. Similarly, Object.isExtensible(proxy) will return true, even if your generator will return a non-extensible object. If you will return a frozen object from your generator, you can add the frozen modifier so that Object.isExtensible will correctly return false.

const generatorFunc = () => Object.freeze({foo: 'bar'});

const proxy = laxy(generatorFunc)();

Object.isExtensible(proxy); 
//=> true, even though the backing object is frozen

const frozenProxy = laxy.frozen(generatorFunc)();

Object.isExtensible(frozenProxy);
//=> false, as it should be

Note that the frozen modifier can be chained onto any of the type hints:

laxy.obj.frozen(fn)(...args);
laxy.arrow.frozen(fn)(...args);
laxy.func.frozen(fn)(...args);
laxy.obj.revocable.frozen(fn)(...args);

License

MIT © James Talmage