Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

deep-storage

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

deep-storage - npm Package Compare versions

Comparing version 4.0.1 to 5.0.0

notes.md

41

lib/storage.d.ts
export declare type StateUpdateCallback = <DeepState>(path: Path, newState: DeepState, oldState: DeepState) => void;
export interface DeepSubscriptions {
export interface DeepStorage<State, RootState = {}> {
/**
* Returns a new subscription that can subscribeTo paths in state. Note,
* the subscription must be cancelled when no longer in use.
*/
subscription: (callback: StateUpdateCallback) => DeepSubscription;
}
export interface DeepStorage<State, RootState = {}> extends DeepSubscriptions {
/**
* sets a value in deep storage and notifies subscribers. shortcut for

@@ -46,2 +39,4 @@ * update where the old value is ignored

prop: <Key extends keyof State>(name: Key) => State[Key];
addSubscriber: (subscriber: Subscriber) => void;
removeSubscriber: (subscriber: Subscriber) => void;
}

@@ -60,17 +55,14 @@ /**

export declare function isPathMatch<T>(stateChangePath: T[], subscriptionPath: T[]): boolean;
/**
* A cancelable way to subscribe to paths in state
*/
export interface DeepSubscription {
subscribeTo: (...path: Path) => void;
cancel: () => void;
}
export interface UsesDeepStorage<State> {
storage: DeepStorage<State>;
}
export declare type stringNumberOrSymbol = string | number | symbol;
export declare type Path = stringNumberOrSymbol[];
export declare class Subscriber {
id: number;
private static idGenerator;
private callback;
constructor();
onChange(callback: StateUpdateCallback): void;
change<DeepState>(path: Path, newState: DeepState, oldState: DeepState): void;
}
export declare class DefaultDeepStorage<State> implements DeepStorage<State, State> {
state: State;
private id;
private subscriptions;

@@ -86,6 +78,6 @@ constructor(state: State);

deep: <DeepState>(name: string | number | symbol) => DeepStorage<DeepState, State>;
subscription: (callback: StateUpdateCallback) => {
subscribeTo: (...path: (string | number | symbol)[]) => void;
cancel: () => void;
};
addSubscriber: (subscriber: Subscriber) => void;
addSubscriberIn: (...path: (string | number | symbol)[]) => (subscriber: Subscriber) => void;
removeSubscriber: (subscriber: Subscriber) => void;
removeSubscriberIn: (...path: (string | number | symbol)[]) => (subscriber: Subscriber) => void;
root: () => this;

@@ -107,6 +99,7 @@ path: Path;

deep: <DeepState>(...path: (string | number | symbol)[]) => DeepStorage<DeepState, RootState>;
subscription: (callback: StateUpdateCallback) => DeepSubscription;
root: () => DefaultDeepStorage<RootState>;
readonly props: { [P in keyof State]: DeepStorage<State[P], {}>; };
prop: <Key extends keyof State>(name: Key) => State[Key];
addSubscriber: (subscriber: Subscriber) => void;
removeSubscriber: (subscriber: Subscriber) => void;
}

@@ -113,0 +106,0 @@ export declare function parsePath(path: Path | stringNumberOrSymbol): Path;

@@ -38,2 +38,31 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
function arraysEqual(a, b) {
if (a === b)
return true;
if (a == null || b == null)
return false;
if (a.length != b.length)
return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i])
return false;
}
return true;
}
function removePath(pathToRemove, paths) {
var found = false;
var result = [];
for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) {
var path = paths_1[_i];
if (arraysEqual(path, pathToRemove) && !found) {
found = true;
}
else {
result.push(path);
}
}
return result;
}
/**

@@ -58,2 +87,18 @@ * Is one array a prefix on another e.g.

exports.isPathMatch = isPathMatch;
var Subscriber = /** @class */ (function () {
function Subscriber() {
this.id = Subscriber.idGenerator++;
}
Subscriber.prototype.onChange = function (callback) {
this.callback = callback;
};
Subscriber.prototype.change = function (path, newState, oldState) {
if (this.callback) {
this.callback(path, newState, oldState);
}
};
Subscriber.idGenerator = 0;
return Subscriber;
}());
exports.Subscriber = Subscriber;
var DefaultDeepStorage = /** @class */ (function () {

@@ -63,3 +108,2 @@ function DefaultDeepStorage(state) {

this.state = state;
this.id = 0;
this.subscriptions = {};

@@ -112,3 +156,3 @@ this.update = function (callback) {

if (subscriber.paths.some(function (subscriberPath) { return isPathMatch(stateChangePath, subscriberPath); })) {
subscriber.callback(stateChangePath, newState, oldState);
subscriber.subscriber.change(stateChangePath, newState, oldState);
}

@@ -147,23 +191,37 @@ }

};
this.subscription = function (callback) {
var subscriberId = _this.id++;
_this.subscriptions[subscriberId] = {
callback: callback,
paths: []
this.addSubscriber = function (subscriber) {
_this.addSubscriberIn.apply(_this, _this.path)(subscriber);
};
this.addSubscriberIn = function () {
var path = [];
for (var _i = 0; _i < arguments.length; _i++) {
path[_i] = arguments[_i];
}
return function (subscriber) {
var subscription = _this.subscriptions[subscriber.id];
if (subscription) {
subscription.paths.push(path);
}
else {
_this.subscriptions[subscriber.id] = {
paths: [path],
subscriber: subscriber
};
}
};
var cancel = function () {
delete _this.subscriptions[subscriberId];
};
this.removeSubscriber = function (subscriber) {
_this.removeSubscriberIn.apply(_this, _this.path)(subscriber);
};
this.removeSubscriberIn = function () {
var path = [];
for (var _i = 0; _i < arguments.length; _i++) {
path[_i] = arguments[_i];
}
return function (subscriber) {
var subscription = _this.subscriptions[subscriber.id];
if (subscription) {
subscription.paths = removePath(path, subscription.paths);
}
};
return {
subscribeTo: function () {
var path = [];
for (var _i = 0; _i < arguments.length; _i++) {
path[_i] = arguments[_i];
}
if (subscriberId in _this.subscriptions) {
_this.subscriptions[subscriberId].paths.push(path);
}
},
cancel: cancel
};
};

@@ -240,17 +298,2 @@ this.root = function () { return _this; };

};
this.subscription = function (callback) {
var rootSubscription = _this.rootStorage.subscription(function (path, newState, oldState) {
callback(path.slice(path.length - _this.path.length, path.length), newState, oldState);
});
return {
subscribeTo: function () {
var path = [];
for (var _i = 0; _i < arguments.length; _i++) {
path[_i] = arguments[_i];
}
return rootSubscription.subscribeTo.apply(rootSubscription, _this.path.concat(path));
},
cancel: rootSubscription.cancel
};
};
this.root = function () { return _this.rootStorage; };

@@ -260,2 +303,10 @@ this.prop = function (name) {

};
this.addSubscriber = function (subscriber) {
var _a;
(_a = _this.rootStorage).addSubscriberIn.apply(_a, _this.path)(subscriber);
};
this.removeSubscriber = function (subscriber) {
var _a;
(_a = _this.rootStorage).removeSubscriberIn.apply(_a, _this.path)(subscriber);
};
}

@@ -262,0 +313,0 @@ Object.defineProperty(NestedDeepStorage.prototype, "state", {

{
"name": "deep-storage",
"version": "4.0.1",
"version": "5.0.0",
"description": "Simple observable state management for reactive applications",

@@ -21,5 +21,5 @@ "main": "./lib/index.js",

"build": "rimraf lib *.d.ts && tsc -p tsconfig.prod.json",
"publish:patch": "yarn build && npm version patch && git push && npm publish",
"publish:minor": "yarn build && npm version minor && git push && npm publish",
"publish:major": "yarn build && npm version major && git push && npm publish"
"publish:patch": "yarn build && npm version patch && git push",
"publish:minor": "yarn build && npm version minor && git push",
"publish:major": "yarn build && npm version major && git push"
},

@@ -26,0 +26,0 @@ "dependencies": {},

import { deepStorage, isPathMatch } from '../';
import { Subscriber } from '../storage';

@@ -50,3 +51,5 @@ test('stateIn', () => {

});
const subscription = storage.subscription((path, newState, oldState) => {
const subscriber = new Subscriber();
subscriber.onChange((path, newState, oldState) => {
expect(path).toEqual(['todos', 'abc', 'title']);

@@ -57,5 +60,5 @@ expect(newState).toBe('test');

});
subscription.subscribeTo('todos');
storage.addSubscriber(subscriber);
storage.deep('todos').deep('abc').deep('title').set('test');
subscription.cancel();
storage.removeSubscriber(subscriber);
});

@@ -84,3 +87,4 @@

});
const subscription = storage.subscription((path, newState, oldState) => {
const subscriber = new Subscriber();
subscriber.onChange((path, newState, oldState) => {
expect(path).toEqual([]);

@@ -91,5 +95,5 @@ expect(newState).toEqual({ todos: [1] });

});
subscription.subscribeTo('todos');
storage.deep('todos').addSubscriber(subscriber);
storage.update(prevState => ({ ...prevState, todos: [1] }));
subscription.cancel();
storage.deep('todos').removeSubscriber(subscriber);
});
export type StateUpdateCallback = <DeepState>(path: Path, newState: DeepState, oldState: DeepState) => void;
export interface DeepSubscriptions {
/**
* Returns a new subscription that can subscribeTo paths in state. Note,
* the subscription must be cancelled when no longer in use.
*/
subscription: (callback: StateUpdateCallback) => DeepSubscription;
function arraysEqual(a: any, b: any) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
export interface DeepStorage<State, RootState = {}> extends DeepSubscriptions {
function removePath(pathToRemove: Path, paths: Path[]): Path[] {
let found = false;
const result: Path[] = [];
for(const path of paths) {
if(arraysEqual(path, pathToRemove) && !found) {
found = true;
} else {
result.push(path);
}
}
return result;
}
export interface DeepStorage<State, RootState = {}> {
/**

@@ -54,2 +73,5 @@ * sets a value in deep storage and notifies subscribers. shortcut for

prop: <Key extends keyof State>(name: Key) => State[Key];
addSubscriber: (subscriber: Subscriber) => void;
removeSubscriber: (subscriber: Subscriber) => void;
}

@@ -75,22 +97,25 @@

/**
* A cancelable way to subscribe to paths in state
*/
export interface DeepSubscription {
subscribeTo: (...path: Path) => void;
cancel: () => void;
}
export type stringNumberOrSymbol = string | number | symbol;
export type Path = stringNumberOrSymbol[];
export interface UsesDeepStorage<State> {
storage: DeepStorage<State>;
export class Subscriber {
public id: number;
private static idGenerator: number = 0;
private callback: StateUpdateCallback | undefined;
constructor() {
this.id = Subscriber.idGenerator++;
}
onChange(callback: StateUpdateCallback) {
this.callback = callback;
}
change<DeepState>(path: Path, newState: DeepState, oldState: DeepState) {
if(this.callback) {
this.callback(path, newState, oldState);
}
}
}
export type stringNumberOrSymbol = string | number | symbol;
export type Path = stringNumberOrSymbol[];
export class DefaultDeepStorage<State> implements DeepStorage<State, State> {
private id: number = 0;
private subscriptions: { [key: number]: { paths: Path[], callback: StateUpdateCallback } } = {};
private subscriptions: { [key: number]: { paths: Path[], subscriber: Subscriber } } = {};
constructor(public state: State) {

@@ -131,3 +156,3 @@ }

if (subscriber.paths.some(subscriberPath => isPathMatch(stateChangePath, subscriberPath))) {
subscriber.callback(stateChangePath, newState, oldState)
subscriber.subscriber.change(stateChangePath, newState, oldState)
}

@@ -155,18 +180,23 @@ }

}
subscription = (callback: StateUpdateCallback) => {
const subscriberId = this.id++;
this.subscriptions[subscriberId] = {
callback,
paths: []
} as any;
const cancel = () => {
delete this.subscriptions[subscriberId];
addSubscriber = (subscriber: Subscriber) => {
this.addSubscriberIn(...this.path)(subscriber);
}
addSubscriberIn = (...path: Path) => (subscriber: Subscriber) => {
const subscription = this.subscriptions[subscriber.id];
if(subscription) {
subscription.paths.push(path);
} else {
this.subscriptions[subscriber.id] = {
paths: [path],
subscriber
}
}
return {
subscribeTo: (...path: Path) => {
if (subscriberId in this.subscriptions) {
this.subscriptions[subscriberId].paths.push(path);
}
},
cancel
}
removeSubscriber = (subscriber: Subscriber) => {
this.removeSubscriberIn(...this.path)(subscriber);
}
removeSubscriberIn = (...path: Path) => (subscriber: Subscriber) => {
const subscription = this.subscriptions[subscriber.id];
if(subscription) {
subscription.paths = removePath(path, subscription.paths);
}

@@ -217,13 +247,2 @@ }

}
subscription = (callback: StateUpdateCallback): DeepSubscription => {
const rootSubscription = this.rootStorage.subscription((path, newState, oldState) => {
callback(path.slice(path.length - this.path.length, path.length), newState, oldState);
});
return {
subscribeTo: (...path: Path) => {
return rootSubscription.subscribeTo(...this.path.concat(path));
},
cancel: rootSubscription.cancel
}
}
root = () => this.rootStorage;

@@ -240,2 +259,8 @@ get props() {

}
addSubscriber = (subscriber: Subscriber) => {
this.rootStorage.addSubscriberIn(...this.path)(subscriber);
}
removeSubscriber = (subscriber: Subscriber) => {
this.rootStorage.removeSubscriberIn(...this.path)(subscriber);
}
}

@@ -242,0 +267,0 @@

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