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 🙏

© 2025 – Pkg Stats / Ryan Hefner

shadowcopy-js

v1.0.1

Published

Deep Proxy creation tool

Downloads

6

Readme

Shadow Copy

Zero dependency deep proxy creation tool.

usage

This deep proxy tool offers by default nesting, property chain path and a cache to avoid Proxy re-instanciation without preventing carbage collection.

yarn add shadowcopy-js
import ShadowCopy from 'shadowcopy-js';

Example 1 DSL query building

In this example we let the user create property chains by nesting functions and log the path when applied.

const db = new ShadowCopy({}, {
    get () {
        return ShadowCopy.nest(function() {});
    },
    apply (target, thisArg, argArray) {
        return [ShadowCopy.path, argArray];
    }
});

console.log(db.select.from.where('a === b'));
// [['select', 'from', 'where'], ['a === b']]

Example 2 watch

In this exemple we create a watcher logging the modification of an object and his childrens via the handler 'set'.

function watch(watched, name) {
    function getCallee() {
        return (new Error()).stack.split('\n').map(v => v.trim()).filter(v => v.startsWith('at'))[3];
    }

    return new ShadowCopy(watched, {
        set (target, p, value) {
            console.log(
                'modified property "', ShadowCopy.path,
                '" of object "', name,
                '" at "', getCallee(),
                '" from "', target[p],
                '" to "', value, '"');

            target[p] = value;
            return true;
        }
    });
}

// create an object to watch and name it 'my_foo'
const p = watch({'foo': {'bar': 'val'}}, 'my_foo');

(function fn(val) {
    val['foo']['bar'] = 'sneak!';
    //logs: modified property "[ 'foo', 'bar' ]" of object "my_foo" at "at fn (file:///var/www/test.js:165:35)" from "val" to "sneak!"
})(p);

Example 3 Property protection

This third example protects private properties from being set.

const p = new ShadowCopy({'foo': {'bar': 'val'}, '_private': null}, {
    set (target, p, value) {
        if (p[0] === '_') {
            throw new Error(`Invalid attempt to set private "${p}" property`);
        }

        target[p] = value;
        return true;
    }
});

p['foo']['bar'] = 'val2';
p['foo']['_private'] = 'val2'; // Error

api

class ShadowCopy

Create a deep proxy with nesting by default.

contructor (target, handler, path = [])

  • target object original to copy/proxy
  • handler object proxy handler (full doc at MDN)
  • path string[] root path of the original object, will be prepended to ShadowCopy.path

static ShadowCopy.path

An array of string which value correspond to the chain of properties called to proc a handler.

It should only be used in a handler.

Example:

const p = new ShadowCopy({'1': {'2': {'3': {'4': '5'}}}}, {
    set (target, p, value) {
        console.log(ShadowCopy.path); // ['1', '2', '3']
        target[p] = value;

        return true;
    }
});

p['1']['2']['3'] = {};

static nest(original = currentTarget[currentP])

Create a nested Proxy.

It should only be used in a handler.

The default get handler returns a ShadowCopy to offer by default nesting, if you wish to implement the 'get' handler and to keep the by default nesting, return ShadowCopy.nest():

const p = new ShadowCopy({}, {
    get (target, p) {
        return ShadowCopy.nest();
        // same as: return ShadowCopy.nest(target[p]);
    }
});

test

Running the tests requires node at least node 14 and yarn.

yarn # install the development dependencies
yarn test # run the tests

license

MIT