New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

roxe

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

roxe - npm Package Compare versions

Comparing version 1.0.4 to 1.0.5

396

index.js

@@ -1,226 +0,216 @@

(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _a;
const rxjs_1 = require("rxjs");
const observedObjectsSymbol_1 = require("./observedObjectsSymbol");
/**
* A Subject that will only memorize its subscribers
* And remove them on unsubscribe.
* Unsubscription will not close or stop the Subject itself.
*/
class ReusableSubject extends rxjs_1.Subject {
unsubscribe() {
this.observers = [];
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "rxjs", "./observedObjectsSymbol"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _a;
const rxjs_1 = require("rxjs");
const observedObjectsSymbol_1 = require("./observedObjectsSymbol");
/**
* A Subject that will only memorize its subscribers
* And remove them on unsubscribe.
* Unsubscription will not close or stop the Subject itself.
*/
class ReusableSubject extends rxjs_1.Subject {
unsubscribe() {
this.observers = [];
}
class _ObservableObject {
constructor(from = {}, optHandlers = {}) {
this[_a] = {};
let setCustomHandler;
let getCustomHandler;
if (optHandlers && Object.keys(optHandlers).length) {
if (optHandlers.set) {
setCustomHandler = optHandlers.set;
delete optHandlers.set;
}
if (optHandlers.get) {
getCustomHandler = optHandlers.get;
}
}
}
class _ObservableObject {
constructor(from = {}, optHandlers = {}) {
this[_a] = {};
let setCustomHandler;
let getCustomHandler;
if (optHandlers && Object.keys(optHandlers).length) {
if (optHandlers.set) {
setCustomHandler = optHandlers.set;
delete optHandlers.set;
}
if (optHandlers.get) {
getCustomHandler = optHandlers.get;
}
}
const handlers = Object.assign(optHandlers, {
// Note for future: leave receiver as parameter even if not used
// to keep args as the last and not include receiver in this one
set: (obj, prop, value, receiver, ...args) => {
let notificationChain;
if (typeof value === "object") {
// Creating the chain of properties that will be notified
notificationChain = Object.assign({
[prop]: value,
}, buildNotificationChain(value, prop));
if (setCustomHandler) {
let setResult = setCustomHandler(obj, prop, value, receiver);
if (setResult === false) {
return setResult;
}
const handlers = Object.assign(optHandlers, {
// Note for future: leave receiver as parameter even if not used
// to keep args as the last and not include receiver in this one
set: (obj, prop, value, receiver, ...args) => {
let notificationChain;
if (typeof value === "object") {
// Creating the chain of properties that will be notified
notificationChain = Object.assign({
[prop]: value,
}, buildNotificationChain(value, prop));
if (setCustomHandler) {
let setResult = setCustomHandler(obj, prop, value, receiver);
if (setResult === false) {
return setResult;
}
/*
* We when we set a property which will be an object
* we set it as a Proxy and pass it
* an edited SETTER with binded trailing keys to reach
* this property.
* E.g. if we have an object structure like x.y.z.w
* x, x.y and x.y.z will be Proxies; each property
* will receive a setter with the parent keys.
* w property, will receive below (in else),
* ["x", "y", "z"] as args.
*
* We have to copy handlers to a new object to keep
* the original `handlers.set` clean from any external argument
*/
obj[prop] = new Proxy(value, Object.assign({}, handlers, {
set: bindLast(handlers.set, ...args, prop),
}));
}
else {
/*
* We when we set a property which will be an object
* we set it as a Proxy and pass it
* an edited SETTER with binded trailing keys to reach
* this property.
* E.g. if we have an object structure like x.y.z.w
* x, x.y and x.y.z will be Proxies; each property
* will receive a setter with the parent keys.
* w property, will receive below (in else),
* ["x", "y", "z"] as args.
*
* We have to copy handlers to a new object to keep
* the original `handlers.set` clean from any external argument
*/
obj[prop] = new Proxy(value, Object.assign({}, handlers, {
set: bindLast(handlers.set, ...args, prop),
}));
}
else {
/*
* We finalize the path of the keys passed in the above condition
* to reach “object endpoint” (like "w" for the prev. example)
* The path keys composition, let us subscribe to observables
* with dot notation like x.y.z.w
*/
if (obj[prop] === value) {
/*
* We finalize the path of the keys passed in the above condition
* to reach “object endpoint” (like "w" for the prev. example)
* The path keys composition, let us subscribe to observables
* with dot notation like x.y.z.w
* If the value is the same, we return true.
* This cannot be considered as a fail. Also, failing would bring
* a strict-mode script to throw a TypeError.
*/
if (obj[prop] === value) {
/*
* If the value is the same, we return true.
* This cannot be considered as a fail. Also, failing would bring
* a strict-mode script to throw a TypeError.
*/
return true;
}
if (setCustomHandler) {
let setResult = setCustomHandler(obj, prop, value, receiver);
if (setResult === false) {
return setResult;
}
}
obj[prop] = value;
const elementKey = args.length ? [...args, prop].join(".") : prop;
notificationChain = {
[elementKey]: value
};
return true;
}
Object.keys(notificationChain).forEach((keyPath) => {
const value = notificationChain[keyPath];
// We want both single properties an complex objects to be notified when edited
if (this[observedObjectsSymbol_1.observedObjects][keyPath]) {
this[observedObjectsSymbol_1.observedObjects][keyPath].next(value);
if (setCustomHandler) {
let setResult = setCustomHandler(obj, prop, value, receiver);
if (setResult === false) {
return setResult;
}
});
return true;
},
get: bindLast((target, prop, receiver, customGetter) => {
if (customGetter !== undefined && !(prop in _ObservableObject.prototype)) {
return customGetter(target, prop, receiver);
}
return Reflect.get(target, prop, receiver);
}, getCustomHandler)
});
return new Proxy(Object.assign(this, buildInitialProxyChain(from, handlers)), handlers);
}
/**
* Registers a custom property to be observed.
*
* @param {string} prop - The property or object
* property to subscribe to (e.g. `epsilon`
* or `time.current`)
*/
observe(prop) {
if (!this[observedObjectsSymbol_1.observedObjects][prop]) {
this[observedObjectsSymbol_1.observedObjects][prop] = new ReusableSubject();
}
return this[observedObjectsSymbol_1.observedObjects][prop];
}
/**
* Unsubscribes from all the subscriptions in a specific pool
* @param subscriptions
*/
unsubscribeAll(subscriptions) {
subscriptions.forEach(sub => sub.unsubscribe());
}
/**
* Returns the current image of a key of the main
* object or a nested key.
*
* @param {string} path - dotted-notation path ("a.b.c")
* @returns {any} - the whole observed object or part of it
* @throws if the current path does not reflect to an available object
*/
snapshot(path) {
let snapshot;
if (path && typeof path === "string") {
snapshot = path.split(".").reduce((acc, current) => {
if (!(current && typeof acc === "object" && !Array.isArray(acc) && acc.hasOwnProperty(current))) {
throw new Error(`Cannot access to ${current} of ${path}. No key available`);
obj[prop] = value;
const elementKey = args.length ? [...args, prop].join(".") : prop;
notificationChain = {
[elementKey]: value
};
}
Object.keys(notificationChain).forEach((keyPath) => {
const value = notificationChain[keyPath];
// We want both single properties an complex objects to be notified when edited
if (this[observedObjectsSymbol_1.observedObjects][keyPath]) {
this[observedObjectsSymbol_1.observedObjects][keyPath].next(value);
}
return acc[current];
}, this);
if (typeof snapshot === "object") {
return Object.assign({}, snapshot);
});
return true;
},
get: bindLast((target, prop, receiver, customGetter) => {
if (customGetter !== undefined && !(prop in _ObservableObject.prototype)) {
return customGetter(target, prop, receiver);
}
else {
return snapshot;
}
}
else {
snapshot = Object.assign({}, this);
// In the snapshot, we don't need the symbol that collects
// All the observers
delete snapshot[observedObjectsSymbol_1.observedObjects];
}
return snapshot;
}
return Reflect.get(target, prop, receiver);
}, getCustomHandler)
});
return new Proxy(Object.assign(this, buildInitialProxyChain(from, handlers)), handlers);
}
_a = observedObjectsSymbol_1.observedObjects;
// Workaround to allow us to recognize T's props as part of ObservableObject
// https://stackoverflow.com/a/54737176/2929433
exports.ObservableObject = _ObservableObject;
/**
* Builds the initial object-proxy composed of proxies objects
* @param sourceObject
* @param handlers
* Registers a custom property to be observed.
*
* @param {string} prop - The property or object
* property to subscribe to (e.g. `epsilon`
* or `time.current`)
*/
function buildInitialProxyChain(sourceObject, handlers, ...args) {
let chain = {};
for (const prop in sourceObject) {
if (typeof sourceObject[prop] === "object" && !Array.isArray(sourceObject[prop])) {
chain[prop] = buildInitialProxyChain(sourceObject[prop], Object.assign({}, handlers, {
set: bindLast(handlers.set, ...args, prop)
}), ...args, prop);
}
else {
chain[prop] = sourceObject[prop];
}
observe(prop) {
if (!this[observedObjectsSymbol_1.observedObjects][prop]) {
this[observedObjectsSymbol_1.observedObjects][prop] = new ReusableSubject();
}
return new Proxy(chain, handlers);
return this[observedObjectsSymbol_1.observedObjects][prop];
}
/**
* Builds the chain of properties that will be notified.
* This is used when a property that is or will be
* an object, is assigned.
* The function will compose an object { "x.y.z": value }
* for each key of each nested object.
* @param source - Current object
* @param args
* Unsubscribes from all the subscriptions in a specific pool
* @param subscriptions
*/
function buildNotificationChain(source, ...args) {
let chain = {};
for (const prop in source) {
chain[[...args, prop].join(".")] = source[prop];
if (typeof source[prop] === "object" && !Array.isArray(source[prop])) {
Object.assign(chain, buildNotificationChain(source[prop], ...args, prop));
}
}
return chain;
unsubscribeAll(subscriptions) {
subscriptions.forEach(sub => sub.unsubscribe());
}
/**
* Creates a function that accepts default arguments
* with some other trailing arbitrary dev-defined arguments
* Returns the current image of a key of the main
* object or a nested key.
*
* E.g. Setter receives the following arguments: obj, prop, value, receiver.
* We wrap the original function in another one that adds the arguments;
*
* @param {Function} fn - the original function
* @param {any[]} boundArgs - the arbitrary arguments
* @param {string} path - dotted-notation path ("a.b.c")
* @returns {any} - the whole observed object or part of it
* @throws if the current path does not reflect to an available object
*/
function bindLast(fn, ...boundArgs) {
return (...args) => fn(...args, ...boundArgs);
snapshot(path) {
let snapshot;
if (path && typeof path === "string") {
snapshot = path.split(".").reduce((acc, current) => {
if (!(current && typeof acc === "object" && !Array.isArray(acc) && acc.hasOwnProperty(current))) {
throw new Error(`Cannot access to ${current} of ${path}. No key available`);
}
return acc[current];
}, this);
if (typeof snapshot === "object") {
return Object.assign({}, snapshot);
}
else {
return snapshot;
}
}
else {
snapshot = Object.assign({}, this);
// In the snapshot, we don't need the symbol that collects
// All the observers
delete snapshot[observedObjectsSymbol_1.observedObjects];
}
return snapshot;
}
});
}
_a = observedObjectsSymbol_1.observedObjects;
// Workaround to allow us to recognize T's props as part of ObservableObject
// https://stackoverflow.com/a/54737176/2929433
exports.ObservableObject = _ObservableObject;
/**
* Builds the initial object-proxy composed of proxies objects
* @param sourceObject
* @param handlers
*/
function buildInitialProxyChain(sourceObject, handlers, ...args) {
let chain = {};
for (const prop in sourceObject) {
if (typeof sourceObject[prop] === "object" && !Array.isArray(sourceObject[prop])) {
chain[prop] = buildInitialProxyChain(sourceObject[prop], Object.assign({}, handlers, {
set: bindLast(handlers.set, ...args, prop)
}), ...args, prop);
}
else {
chain[prop] = sourceObject[prop];
}
}
return new Proxy(chain, handlers);
}
/**
* Builds the chain of properties that will be notified.
* This is used when a property that is or will be
* an object, is assigned.
* The function will compose an object { "x.y.z": value }
* for each key of each nested object.
* @param source - Current object
* @param args
*/
function buildNotificationChain(source, ...args) {
let chain = {};
for (const prop in source) {
chain[[...args, prop].join(".")] = source[prop];
if (typeof source[prop] === "object" && !Array.isArray(source[prop])) {
Object.assign(chain, buildNotificationChain(source[prop], ...args, prop));
}
}
return chain;
}
/**
* Creates a function that accepts default arguments
* with some other trailing arbitrary dev-defined arguments
*
* E.g. Setter receives the following arguments: obj, prop, value, receiver.
* We wrap the original function in another one that adds the arguments;
*
* @param {Function} fn - the original function
* @param {any[]} boundArgs - the arbitrary arguments
*/
function bindLast(fn, ...boundArgs) {
return (...args) => fn(...args, ...boundArgs);
}

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -5,14 +6,3 @@ * Symbol that identify the map that will contain

*/
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.observedObjects = Symbol("_observedObjects");
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.observedObjects = Symbol("_observedObjects");
{
"name": "roxe",
"version": "1.0.4",
"version": "1.0.5",
"description": "Observe object changes through proxies",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -1,177 +0,167 @@

(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "..", "../observedObjectsSymbol"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("..");
const observedObjectsSymbol_1 = require("../observedObjectsSymbol");
describe("Creating a new observable object", () => {
let oo;
describe("Registration and observing for changes", () => {
beforeEach(() => {
// I think there is no way someone could do something like this.
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("..");
const observedObjectsSymbol_1 = require("../observedObjectsSymbol");
describe("Creating a new observable object", () => {
let oo;
describe("Registration and observing for changes", () => {
beforeEach(() => {
// I think there is no way someone could do something like this.
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
});
}
});
it("Should register an observer to a specific key of the object", () => {
const observed = oo.observe("b.d.e");
// @ts-ignore - only because its the only way to check if it went fine
expect(Object.keys(oo[observedObjectsSymbol_1.observedObjects]).includes("b.d.e")).toBeTruthy();
});
it("Should register an observer to a specific key of the object", () => {
const observed = oo.observe("b.d.e");
// @ts-ignore - only because its the only way to check if it went fine
expect(Object.keys(oo[observedObjectsSymbol_1.observedObjects]).includes("b.d.e")).toBeTruthy();
});
it("Should notify all the changes", () => {
const observed = oo.observe("b.d.e");
observed.subscribe({
next: (newValue) => {
expect(newValue).toBe(5);
expect(oo.b.d.e).toBe(5);
}
});
it("Should notify all the changes", () => {
const observed = oo.observe("b.d.e");
observed.subscribe({
next: (newValue) => {
expect(newValue).toBe(5);
expect(oo.b.d.e).toBe(5);
}
});
oo.b.d.e = 5;
oo.b.d.e = 5;
});
it("Unsubscribed object should not show any update", () => {
const observed = oo.observe("b.d.e");
let subscription = observed.subscribe({
next: (newValue) => {
// this won't be executed since unsubscribed
expect(newValue).toBe(42);
}
});
it("Unsubscribed object should not show any update", () => {
const observed = oo.observe("b.d.e");
let subscription = observed.subscribe({
next: (newValue) => {
// this won't be executed since unsubscribed
expect(newValue).toBe(42);
}
});
subscription.unsubscribe();
oo.b.d.e = 42;
});
subscription.unsubscribe();
oo.b.d.e = 42;
});
describe("Proxy handler", () => {
let oo;
it("Should attach custom handlers to the original one", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
});
describe("Proxy handler", () => {
let oo;
it("Should attach custom handlers to the original one", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
}, {
get(target, prop, receiver) {
// this trap will be executed always, when getting values
// from the observed objects
if (typeof target[prop] === "number") {
return Math.pow(target[prop], 2);
}
return target[prop];
}
}, {
get(target, prop, receiver) {
// this trap will be executed always, when getting values
// from the observed objects
if (typeof target[prop] === "number") {
return Math.pow(target[prop], 2);
}
});
expect(oo.b.c).toBe(4);
return target[prop];
}
});
expect(oo.b.c).toBe(4);
});
describe("But first... let me take a snapshot", () => {
let oo;
it("Should return a full snapshot of the structure", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
});
describe("But first... let me take a snapshot", () => {
let oo;
it("Should return a full snapshot of the structure", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
});
expect(compareObjects({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
});
expect(compareObjects({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
}, oo.snapshot())).toBe(true);
});
it("Should take a partial snapshot (object) of the main object", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}, oo.snapshot())).toBe(true);
});
it("Should take a partial snapshot (object) of the main object", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
});
expect(compareObjects({
g: 4,
h: {
i: 5,
}
}, oo.snapshot("b.d.f"))).toBe(true);
}
});
it("Should take a partial snapshot (value) of the main object", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
expect(compareObjects({
g: 4,
h: {
i: 5,
}
}, oo.snapshot("b.d.f"))).toBe(true);
});
it("Should take a partial snapshot (value) of the main object", () => {
oo = new __1.ObservableObject({
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4,
h: {
i: 5,
}
}
}
});
expect(oo.snapshot("b.d.e")).toBe(3);
}
});
expect(oo.snapshot("b.d.e")).toBe(3);
});
});
function compareObjects(obj1, obj2) {
return Object.keys(obj1).every(key => {
if (obj2[key] && typeof obj1[key] === "object") {
return compareObjects(obj1[key], obj2[key]);
}
return obj2[key] === obj1[key];
});
}
});
function compareObjects(obj1, obj2) {
return Object.keys(obj1).every(key => {
if (obj2[key] && typeof obj1[key] === "object") {
return compareObjects(obj1[key], obj2[key]);
}
return obj2[key] === obj1[key];
});
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc