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

value-enhancer

Package Overview
Dependencies
Maintainers
1
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

value-enhancer - npm Package Compare versions

Comparing version 5.2.1 to 5.3.0

23

dist/index.d.ts

@@ -199,3 +199,3 @@ /**

*/
declare function flatten<TSrcValue = any, TValOrValue = any>(val: ReadonlyVal<TSrcValue>, get: (value: TSrcValue) => TValOrValue, config?: ValConfig<UnwrapVal<TValOrValue>>): ReadonlyVal<UnwrapVal<TValOrValue>>;
declare function flatten<TSrcValue = any, TValOrValue = any>(val: ReadonlyVal<TSrcValue>, get?: (value: TSrcValue) => TValOrValue, config?: ValConfig<UnwrapVal<TValOrValue>>): ReadonlyVal<UnwrapVal<TValOrValue>>;

@@ -208,3 +208,3 @@ /**

* If the value is a val, it will be auto-flattened.
* @param listen A function that takes a notify function and returns a disposer.
* @param onChange A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.

@@ -214,14 +214,3 @@ * @param config custom config for the val.

*/
/**
* Creates a readonly val from a getter function and a listener function.
* If the value is a val, it will be auto-flattened.
*
* @param getValue A function that returns the current value.
* If the value is a val, it will be auto-flattened.
* @param listen A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.
* @param config custom config for the val.
* @returns A readonly val with value of inner val.
*/
declare const flattenFrom: <TValOrValue = any>(getValue: () => TValOrValue, listen: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<UnwrapVal<TValOrValue>> | undefined) => ReadonlyVal<UnwrapVal<TValOrValue>>;
declare const flattenFrom: <TValOrValue = any>(getValue: () => TValOrValue, onChange: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<UnwrapVal<TValOrValue>> | undefined) => ReadonlyVal<UnwrapVal<TValOrValue>>;

@@ -232,3 +221,3 @@ /**

* @param getValue A function that returns the current value.
* @param listen A function that takes a notify function and returns a disposer.
* @param onChange A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.

@@ -259,3 +248,3 @@ * @param config custom config for the val.

*/
declare const from: <TValue = any>(getValue: () => TValue, listen: (handler: () => void) => ValDisposer | void | undefined, config?: ValConfig<TValue> | undefined) => ReadonlyVal<TValue>;
declare const from: <TValue = any>(getValue: () => TValue, onChange: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<TValue> | undefined) => ReadonlyVal<TValue>;

@@ -265,4 +254,2 @@ declare const nextTick: () => Promise<void>;

/**
* @deprecated
* @ignore
* Set the value of a val.

@@ -269,0 +256,0 @@ * It works for both `Val` and `ReadonlyVal` type (if the `ReadonlyVal` is actually a `Val`).

@@ -107,12 +107,33 @@ 'use strict';

// src/agent.ts
var registry = /* @__PURE__ */ new FinalizationRegistry(invoke);
var ValAgent = class {
constructor(getValue2, config, onStart) {
this.#onStart = onStart;
constructor(getValue2, config, onChange) {
this.#getValue = getValue2;
this.q = (config?.equal ?? strictEqual) || void 0;
this.e = config?.eager;
if (onChange) {
const ref = new WeakRef(this);
const disposeEffect = () => {
if (disposeListen) {
const dispose = disposeListen;
disposeListen = void 0;
dispose();
}
};
let disposeListen = onChange(() => {
const agent = ref.deref();
if (agent) {
agent.n();
} else {
disposeEffect();
}
});
if (disposeListen) {
registry.register(this, this.#disposeEffect = disposeEffect);
}
}
}
s = /* @__PURE__ */ new Map();
b = 2 /* ValueDirty */;
v = INIT_VALUE;
b = 4 /* NeedResolveValue */;
v;
c = INIT_VALUE;

@@ -122,21 +143,20 @@ q;

u = () => {
if (this.b & 2 /* ValueDirty */) {
if (this.b & 4 /* NeedResolveValue */) {
this.b &= ~4 /* NeedResolveValue */;
const newValue = this.#getValue();
if (this.c === INIT_VALUE) {
this.d(newValue);
this.f(newValue);
} else if (!this.q?.(newValue, this.c)) {
this.d(newValue);
this.b |= 12 /* ShouldInvoke */;
this.f(newValue);
if (this.b & 1 /* Notifying */) {
this.b |= 2 /* ValueChanged */;
}
}
if (this.s.size) {
this.b &= ~2 /* ValueDirty */;
}
}
this.b &= ~1 /* Notified */;
return this.c;
};
n = () => {
this.b |= 2 /* ValueDirty */;
if (!(this.b & 1 /* Notified */)) {
this.b |= 1 /* Notified */;
this.b |= 4 /* NeedResolveValue */;
if (this.s.size) {
this.b |= 1 /* Notifying */;
if (this[3 /* Computed */]) {

@@ -147,21 +167,10 @@ this.#invoke(3 /* Computed */);

this.u();
if (this.b & 4 /* ShouldInvokeEager */) {
this.b &= ~4 /* ShouldInvokeEager */;
if (this.b & 2 /* ValueChanged */) {
this.#invoke(2 /* Eager */);
} else {
this.b &= ~12 /* ShouldInvoke */;
return;
}
} else {
this.b &= ~4 /* ShouldInvokeEager */;
}
if (this[1 /* Async */]) {
schedule(this);
} else {
this.b &= ~8 /* ShouldInvokeAsync */;
}
schedule(this);
}
};
a(subscriber, mode) {
const oldSize = this.s.size;
const currentMode = this.s.get(subscriber);

@@ -173,8 +182,2 @@ if (currentMode) {

this[mode]++;
if (!oldSize) {
this.u();
this.b &= ~12 /* ShouldInvoke */;
this.#onStartDisposer?.();
this.#onStartDisposer = this.#onStart?.(this.n);
}
return () => this.r(subscriber);

@@ -194,9 +197,2 @@ }

}
if (!this.s.size) {
this.b |= 2 /* ValueDirty */;
if (this.#onStartDisposer) {
this.#onStartDisposer();
this.#onStartDisposer = null;
}
}
}

@@ -206,19 +202,22 @@ t() {

this.u();
if (this.b & 8 /* ShouldInvokeAsync */) {
this.b &= ~8 /* ShouldInvokeAsync */;
if (this.b & 2 /* ValueChanged */) {
this.#invoke(1 /* Async */);
}
} else {
this.b &= ~8 /* ShouldInvokeAsync */;
}
this.b &= ~(1 /* Notifying */ | 2 /* ValueChanged */);
}
d(value) {
this.d = this.q?.(value, value) ? this.f : this.g;
this.d(value);
d() {
this.r();
registry.unregister(this);
this.#disposeEffect?.();
}
g(value) {
f(value) {
this.f = this.q?.(value, value) ? this.g : this.h;
this.f(value);
}
h(value) {
this.c = value;
this.v = this.#numberVersion++ | 0;
}
f(value) {
g(value) {
this.c = this.v = value;

@@ -230,5 +229,4 @@ }

#numberVersion = 0;
#disposeEffect;
#getValue;
#onStart;
#onStartDisposer;
#invoke(mode) {

@@ -275,2 +273,5 @@ for (const [sub, subMode] of this.s) {

}
d() {
this.r();
}
};

@@ -287,2 +288,3 @@

this.get = agent.u;
agent.u();
}

@@ -320,3 +322,3 @@ get $version() {

dispose() {
this.#agent.r();
this.#agent.d();
}

@@ -378,5 +380,3 @@ /**

// src/from.ts
var from = (getValue2, listen, config) => {
return new ValImpl(new ValAgent(getValue2, config, listen));
};
var from = (getValue2, onChange, config) => new ValImpl(new ValAgent(getValue2, config, onChange));

@@ -423,14 +423,12 @@ // src/combine.ts

// src/flatten-from.ts
var flattenFrom = (getValue2, listen, config) => {
var flattenFrom = (getValue2, onChange, config) => {
let innerDisposer;
let currentValVersion = INIT_VALUE;
let currentMaybeVal = INIT_VALUE;
let dirty = true;
let needCheckOuterVal = true;
const useDefaultEqual = config?.equal == null;
const subs = new ValAgent(
const agent = new ValAgent(
() => {
if (dirty) {
if (subs.s.size) {
dirty = false;
}
if (needCheckOuterVal) {
needCheckOuterVal = false;
const lastMaybeVal = currentMaybeVal;

@@ -440,6 +438,4 @@ currentMaybeVal = getValue2();

if (!strictEqual(currentMaybeVal, lastMaybeVal)) {
innerDisposer &&= innerDisposer();
if (subs.s.size) {
innerDisposer = currentMaybeVal.$valCompute(subs.n);
}
innerDisposer?.();
innerDisposer = currentMaybeVal.$valCompute(agent.n);
}

@@ -453,4 +449,4 @@ } else {

currentValVersion = currentMaybeVal.$version;
if (useDefaultEqual && !strictEqual(currentValVersion, lastValVersion)) {
subs.b |= 12 /* ShouldInvoke */;
if (useDefaultEqual && agent.b & 1 /* Notifying */ && !strictEqual(currentValVersion, lastValVersion)) {
agent.b |= 2 /* ValueChanged */;
}

@@ -465,11 +461,7 @@ return currentMaybeVal.value;

(notify) => {
const outerDisposer = listen(() => {
dirty = true;
const outerDisposer = onChange(() => {
needCheckOuterVal = true;
notify();
});
if (!innerDisposer && isVal(currentMaybeVal)) {
innerDisposer = currentMaybeVal.$valCompute(notify);
}
return () => {
dirty = true;
innerDisposer &&= innerDisposer();

@@ -480,3 +472,3 @@ outerDisposer?.();

);
return new ValImpl(subs);
return new ValImpl(agent);
};

@@ -483,0 +475,0 @@

{
"name": "value-enhancer",
"version": "5.2.1",
"version": "5.3.0",
"private": false,

@@ -44,2 +44,15 @@ "description": "A tiny library to enhance value with reactive wrapper.",

],
"scripts": {
"prepublishOnly": "pnpm run build",
"lint": "eslint --ext .ts,.tsx . && prettier --check . && tsc --noEmit",
"test": "node --expose-gc ./node_modules/jest/bin/jest.js",
"test:CI": "tsc --noEmit -p ./test/tsconfig.json && node --expose-gc ./node_modules/jest/bin/jest.js --collect-coverage",
"docs": "typedoc --options typedoc.json",
"types": "cross-env NODE_ENV=production tsc --declaration --emitDeclarationOnly --jsx react --esModuleInterop --outDir dist",
"build:index": "tsup --config tsup-config/index.tsup.config.ts",
"build:collections": "tsup --config tsup-config/collections.tsup.config.ts",
"build": "cross-env NODE_ENV=production pnpm run build:index && cross-env NODE_ENV=production pnpm run build:collections",
"build:min": "cross-env NODE_ENV=production MINIFY=true pnpm run build:index && cross-env NODE_ENV=production MINIFY=true pnpm run build:collections && node scripts/gzip.mjs",
"release": "standard-version"
},
"devDependencies": {

@@ -63,15 +76,3 @@ "@jest/globals": "^29.5.0",

"yoctocolors": "^1.0.0"
},
"scripts": {
"lint": "eslint --ext .ts,.tsx . && prettier --check . && tsc --noEmit",
"test": "jest",
"test:CI": "tsc --noEmit -p ./test/tsconfig.json && jest --collect-coverage",
"docs": "typedoc --options typedoc.json",
"types": "cross-env NODE_ENV=production tsc --declaration --emitDeclarationOnly --jsx react --esModuleInterop --outDir dist",
"build:index": "tsup --config tsup-config/index.tsup.config.ts",
"build:collections": "tsup --config tsup-config/collections.tsup.config.ts",
"build": "cross-env NODE_ENV=production pnpm run build:index && cross-env NODE_ENV=production pnpm run build:collections",
"build:min": "cross-env NODE_ENV=production MINIFY=true pnpm run build:index && cross-env NODE_ENV=production MINIFY=true pnpm run build:collections && node scripts/gzip.mjs",
"release": "standard-version"
}
}
}

@@ -11,2 +11,4 @@ import type { Task } from "./scheduler";

const registry = /* @__PURE__ */ new FinalizationRegistry<() => void>(invoke);
export enum SubMode {

@@ -19,7 +21,5 @@ Async = 1,

export enum AgentStatus {
Notified = 1 << 0,
ValueDirty = 1 << 1,
ShouldInvokeEager = 1 << 2,
ShouldInvokeAsync = 1 << 3,
ShouldInvoke = AgentStatus.ShouldInvokeEager | AgentStatus.ShouldInvokeAsync,
Notifying = 1 << 0,
ValueChanged = 1 << 1,
NeedResolveValue = 1 << 2,
}

@@ -35,2 +35,3 @@

remove_(subscriber?: (...args: any[]) => any): void;
dispose_(): void;
}

@@ -42,13 +43,35 @@

config?: ValConfig<TValue>,
onStart?: (notify: () => void) => ValDisposer | void | undefined
onChange?: (notify: () => void) => ValDisposer | void | undefined
) {
this.#onStart = onStart;
this.#getValue = getValue;
this.equal_ = (config?.equal ?? strictEqual) || void 0;
this.eager_ = config?.eager;
if (onChange) {
const ref = new WeakRef(this);
const disposeEffect = () => {
if (disposeListen) {
// prevent infinite recursion if user returns the notify function
const dispose = disposeListen;
disposeListen = void 0;
dispose();
}
};
let disposeListen = onChange(() => {
const agent = ref.deref();
if (agent) {
agent.notify_();
} else {
disposeEffect();
}
});
if (disposeListen) {
registry.register(this, (this.#disposeEffect = disposeEffect));
}
}
}
public readonly subs_ = new Map<ValSubscriber<TValue>, SubMode>();
public status_: number = AgentStatus.ValueDirty;
public version_: ValVersion = INIT_VALUE;
public status_ = AgentStatus.NeedResolveValue;
public version_: ValVersion;
public value_: TValue = INIT_VALUE;

@@ -59,3 +82,4 @@ public equal_?: (newValue: TValue, oldValue: TValue) => boolean;

public resolveValue_ = (): TValue => {
if (this.status_ & AgentStatus.ValueDirty) {
if (this.status_ & AgentStatus.NeedResolveValue) {
this.status_ &= ~AgentStatus.NeedResolveValue;
const newValue = this.#getValue();

@@ -66,9 +90,7 @@ if (this.value_ === INIT_VALUE) {

this._bumpVersion_(newValue);
this.status_ |= AgentStatus.ShouldInvoke;
if (this.status_ & AgentStatus.Notifying) {
this.status_ |= AgentStatus.ValueChanged;
}
}
if (this.subs_.size) {
this.status_ &= ~AgentStatus.ValueDirty;
}
}
this.status_ &= ~AgentStatus.Notified;
return this.value_;

@@ -78,5 +100,5 @@ };

public notify_ = (): void => {
this.status_ |= AgentStatus.ValueDirty;
if (!(this.status_ & AgentStatus.Notified)) {
this.status_ |= AgentStatus.Notified;
this.status_ |= AgentStatus.NeedResolveValue;
if (this.subs_.size) {
this.status_ |= AgentStatus.Notifying;
if (this[SubMode.Computed]) {

@@ -87,17 +109,8 @@ this.#invoke(SubMode.Computed);

this.resolveValue_();
if (this.status_ & AgentStatus.ShouldInvokeEager) {
this.status_ &= ~AgentStatus.ShouldInvokeEager;
if (this.status_ & AgentStatus.ValueChanged) {
this.#invoke(SubMode.Eager);
} else {
this.status_ &= ~AgentStatus.ShouldInvoke;
return;
}
} else {
this.status_ &= ~AgentStatus.ShouldInvokeEager;
}
if (this[SubMode.Async]) {
schedule(this);
} else {
this.status_ &= ~AgentStatus.ShouldInvokeAsync;
}
// always schedule an async task for cleaning the Notifying status
schedule(this);
}

@@ -107,3 +120,2 @@ };

public add_(subscriber: ValSubscriber, mode: SubMode): () => void {
const oldSize = this.subs_.size;
const currentMode = this.subs_.get(subscriber);

@@ -116,9 +128,2 @@ if (currentMode) {

if (!oldSize) {
this.resolveValue_();
this.status_ &= ~AgentStatus.ShouldInvoke;
this.#onStartDisposer?.();
this.#onStartDisposer = this.#onStart?.(this.notify_);
}
return () => this.remove_(subscriber);

@@ -139,9 +144,2 @@ }

}
if (!this.subs_.size) {
this.status_ |= AgentStatus.ValueDirty;
if (this.#onStartDisposer) {
this.#onStartDisposer();
this.#onStartDisposer = null;
}
}
}

@@ -152,11 +150,15 @@

this.resolveValue_();
if (this.status_ & AgentStatus.ShouldInvokeAsync) {
this.status_ &= ~AgentStatus.ShouldInvokeAsync;
if (this.status_ & AgentStatus.ValueChanged) {
this.#invoke(SubMode.Async);
}
} else {
this.status_ &= ~AgentStatus.ShouldInvokeAsync;
}
this.status_ &= ~(AgentStatus.Notifying | AgentStatus.ValueChanged);
}
public dispose_(): void {
this.remove_();
registry.unregister(this);
this.#disposeEffect?.();
}
private _bumpVersion_(value: TValue): void {

@@ -183,6 +185,5 @@ this._bumpVersion_ = this.equal_?.(value, value)

#numberVersion = 0;
#disposeEffect?: () => void;
readonly #getValue: () => TValue;
readonly #onStart?: (notify: () => void) => ValDisposer | void | undefined;
#onStartDisposer?: ValDisposer | void | null;

@@ -236,2 +237,6 @@ #invoke(mode: SubMode): void {

}
public dispose_(): void {
this.remove_();
}
}
import type { ReadonlyVal, ValConfig } from "./typings";
import { from } from "./from";
import { INIT_VALUE, identity, strictEqual } from "./utils";
import { identity, INIT_VALUE, strictEqual } from "./utils";

@@ -6,0 +6,0 @@ export type DerivedValTransform<TValue = any, TDerivedValue = any> = (

@@ -19,3 +19,3 @@ import type {

* If the value is a val, it will be auto-flattened.
* @param listen A function that takes a notify function and returns a disposer.
* @param onChange A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.

@@ -25,23 +25,5 @@ * @param config custom config for the val.

*/
// export const flattenFrom2 = <TValOrValue = any>(
// getValue: () => TValOrValue,
// listen: (notify: () => void) => ValDisposer | void | undefined,
// config?: ValConfig<UnwrapVal<TValOrValue>>
// ): ReadonlyVal<UnwrapVal<TValOrValue>> =>
// new FlattenFromImpl(getValue, listen, config);
/**
* Creates a readonly val from a getter function and a listener function.
* If the value is a val, it will be auto-flattened.
*
* @param getValue A function that returns the current value.
* If the value is a val, it will be auto-flattened.
* @param listen A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.
* @param config custom config for the val.
* @returns A readonly val with value of inner val.
*/
export const flattenFrom = <TValOrValue = any>(
getValue: () => TValOrValue,
listen: (notify: () => void) => ValDisposer | void | undefined,
onChange: (notify: () => void) => ValDisposer | void | undefined,
config?: ValConfig<UnwrapVal<TValOrValue>>

@@ -52,11 +34,9 @@ ): ReadonlyVal<UnwrapVal<TValOrValue>> => {

let currentMaybeVal: TValOrValue = INIT_VALUE;
let dirty = true;
let needCheckOuterVal = true;
const useDefaultEqual = config?.equal == null;
const subs = new ValAgent(
const agent = new ValAgent(
() => {
if (dirty) {
if (subs.subs_.size) {
dirty = false;
}
if (needCheckOuterVal) {
needCheckOuterVal = false;

@@ -68,6 +48,4 @@ const lastMaybeVal = currentMaybeVal;

if (!strictEqual(currentMaybeVal, lastMaybeVal)) {
innerDisposer &&= innerDisposer();
if (subs.subs_.size) {
innerDisposer = currentMaybeVal.$valCompute(subs.notify_);
}
innerDisposer?.();
innerDisposer = currentMaybeVal.$valCompute(agent.notify_);
}

@@ -84,5 +62,6 @@ } else {

useDefaultEqual &&
agent.status_ & AgentStatus.Notifying &&
!strictEqual(currentValVersion, lastValVersion)
) {
subs.status_ |= AgentStatus.ShouldInvoke;
agent.status_ |= AgentStatus.ValueChanged;
}

@@ -97,11 +76,7 @@ return currentMaybeVal.value;

notify => {
const outerDisposer = listen(() => {
dirty = true;
const outerDisposer = onChange(() => {
needCheckOuterVal = true;
notify();
});
if (!innerDisposer && isVal(currentMaybeVal)) {
innerDisposer = currentMaybeVal.$valCompute(notify);
}
return () => {
dirty = true;
innerDisposer &&= innerDisposer();

@@ -113,3 +88,3 @@ outerDisposer?.();

return new ValImpl(subs);
return new ValImpl(agent);
};

@@ -47,3 +47,3 @@ import type { ReadonlyVal, UnwrapVal, ValConfig } from "./typings";

val: ReadonlyVal<TSrcValue>,
get: (value: TSrcValue) => TValOrValue,
get?: (value: TSrcValue) => TValOrValue,
config?: ValConfig<UnwrapVal<TValOrValue>>

@@ -50,0 +50,0 @@ ): ReadonlyVal<UnwrapVal<TValOrValue>>;

@@ -9,3 +9,3 @@ import { ValAgent } from "./agent";

* @param getValue A function that returns the current value.
* @param listen A function that takes a notify function and returns a disposer.
* @param onChange A function that takes a notify function and returns a disposer.
* The notify function should be called when the value changes.

@@ -38,6 +38,4 @@ * @param config custom config for the val.

getValue: () => TValue,
listen: (handler: () => void) => ValDisposer | void | undefined,
onChange: (notify: () => void) => ValDisposer | void | undefined,
config?: ValConfig<TValue>
): ReadonlyVal<TValue> => {
return new ValImpl(new ValAgent(getValue, config, listen));
};
): ReadonlyVal<TValue> => new ValImpl(new ValAgent(getValue, config, onChange));

@@ -13,4 +13,2 @@ import type {

/**
* @deprecated
* @ignore
* Set the value of a val.

@@ -107,5 +105,10 @@ * It works for both `Val` and `ReadonlyVal` type (if the `ReadonlyVal` is actually a `Val`).

export const invoke = <TValue>(
fn: (value: TValue) => void,
value: TValue
export interface Invoke {
(fn: () => void): void;
<TValue>(fn: (value: TValue) => void, value: TValue): void;
}
export const invoke: Invoke = <TValue>(
fn: (value?: TValue) => void,
value?: TValue
): void => {

@@ -112,0 +115,0 @@ try {

@@ -29,2 +29,3 @@ import type {

this.get = agent.resolveValue_;
agent.resolveValue_();
}

@@ -80,3 +81,3 @@

public dispose(): void {
this.#agent.remove_();
this.#agent.dispose_();
}

@@ -83,0 +84,0 @@

Sorry, the diff of this file is not supported yet

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