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

value-enhancer

Package Overview
Dependencies
Maintainers
1
Versions
87
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 2.4.4 to 3.0.0

dist/collections.cjs

249

dist/index.d.ts

@@ -1,122 +0,4 @@

interface ReadonlyVal<TValue = any> {
/** value */
readonly value: TValue;
/** Compare two values. Default `===`. */
compare(newValue: TValue, oldValue: TValue): boolean;
/**
* Subscribe to value changes without immediate emission.
* @param subscriber
* @param eager by default subscribers will be notified on next tick. set `true` to notify subscribers of value changes synchronously.
* @returns a disposer function that cancels the subscription
*/
reaction(subscriber: ValSubscriber<TValue>, eager?: boolean): ValDisposer;
/**
* Subscribe to value changes with immediate emission.
* @param subscriber
* @param eager by default subscribers will be notified on next tick. set `true` to notify subscribers of value changes synchronously.
* @returns a disposer function that cancels the subscription
*/
subscribe(subscriber: ValSubscriber<TValue>, eager?: boolean): ValDisposer;
/**
* Remove the given subscriber.
* Remove all if no subscriber provided.
* @param subscriber
*/
unsubscribe(subscriber?: (...args: any[]) => any): void;
/**
* Remove all subscribers.
*/
dispose(): void;
}
interface Val<TValue = any> extends ReadonlyVal<TValue> {
value: TValue;
/** set new value */
readonly set: (this: void, value: TValue) => void;
}
type ValCompare<TValue = any> = (newValue: TValue, oldValue: TValue) => boolean;
type ValSubscriber<TValue = any> = (newValue: TValue) => void;
type ValDisposer = () => void;
/** @ignore */
type ValOnStart = () => void | ValDisposer | undefined;
interface ValConfig<TValue = any> {
/**
* Compare two values. Default `===`.
*/
compare?: ValCompare<TValue>;
/**
* Set the default behavior of subscription and reaction.
* Emission triggers synchronously if `true`. Default `false`.
*/
eager?: boolean;
}
/** @ignore */
type ValInputsValueTuple<TValInputs extends readonly ReadonlyVal[]> = Readonly<{
[K in keyof TValInputs]: ExtractValValue<TValInputs[K]>;
}>;
/** @ignore */
type ExtractValValue<TVal> = TVal extends ReadonlyVal<infer TValue> ? TValue : never;
import { R as ReadonlyVal, V as ValInputsValueTuple, a as ValConfig, b as ValDisposer, c as ValSetValue, U as UnwrapVal, d as Val, e as ValSubscriber } from './typings-c9d13ac0.js';
export { f as ValCompare } from './typings-c9d13ac0.js';
declare enum SubscriberMode {
Async = 1,
Eager = 2,
Computed = 3
}
declare class Subscribers<TValue = any> {
constructor(val: ReadonlyVal<TValue>, start?: (() => void | ValDisposer | undefined) | null);
invoke_(): void;
add_(subscriber: ValSubscriber, mode: SubscriberMode): () => void;
remove_(subscriber: ValSubscriber): void;
clear_(): void;
exec_(mode: SubscriberMode): void;
shouldExec_: boolean;
readonly subscribers_: Map<ValSubscriber<TValue>, SubscriberMode>;
private _stop_;
private _getValue_;
private [SubscriberMode.Async];
private [SubscriberMode.Eager];
private [SubscriberMode.Computed];
private readonly _notReadySubscribers_;
private _start_?;
private _startDisposer_?;
}
declare class ReadonlyValImpl<TValue = any> implements ReadonlyVal<TValue> {
protected _subs_: Subscribers<TValue>;
protected _value_: TValue;
protected _set_: (value: TValue) => void;
constructor(value: TValue, { compare, eager }?: ValConfig<TValue>, start?: ValOnStart);
get value(): TValue;
eager: boolean;
compare(newValue: TValue, oldValue: TValue): boolean;
reaction(subscriber: ValSubscriber<TValue>, eager?: boolean): ValDisposer;
subscribe(subscriber: ValSubscriber<TValue>, eager?: boolean): ValDisposer;
/**
* @internal
* For computed vals
*/
_compute_(subscriber: ValSubscriber<void>): ValDisposer;
unsubscribe(subscriber?: (...args: any[]) => any): void;
dispose(): void;
/**
* @returns the string representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val(1)));
* console.log(`${v$}`); // "1"
* ```
*/
toString(): string;
/**
* @returns the JSON representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val({ a: 1 })));
* JSON.stringify(v$); // '{"a":1}'
* ```
*/
toJSON(key: string): unknown;
}
/** Returns the value passed in. */

@@ -131,19 +13,23 @@ declare const identity: <TValue>(value: TValue) => TValue;

/**
* Marks an object that implements `ReadonlyVal` interface to be `isVal` detectable.
* @ignore
* @deprecated No longer needed. `isVal` works without `markVal` now.
*/
declare const markVal: <T extends ReadonlyVal<any>>(val: T) => T;
declare const markVal: <T extends ReadonlyVal>(val: T) => T;
type CombineValTransform<TDerivedValue = any, TValues extends readonly any[] = any[], TMeta = any> = (newValues: TValues, oldValues?: TValues, meta?: TMeta) => TDerivedValue;
/**
* Creates a writable val.
* @returns A val with undefined value.
* Combines an array of vals into a single val with the array of values.
* @param valInputs An array of vals to combine.
* @returns A readonly val with the combined values.
*/
declare function val(): Val<undefined>;
declare function combine<TValInputs extends readonly ReadonlyVal[] = ReadonlyVal[]>(valInputs: readonly [...TValInputs]): ReadonlyVal<[...ValInputsValueTuple<TValInputs>]>;
/**
* Creates a writable val.
* @param value Initial value.
* @param config Custom config.
* Combines an array of vals into a single val with transformed value.
* @param valInputs An array of vals to combine.
* @param transform A pure function that takes an array of values and returns a new value.
* @param config custom config for the combined val.
* @returns A readonly val with the transformed values.
*/
declare function val<TValue = any>(value: TValue, config?: ValConfig<TValue>): Val<TValue>;
declare function combine<TValInputs extends readonly ReadonlyVal[] = ReadonlyVal[], TValue = any>(valInputs: readonly [...TValInputs], transform: CombineValTransform<TValue, [...ValInputsValueTuple<TValInputs>]>, config?: ValConfig<TValue>): ReadonlyVal<TValue>;
/** @ignore */
type DerivedValTransform<TValue = any, TDerivedValue = any> = (newValue: TValue) => TDerivedValue;

@@ -153,3 +39,3 @@ /**

* @param val Input value.
* @returns An readonly val with same value as the input val.
* @returns A readonly val with same value as the input val.
*/

@@ -162,45 +48,51 @@ declare function derive<TSrcValue = any, TValue = any>(val: ReadonlyVal<TSrcValue>): ReadonlyVal<TValue>;

* @param config custom config for the combined val.
* @returns An readonly val with transformed value from the input val.
* @returns A readonly val with transformed value from the input val.
*/
declare function derive<TSrcValue = any, TValue = any>(val: ReadonlyVal<TSrcValue>, transform: DerivedValTransform<TSrcValue, TValue>, config?: ValConfig<TValue>): ReadonlyVal<TValue>;
/** @ignore */
type CombineValTransform<TDerivedValue = any, TValues extends readonly any[] = any[], TMeta = any> = (newValues: TValues, oldValues?: TValues, meta?: TMeta) => TDerivedValue;
/**
* Combines an array of vals into a single val with the array of values.
* @param valInputs An array of vals to combine.
* @returns A readonly val with the combined values.
*/
declare function combine<TValInputs extends readonly ReadonlyVal[] = ReadonlyVal[]>(valInputs: readonly [...TValInputs]): ReadonlyVal<[...ValInputsValueTuple<TValInputs>]>;
/**
* Combines an array of vals into a single val with transformed value.
* @param valInputs An array of vals to combine.
* @param transform A pure function that takes an array of values and returns a new value.
* @param config custom config for the combined val.
* @returns A readonly val with the transformed values.
*/
declare function combine<TValInputs extends readonly ReadonlyVal[] = ReadonlyVal[], TValue = any>(valInputs: readonly [...TValInputs], transform: CombineValTransform<TValue, [...ValInputsValueTuple<TValInputs>]>, config?: ValConfig<TValue>): ReadonlyVal<TValue>;
/**
* Unwrap a val of val to a val of the inner val value.
* @param val Input value.
* @returns An readonly val with value of inner val.
* Creates a readonly val from a getter function and a listener function.
*
* @param getValue A function that returns the current value.
* @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.
*
* @example
* ```js
* import { unwrap, val } from "value-enhancer";
* ```ts
* const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
* const isDarkMode$ = from(
* () => prefersDark.matches,
* notify => {
* prefersDark.addEventListener("change", notify);
* return () => prefersDark.removeEventListener("change", notify);
* },
* );
* ```
*
* const inner$ = val(12);
* const outer$ = val(inner$);
*
* const unwrapped$ = unwrap(outer$);
*
* inner$.value === unwrapped$.value; // true
* @example An implementation of the `derive` function:
* ```ts
* const derive = (val, transform, config) => from(
* () => transform(val.value),
* notify => val.subscribe(notify),
* config,
* );
* ```
*/
declare function unwrap<TValue = any>(val: ReadonlyVal<ReadonlyVal<TValue>>): ReadonlyVal<TValue>;
declare const from: <TValue = any>(getValue: () => TValue, listen: (handler: () => void) => ValDisposer | void | undefined, config?: ValConfig<TValue> | undefined) => ReadonlyVal<TValue>;
/**
* Creates a readonly val with the given value.
*
* @param value Value for the val
* @param config Custom config for the val.
* @returns A tuple with the readonly val and a function to set the value.
*/
declare const readonlyVal: <TValue = any>(value: TValue, config?: ValConfig<TValue> | undefined) => [ReadonlyVal<TValue>, ValSetValue<TValue>];
/**
* Unwrap a val of val to a val of the inner val value.
* @param val Input value.
* @returns An readonly val with value of inner val.
* @returns A readonly val with value of inner val.
*

@@ -219,3 +111,3 @@ * @example

*/
declare function unwrap<TValue = any>(val: ReadonlyVal<Val<TValue>>): ReadonlyVal<TValue>;
declare function unwrap<TValOrValue = any>(val: ReadonlyVal<TValOrValue>): ReadonlyVal<UnwrapVal<TValOrValue>>;
/**

@@ -225,3 +117,3 @@ * Unwrap an inner val extracted from a source val to a val of the inner val value.

* @param get extract inner val or value from source val.
* @returns An readonly val with value of inner val.
* @returns A readonly val with value of inner val.
*

@@ -240,5 +132,30 @@ * @example

*/
declare function unwrap<TSrcValue = any, TValue = any>(val: ReadonlyVal<TSrcValue>, get: (value: TSrcValue) => ReadonlyVal<TValue> | TValue, config?: ValConfig<TValue>): ReadonlyVal<TValue>;
declare function unwrap<TSrcValue = any, TValOrValue = any>(val: ReadonlyVal<TSrcValue>, get: (value: TSrcValue) => TValOrValue, config?: ValConfig<UnwrapVal<TValOrValue>>): ReadonlyVal<UnwrapVal<TValOrValue>>;
/**
* Creates a readonly val from a getter function and a listener function.
* If the value is a val, it will be auto-unwrapped.
*
* @param getValue A function that returns the current value.
* If the value is a val, it will be auto-unwrapped.
* @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 unwrapFrom: <TValOrValue = any>(getValue: () => TValOrValue, listen: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<UnwrapVal<TValOrValue>> | undefined) => ReadonlyVal<UnwrapVal<TValOrValue>>;
/**
* Creates a writable val.
* @returns A val with undefined value.
*/
declare function val<TValue>(): Val<TValue | undefined>;
/**
* Creates a writable val.
* @param value Initial value.
* @param config Custom config.
*/
declare function val<TValue = any>(value: TValue, config?: ValConfig<TValue>): Val<TValue>;
/**
* Set the value of a val.

@@ -273,2 +190,2 @@ * It works for both `Val` and `ReadonlyVal` type (if the `ReadonlyVal` is actually a `Val`).

export { CombineValTransform, DerivedValTransform, ExtractValValue, ReadonlyVal, ReadonlyValImpl, Val, ValCompare, ValConfig, ValDisposer, ValInputsValueTuple, ValOnStart, ValSubscriber, combine, derive, identity, isVal, markVal, reaction, setValue, subscribe, unsubscribe, unwrap, val };
export { CombineValTransform, DerivedValTransform, ReadonlyVal, UnwrapVal, Val, ValConfig, ValDisposer, ValSetValue, ValSubscriber, combine, derive, from, identity, isVal, markVal, reaction, readonlyVal, setValue, subscribe, unsubscribe, unwrap, unwrapFrom, val };

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

'use strict';
// src/utils.ts
var identity = (value) => value;
var defaultCompare = (newValue, oldValue) => newValue === oldValue;
var getValue = (val2) => val2.value;
var getValues = (valInputs) => valInputs.map(getValue);
var invoke = (fn, value) => {
try {
fn(value);
} catch (e) {
console.error(e);
}
};
var INIT_VALUE = {};
var isVal = (val2) => !!val2?.$valCompute;
var markVal = identity;

@@ -20,32 +34,11 @@ // src/scheduler.ts

// src/utils.ts
var identity = (value) => value;
var getValue = (val2) => val2.value;
var getValues = (valInputs) => valInputs.map(getValue);
var invoke = (fn, value) => {
try {
fn(value);
} catch (e) {
console.error(e);
}
};
var INIT_VALUE = {};
var VAL_SYMBOL = "$\u2009val\u2009";
var isVal = (val2) => !!(val2 && val2[VAL_SYMBOL]);
var markVal = (val2) => {
Object.defineProperty(val2, VAL_SYMBOL, { value: 1 });
return val2;
};
var compute = (val2, subscriber) => val2._c(subscriber);
// src/subscribers.ts
var Subscribers = class {
constructor(val2, start) {
this._g = () => val2.value;
this.g = start;
constructor(getValue2, start) {
this._g = getValue2;
this.h = start;
}
i() {
if (this.d.size > 0) {
this.d.clear();
}
d = false;
n() {
this.f.clear();
if (this.b.size > 0) {

@@ -58,8 +51,8 @@ this.e(3 /* Computed */);

} else {
this.s = false;
this.d = false;
}
}
a(subscriber, mode) {
if (this.g && this.b.size <= 0) {
this.f = this.g();
if (this.h && this.b.size <= 0) {
this.g = this.h(this);
}

@@ -70,3 +63,3 @@ const currentMode = this.b.get(subscriber);

}
this.d.add(subscriber);
this.f.add(subscriber);
this.b.set(subscriber, mode);

@@ -77,3 +70,3 @@ this[mode]++;

r(subscriber) {
this.d.delete(subscriber);
this.f.delete(subscriber);
const mode = this.b.get(subscriber);

@@ -84,3 +77,3 @@ if (mode) {

if (this.b.size <= 0) {
this.h();
this.i();
}

@@ -91,6 +84,6 @@ }

this.b.clear();
this.d.clear();
this.f.clear();
this[1 /* Async */] = this[2 /* Eager */] = this[3 /* Computed */] = 0;
cancelTask(this);
this.h();
this.i();
}

@@ -102,16 +95,16 @@ e(mode) {

if (this[1 /* Async */] + this[2 /* Eager */] <= 0) {
this.s = false;
this.d = false;
}
} else {
value = this._g();
if (!this.s) {
if (!this.d) {
return;
}
if (mode === 1 /* Async */ || /* mode === SubscriberMode.Computed */
if (mode === 1 /* Async */ || /* mode === SubscriberMode.Eager && */
this[1 /* Async */] <= 0) {
this.s = false;
this.d = false;
}
}
for (const [sub, subMode] of this.b) {
if (subMode === mode && !this.d.has(sub)) {
if (subMode === mode && !this.f.has(sub)) {
invoke(sub, value);

@@ -122,6 +115,5 @@ }

}
s = false;
b = /* @__PURE__ */ new Map();
h() {
this.f && (this.f = this.f());
i() {
this.g && (this.g = this.g());
}

@@ -132,5 +124,5 @@ _g;

[3 /* Computed */] = 0;
d = /* @__PURE__ */ new Set();
f = /* @__PURE__ */ new Set();
h;
g;
f;
};

@@ -140,29 +132,26 @@

var ReadonlyValImpl = class {
_u;
_v;
_s = (value) => {
if (!this.compare(value, this._v)) {
this._u.s = true;
this._v = value;
this._u.i();
}
};
constructor(value, { compare, eager = false } = {}, start) {
markVal(this);
this._v = value;
this.eager = eager;
if (compare) {
this.compare = compare;
}
this._u = new Subscribers(this, start);
/**
* Manage subscribers for a val.
*/
_s;
_e;
/**
* @param get A pure function that returns the current value of the val.
* @param config Custom config for the val.
* @param start A function that is called when a val get its first subscriber.
* The returned disposer will be called when the last subscriber unsubscribed from the val.
*/
constructor(get, { compare = defaultCompare, eager } = {}, start) {
this.get = get;
this.compare = compare;
this._e = eager;
this._s = new Subscribers(get, start);
}
get value() {
return this._v;
return this.get();
}
eager;
compare(newValue, oldValue) {
return newValue === oldValue;
}
reaction(subscriber, eager = this.eager) {
return this._u.a(
get;
compare;
reaction(subscriber, eager = this._e) {
return this._s.a(
subscriber,

@@ -172,23 +161,20 @@ eager ? 2 /* Eager */ : 1 /* Async */

}
subscribe(subscriber, eager = this.eager) {
subscribe(subscriber, eager = this._e) {
const disposer = this.reaction(subscriber, eager);
invoke(subscriber, this.value);
this._s.d = false;
return disposer;
}
/**
* @internal
* For computed vals
*/
_c(subscriber) {
return this._u.a(subscriber, 3 /* Computed */);
$valCompute(subscriber) {
return this._s.a(subscriber, 3 /* Computed */);
}
unsubscribe(subscriber) {
if (subscriber) {
this._u.r(subscriber);
this._s.r(subscriber);
} else {
this._u.c();
this._s.c();
}
}
dispose() {
this._u.c();
this._s.c();
}

@@ -221,168 +207,181 @@ /**

};
// src/val.ts
var ValImpl = class extends ReadonlyValImpl {
constructor(value, config) {
super(value, config);
}
get value() {
return this._v;
}
set value(value) {
this._s(value);
}
/** Set new value */
set = this._s;
var readonlyVal = (value, config) => {
let currentValue = value;
let subs;
const set = (value2) => {
if (!val2.compare(value2, currentValue)) {
currentValue = value2;
if (subs) {
subs.d = true;
subs.n();
}
}
};
const val2 = new ReadonlyValImpl(
() => currentValue,
config,
(s) => {
subs = s;
}
);
return [val2, set];
};
function val(value, config) {
return new ValImpl(value, config);
}
// src/derived-val.ts
var DerivedValImpl = class extends ReadonlyValImpl {
constructor(val2, transform, config) {
const getValue2 = () => transform(val2.value);
super(INIT_VALUE, config, () => {
if (this._v === INIT_VALUE) {
this._v = getValue2();
} else {
this._d = this._d || 1;
// src/from.ts
var FromImpl = class extends ReadonlyValImpl {
constructor(getValue2, listen, config) {
let currentValue = INIT_VALUE;
let dirty = false;
let notified = false;
const get = () => {
if (currentValue === INIT_VALUE || this._s.b.size <= 0) {
currentValue = getValue2();
} else if (dirty) {
const value = getValue2();
if (!this.compare(value, currentValue)) {
this._s.d = true;
currentValue = value;
}
}
return compute(val2, () => {
if (this._d < 2) {
this._d = 2;
this._u.i();
}
});
dirty = notified = false;
return currentValue;
};
const notify = () => {
dirty = true;
if (!notified) {
notified = true;
this._s.n();
}
};
super(get, config, () => {
currentValue = getValue2();
dirty = notified = false;
return listen(notify);
});
this._g = getValue2;
}
get value() {
if (this._v === INIT_VALUE) {
this._v = this._g();
this._u.s = true;
} else if (this._d || this._u.b.size <= 0) {
const value = this._g();
if (!this.compare(value, this._v)) {
this._u.s = true;
this._v = value;
}
}
this._d = 0;
return this._v;
}
_g;
_d = 0;
};
function derive(val2, transform = identity, config) {
return new DerivedValImpl(val2, transform, config);
}
var from = (getValue2, listen, config) => new FromImpl(getValue2, listen, config);
// src/combine.ts
var CombinedValImpl = class extends ReadonlyValImpl {
constructor(valInputs, transform, config) {
const getValue2 = () => transform(getValues(valInputs));
super(INIT_VALUE, config, () => {
if (this._v === INIT_VALUE) {
this._v = getValue2();
} else {
this._d = this._d || 1;
}
const disposers = valInputs.map(
(val2) => compute(val2, () => {
if (this._d < 2) {
this._d = 2;
this._u.i();
}
})
);
function combine(valInputs, transform = identity, config) {
return from(
() => transform(getValues(valInputs)),
(notify) => {
const disposers = valInputs.map((val2) => val2.$valCompute(notify));
return () => disposers.forEach(invoke);
});
this._g = getValue2;
}
get value() {
if (this._v === INIT_VALUE) {
this._v = this._g();
this._u.s = true;
} else if (this._d || this._u.b.size <= 0) {
const value = this._g();
if (!this.compare(value, this._v)) {
this._u.s = true;
this._v = value;
}
}
this._d = 0;
return this._v;
}
_g;
_d = 0;
};
function combine(valInputs, transform = identity, config) {
return new CombinedValImpl(valInputs, transform, config);
},
config
);
}
// src/unwrap-val.ts
var UnwrapValImpl = class extends ReadonlyValImpl {
constructor(val2, get = identity, config) {
let innerValue;
super(INIT_VALUE, config, () => {
innerValue = get(val2.value);
if (this._v === INIT_VALUE) {
this._v = isVal(innerValue) ? innerValue.value : innerValue;
} else {
this._d = this._d || 1;
// src/derive.ts
function derive(val2, transform = identity, config) {
return from(
() => transform(val2.value),
(notify) => val2.$valCompute(notify),
config
);
}
// src/unwrap-from.ts
var UnwrapFromImpl = class extends ReadonlyValImpl {
constructor(getValue2, listen, config) {
const initialCompare = config?.compare;
let currentValue = INIT_VALUE;
let dirty = false;
let notified = false;
let innerMaybeVal;
let innerVal;
let innerDisposer;
const computeValue = () => {
if (this._s.b.size <= 0) {
updateInnerVal();
}
const markDirty = () => {
if (this._d < 2) {
this._d = 2;
this._u.i();
return innerVal ? innerVal.value : innerMaybeVal;
};
const get = () => {
if (currentValue === INIT_VALUE || this._s.b.size <= 0) {
currentValue = computeValue();
} else if (dirty) {
const value = computeValue();
if (!this.compare(value, currentValue)) {
this._s.d = true;
currentValue = value;
}
};
let innerDisposer = isVal(innerValue) && compute(innerValue, markDirty);
const outerDisposer = compute(val2, () => {
innerDisposer && innerDisposer();
innerValue = get(val2.value);
innerDisposer = isVal(innerValue) && compute(innerValue, markDirty);
markDirty();
}
dirty = notified = false;
return currentValue;
};
const updateInnerVal = () => {
const maybeVal = getValue2();
if (maybeVal !== innerMaybeVal) {
innerMaybeVal = maybeVal;
innerVal = isVal(maybeVal) ? maybeVal : null;
innerDisposer?.();
innerDisposer = innerVal && innerVal.$valCompute(notify);
currentCompare = initialCompare || (innerVal ? innerVal.compare : defaultCompare);
}
};
const notify = () => {
dirty = true;
if (!notified) {
notified = true;
this._s.n();
}
};
super(get, config, () => {
updateInnerVal();
currentValue = innerVal ? innerVal.value : innerMaybeVal;
dirty = notified = false;
const outerDisposer = listen(() => {
updateInnerVal();
notify();
});
return () => {
innerDisposer && innerDisposer();
outerDisposer();
innerDisposer?.();
outerDisposer?.();
};
});
this._g = () => {
if (this._u.b.size <= 0 || !innerValue) {
innerValue = get(val2.value);
let currentCompare = this.compare;
this.compare = (newValue, oldValue) => currentCompare(newValue, oldValue);
}
};
var unwrapFrom = (getValue2, listen, config) => new UnwrapFromImpl(getValue2, listen, config);
// src/unwrap.ts
function unwrap(val2, get = identity, config) {
return unwrapFrom(
() => get(val2.value),
(notify) => val2.$valCompute(notify),
config
);
}
// src/val.ts
var ValImpl = class extends ReadonlyValImpl {
constructor(currentValue, config) {
const get = () => currentValue;
super(get, config);
this.set = (value) => {
if (!this.compare(value, currentValue)) {
this._s.d = true;
currentValue = value;
this._s.n();
}
return isVal(innerValue) ? innerValue.value : innerValue;
};
this._m = (newValue, oldValue) => isVal(innerValue) ? innerValue.compare(newValue, oldValue) : super.compare(newValue, oldValue);
}
set;
get value() {
if (this._v === INIT_VALUE) {
this._v = this._g();
this._u.s = true;
} else if (this._d || this._u.b.size <= 0) {
const value = this._g();
if (!this.compare(value, this._v)) {
this._u.s = true;
this._v = value;
}
}
this._d = 0;
return this._v;
return this.get();
}
compare(newValue, oldValue) {
return this._m(newValue, oldValue);
set value(value) {
this.set(value);
}
_m;
_g;
_d = 0;
};
function unwrap(val2, get, config) {
return new UnwrapValImpl(val2, get, config);
function val(value, config) {
return new ValImpl(value, config);
}
// src/value-enhancer.ts
var setValue = (val2, value) => val2.set && val2.set(value);
var setValue = (val2, value) => val2.set?.(value);
var subscribe = (val2, subscriber, eager) => val2.subscribe(subscriber, eager);

@@ -392,15 +391,2 @@ var reaction = (val2, subscriber, eager) => val2.reaction(subscriber, eager);

exports.ReadonlyValImpl = ReadonlyValImpl;
exports.combine = combine;
exports.derive = derive;
exports.identity = identity;
exports.isVal = isVal;
exports.markVal = markVal;
exports.reaction = reaction;
exports.setValue = setValue;
exports.subscribe = subscribe;
exports.unsubscribe = unsubscribe;
exports.unwrap = unwrap;
exports.val = val;
//# sourceMappingURL=out.js.map
//# sourceMappingURL=index.js.map
export { combine, derive, from, identity, isVal, markVal, reaction, readonlyVal, setValue, subscribe, unsubscribe, unwrap, unwrapFrom, val };
{
"name": "value-enhancer",
"version": "2.4.4",
"version": "3.0.0",
"private": false,

@@ -19,5 +19,27 @@ "description": "A tiny library to enhance value with reactive wrapper.",

"sideEffects": false,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"type": "module",
"main": "./dist/index.cjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.cjs",
"import": "./dist/index.js"
},
"./collection": {
"types": "./dist/collections.d.ts",
"require": "./dist/collections.cjs",
"import": "./dist/collections.js"
}
},
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
".": [
"dist/index.d.ts"
],
"collection": [
"dist/collections.d.ts"
]
}
},
"files": [

@@ -31,6 +53,6 @@ "src",

"test": "jest",
"docs": "typedoc --cname value-enhancer.js.org --includeVersion --excludePrivate --excludeProtected --excludeInternal --out docs src/index.ts",
"docs": "typedoc --options typedoc.json",
"types": "cross-env NODE_ENV=production tsc --declaration --emitDeclarationOnly --jsx react --esModuleInterop --outDir dist",
"build": "cross-env NODE_ENV=production tsup-node src/index.ts",
"build:min": "cross-env NODE_ENV=production MINIFY=true tsup-node src/index.ts && node scripts/gzip.mjs",
"build": "cross-env NODE_ENV=production tsup-node",
"build:min": "cross-env NODE_ENV=production MINIFY=true tsup-node && node scripts/gzip.mjs",
"build:dev": "cross-env NODE_ENV=development tsup-node src/index.ts",

@@ -54,3 +76,3 @@ "release": "standard-version"

"tsup": "^6.6.3",
"typedoc": "^0.23.26",
"typedoc": "^0.24.8",
"typescript": "^4.9.5",

@@ -57,0 +79,0 @@ "yoctocolors": "^1.0.0"

@@ -12,3 +12,3 @@ # [value-enhancer](https://github.com/crimx/value-enhancer)

[![full-size](https://img.shields.io/bundlephobia/minzip/value-enhancer)](https://bundlejs.com/?q=value-enhancer)
[![core-size](https://runkit.io/crimx/bundlejs-badge/branches/master?q=value-enhancer&exports=val&label=core%20size)](https://bundlejs.com/?q=value-enhancer&treeshake=%5B%7Bval%7D%5D)
[![core-size](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fdeno.bundlejs.com%2F%3Fq%3Dvalue-enhancer%26treeshake%3D%255B%257B%2520val%2520%257D%255D&query=%24.size.size&label=core%20size)](https://bundlejs.com/?q=value-enhancer&treeshake=%5B%7Bval%7D%5D)
[![tree-shakable](https://img.shields.io/badge/%20tree-shakable-success)](https://bundlejs.com/?q=value-enhancer)

@@ -32,2 +32,6 @@ [![no-dependencies](https://img.shields.io/badge/dependencies-none-success)](https://bundlejs.com/?q=value-enhancer)

## Docs
<https://value-enhancer.js.org/>
## Features

@@ -39,3 +43,3 @@

It does not convert the value with `Object.defineProperty` nor `Proxy`. Keeping everything as plain JavaScript value makes it easier to work with other libraries and easier for the JavaScript engine to optimize.
- Safe and fast.
- Safe and fast lazy computation.
It solves multi-level derivation issue (like in Svelte Stores) with smart lazy value evaluation.

@@ -45,3 +49,3 @@ - Explicit.

- Simple DX.
No hidden rules for getting or setting values. What you see is what you get.
Designed with ergonomics in mind. No hidden rules for getting or setting values. What you see is what you get.
- Bundle size and Performance.

@@ -57,3 +61,3 @@ By carefully defining scope and choosing right features that balance usability and performance, less work needed to be done in `value-enhancer` which makes it smaller and faster.

MobX does not work well with other libraries. It could break other libraries if you forget to exclude instances from other libraries from making observable. `toJS` is also needed if data is passed to other libraries.
MobX does not work well with other libraries. It could break other libraries if you forget to exclude third-party instances from making observable. `toJS` is also needed if data is passed to other libraries.

@@ -138,2 +142,4 @@ MobX also prints error when it sees another version of MobX in the global. It is not a good choice for making SDK or library that will be delivered into customer's environment.

`value-enhancer` also fixes the edge cases of Svelte stores by leveraging Vue's layered subscriber design.
</details>

@@ -205,3 +211,3 @@

## Create Val
## Create Writable Val

@@ -222,2 +228,18 @@ ```js

## Create Readonly Val
```js
import { readonlyVal } from "value-enhancer";
const [count$, setCount] = readonlyVal(2);
console.log(count$.value); // 2
setCount(3);
console.log(count$.value); // 3
count$.value = 4;
console.log(count$.value); // 4
```
## Subscribe to value changes

@@ -246,3 +268,3 @@

await Promise.resolve(); // wait for the next tick
await Promise.resolve(); // subscription triggered asynchronously by default

@@ -258,3 +280,3 @@ // printed "subscribe: 4"

Derive a new Val from another Val.
`derive` a new Val from another Val.

@@ -273,3 +295,3 @@ ```js

Combine multiple Vals into a new Val.
`combine` multiple Vals into a new Val.

@@ -293,3 +315,3 @@ ```js

Unwrap the inner Val from a Val of Val. This is useful for subscribing to a dynamic Val that is inside another Val.
`unwrap` the inner Val from a Val of Val. This is useful for subscribing to a dynamic Val that is inside another Val.

@@ -310,2 +332,24 @@ ```js

## From
`from` creates a Val from any value source. Both `derive` and `combine` are implemented using `from`.
```ts
import { from } from "value-enhancer";
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
const isDarkMode$ = from(
() => prefersDark.matches,
notify => {
prefersDark.addEventListener("change", notify);
return () => prefersDark.removeEventListener("change", notify);
}
);
```
## UnwrapFrom
`unwrapFrom` creates a Val from any value source like `from` but also unwrap the value if the value is a Val. `unwrap` is implemented using `unwrapFrom`.
## Custom Compare

@@ -346,53 +390,38 @@

## Custom Val
## Reactive Collections
You can create your own Val by extending `ReadonlyValImpl` class, or implement the `ReadonlyVal` interface and mark manually with `markVal` function.
The Reactive Collections are a group of classes that expand on the built-in JavaScript collections, allowing changes to the collections to be observed. See [docs](https://value-enhancer.js.org/modules/collections.html) for API details.
```js
import { ReadonlyValImpl, isVal } from "value-enhancer";
```ts
import { ReactiveList, fromCollection } from "value-enhancer/collections";
class MyVal extends ReadonlyValImpl {
constructor(value) {
super(value);
}
const list = new ReactiveList(["a", "b", "c"]);
set(value) {
console.log("set", value);
this._set(value);
}
}
const item$ = fromCollection(list, 2); // watch the item at index 2
const myVal = new MyVal(11);
myVal.set(22); // printed "set 22"
console.log(item$.value); // "c"
console.log(isVal(myVal)); // true
list.set(2, "d");
console.log(item$.value); // "d"
```
```js
import { val, isVal, markVal, identity } from "value-enhancer";
```ts
import { ReactiveMap, unwrapFromCollection } from "value-enhancer/collections";
import { val } from "value-enhancer";
const createMyVal = value => {
const v = val(value);
const map = new ReactiveMap();
const v = val("someValue");
const myVal = {
value: 11,
compare: identity,
reaction: v.reaction.bind(v),
subscribe: v.subscribe.bind(v),
unsubscribe: v.unsubscribe.bind(v),
set(value) {
console.log("set", value);
this.value = value;
},
};
const item$ = unwrapFromCollection(map, "someKey"); // watch the item at "someKey"
markVal(myVal);
console.log(item$.value); // undefined
return myVal;
};
map.set("someKey", v);
const myVal = createMyVal(11);
myVal.set(22); // printed "set 22"
console.log(item$.value); // "someValue"
console.log(isVal(myVal)); // true
v.set("someValue2");
console.log(item$.value); // "someValue2"
```

@@ -1,6 +0,6 @@

import { ReadonlyValImpl } from "./readonly-val";
import type { ReadonlyVal, ValInputsValueTuple, ValConfig } from "./typings";
import { invoke, getValues, INIT_VALUE, identity, compute } from "./utils";
import type { ReadonlyVal, ValConfig, ValInputsValueTuple } from "./typings";
/** @ignore */
import { from } from "./from";
import { getValues, identity, invoke } from "./utils";
export type CombineValTransform<

@@ -12,58 +12,2 @@ TDerivedValue = any,

class CombinedValImpl<
TValInputs extends readonly ReadonlyVal[] = ReadonlyVal[],
TValue = any
>
extends ReadonlyValImpl<TValue>
implements ReadonlyVal<TValue>
{
public constructor(
valInputs: TValInputs,
transform: CombineValTransform<
TValue,
[...ValInputsValueTuple<TValInputs>]
>,
config?: ValConfig<TValue>
) {
const getValue = () => transform(getValues(valInputs));
super(INIT_VALUE, config, () => {
if (this._value_ === INIT_VALUE) {
this._value_ = getValue();
} else {
this._dirtyLevel_ = this._dirtyLevel_ || 1;
}
const disposers = valInputs.map(val =>
compute(val, () => {
if (this._dirtyLevel_ < 2) {
this._dirtyLevel_ = 2;
this._subs_.invoke_();
}
})
);
return () => disposers.forEach(invoke);
});
this._getValue_ = getValue;
}
public override get value(): TValue {
if (this._value_ === INIT_VALUE) {
this._value_ = this._getValue_();
this._subs_.shouldExec_ = true;
} else if (this._dirtyLevel_ || this._subs_.subscribers_.size <= 0) {
const value = this._getValue_();
if (!this.compare(value, this._value_)) {
this._subs_.shouldExec_ = true;
this._value_ = value;
}
}
this._dirtyLevel_ = 0;
return this._value_;
}
private _getValue_: () => TValue;
private _dirtyLevel_ = 0;
}
/**

@@ -108,3 +52,10 @@ * Combines an array of vals into a single val with the array of values.

): ReadonlyVal<TValue> {
return new CombinedValImpl(valInputs, transform, config);
return from(
() => transform(getValues(valInputs)),
notify => {
const disposers = valInputs.map(val => val.$valCompute(notify));
return () => disposers.forEach(invoke);
},
config
);
}
export type {
ReadonlyVal,
UnwrapVal,
Val,
ValCompare,
ValConfig,
ValDisposer,
ValSetValue,
ValSubscriber,
ValDisposer,
ValConfig,
ValInputsValueTuple,
ExtractValValue,
ValOnStart,
} from "./typings";
export { ReadonlyValImpl } from "./readonly-val";
export { identity, isVal, markVal } from "./utils";
export { combine, type CombineValTransform } from "./combine";
export { derive, type DerivedValTransform } from "./derive";
export { from } from "./from";
export { readonlyVal } from "./readonly-val";
export { unwrap } from "./unwrap";
export { unwrapFrom } from "./unwrap-from";
export { val } from "./val";
export { derive, type DerivedValTransform } from "./derived-val";
export { combine, type CombineValTransform } from "./combine";
export { unwrap } from "./unwrap-val";
export { setValue, subscribe, reaction, unsubscribe } from "./value-enhancer";
export { reaction, setValue, subscribe, unsubscribe } from "./value-enhancer";

@@ -1,55 +0,52 @@

import { SubscriberMode, Subscribers } from "./subscribers";
import type { ValOnStart } from "./subscribers";
import type {
ReadonlyVal,
ValConfig,
ValDisposer,
ValSetValue,
ValSubscriber,
ValConfig,
ValOnStart,
ReadonlyVal,
} from "./typings";
import { invoke, markVal } from "./utils";
import { SubscriberMode, Subscribers } from "./subscribers";
import { defaultCompare, invoke } from "./utils";
/**
* Bare minimum implementation of a readonly val.
*/
export class ReadonlyValImpl<TValue = any> implements ReadonlyVal<TValue> {
/**
* Manage subscribers for a val.
*/
protected _subs_: Subscribers<TValue>;
protected _value_: TValue;
private _eager_?: boolean;
protected _set_ = (value: TValue): void => {
if (!this.compare(value, this._value_)) {
this._subs_.shouldExec_ = true;
this._value_ = value;
this._subs_.invoke_();
}
};
/**
* @param get A pure function that returns the current value of the val.
* @param config Custom config for the val.
* @param start A function that is called when a val get its first subscriber.
* The returned disposer will be called when the last subscriber unsubscribed from the val.
*/
public constructor(
value: TValue,
{ compare, eager = false }: ValConfig<TValue> = {},
get: () => TValue,
{ compare = defaultCompare, eager }: ValConfig<TValue> = {},
start?: ValOnStart
) {
markVal(this);
this._value_ = value;
this.eager = eager;
if (compare) {
this.compare = compare;
}
this._subs_ = new Subscribers<TValue>(this, start);
this.get = get;
this.compare = compare;
this._eager_ = eager;
this._subs_ = new Subscribers<TValue>(get, start);
}
public get value(): TValue {
return this._value_;
return this.get();
}
public eager: boolean;
public get: (this: void) => TValue;
public compare(newValue: TValue, oldValue: TValue): boolean {
return newValue === oldValue;
}
public compare: (this: void, newValue: TValue, oldValue: TValue) => boolean;
public reaction(
subscriber: ValSubscriber<TValue>,
eager: boolean = this.eager
eager = this._eager_
): ValDisposer {

@@ -64,14 +61,11 @@ return this._subs_.add_(

subscriber: ValSubscriber<TValue>,
eager: boolean = this.eager
eager = this._eager_
): ValDisposer {
const disposer = this.reaction(subscriber, eager);
invoke(subscriber, this.value);
this._subs_.dirty_ = false;
return disposer;
}
/**
* @internal
* For computed vals
*/
public _compute_(subscriber: ValSubscriber<void>): ValDisposer {
public $valCompute(subscriber: ValSubscriber<void>): ValDisposer {
return this._subs_.add_(subscriber, SubscriberMode.Computed);

@@ -122,1 +116,37 @@ }

}
/**
* Creates a readonly val with the given value.
*
* @param value Value for the val
* @param config Custom config for the val.
* @returns A tuple with the readonly val and a function to set the value.
*/
export const readonlyVal = <TValue = any>(
value: TValue,
config?: ValConfig<TValue>
): [ReadonlyVal<TValue>, ValSetValue<TValue>] => {
let currentValue = value;
let subs: Subscribers;
const set = (value: TValue): void => {
if (!val.compare(value, currentValue)) {
currentValue = value;
if (subs) {
subs.dirty_ = true;
subs.notify_();
}
}
};
const val = new ReadonlyValImpl(
() => currentValue,
config,
s => {
subs = s;
}
);
return [val, set];
};

@@ -0,3 +1,4 @@

import type { ValDisposer, ValSubscriber } from "./typings";
import { cancelTask, schedule } from "./scheduler";
import type { ReadonlyVal, ValDisposer, ValSubscriber } from "./typings";
import { invoke } from "./utils";

@@ -11,15 +12,21 @@

export class Subscribers<TValue = any> {
public constructor(
val: ReadonlyVal<TValue>,
start?: (() => void | ValDisposer | undefined) | null
) {
this._getValue_ = () => val.value;
/**
* A function that is called when a val get its first subscriber.
* The returned disposer will be called when the last subscriber unsubscribed from the val.
*/
export type ValOnStart = (subs: Subscribers) => void | ValDisposer | undefined;
/**
* Manage subscribers for a val.
*/
export class Subscribers<TValue = any> implements Subscribers {
public constructor(getValue: () => TValue, start?: ValOnStart | null) {
this._getValue_ = getValue;
this._start_ = start;
}
public invoke_(): void {
if (this._notReadySubscribers_.size > 0) {
this._notReadySubscribers_.clear();
}
public dirty_ = false;
public notify_(): void {
this._notReadySubscribers_.clear();
if (this.subscribers_.size > 0) {

@@ -32,3 +39,3 @@ this.exec_(SubscriberMode.Computed);

} else {
this.shouldExec_ = false;
this.dirty_ = false;
}

@@ -39,3 +46,4 @@ }

if (this._start_ && this.subscribers_.size <= 0) {
this._startDisposer_ = this._start_();
// Subscribe added, clear notified state
this._startDisposer_ = this._start_(this);
}

@@ -82,7 +90,7 @@

if (this[SubscriberMode.Async] + this[SubscriberMode.Eager] <= 0) {
this.shouldExec_ = false;
this.dirty_ = false;
}
} else {
value = this._getValue_();
if (!this.shouldExec_) {
if (!this.dirty_) {
return;

@@ -92,5 +100,5 @@ }

mode === SubscriberMode.Async ||
/* mode === SubscriberMode.Computed */ this[SubscriberMode.Async] <= 0
/* mode === SubscriberMode.Eager && */ this[SubscriberMode.Async] <= 0
) {
this.shouldExec_ = false;
this.dirty_ = false;
}

@@ -106,4 +114,2 @@ }

public shouldExec_ = false;
public readonly subscribers_ = new Map<

@@ -126,4 +132,4 @@ ValSubscriber<TValue>,

private _start_?: (() => void | ValDisposer | undefined) | null;
private _start_?: ValOnStart | null;
private _startDisposer_?: ValDisposer | void | null;
}
export interface ReadonlyVal<TValue = any> {
/** value */
/** Current value of the val */
readonly value: TValue;
/** Get current value of the val */
get(this: void): TValue;
/** Compare two values. Default `===`. */
compare(newValue: TValue, oldValue: TValue): boolean;
compare(this: void, newValue: TValue, oldValue: TValue): boolean;
/**

@@ -21,2 +23,8 @@ * Subscribe to value changes without immediate emission.

/**
* Subscribe to value changes and get invoked before {@link ReadonlyVal#subscribe} and {@link ReadonlyVal#reaction}.
* @param subscriber
* @returns a disposer function that cancels the subscription
*/
$valCompute(subscriber: ValSubscriber<void>): ValDisposer;
/**
* Remove the given subscriber.

@@ -34,5 +42,6 @@ * Remove all if no subscriber provided.

export interface Val<TValue = any> extends ReadonlyVal<TValue> {
/** Current value of the val */
value: TValue;
/** set new value */
readonly set: (this: void, value: TValue) => void;
/** Set new value */
set(this: void, value: TValue): void;
}

@@ -51,5 +60,5 @@

/** @ignore */
export type ValOnStart = () => void | ValDisposer | undefined;
/**
* Custom config for the val.
*/
export interface ValConfig<TValue = any> {

@@ -67,3 +76,5 @@ /**

/** @ignore */
export type UnwrapVal<T> = T extends ReadonlyVal<infer TValue> ? TValue : T;
/** @internal */
export type ValInputsValueTuple<TValInputs extends readonly ReadonlyVal[]> =

@@ -74,5 +85,5 @@ Readonly<{

/** @ignore */
/** @internal */
export type ExtractValValue<TVal> = TVal extends ReadonlyVal<infer TValue>
? TValue
: never;

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

import type { ReadonlyValImpl } from "./readonly-val";
import type {
ReadonlyVal,
ValInputsValueTuple,
ValDisposer,
ValSubscriber,
} from "./typings";
import type { ReadonlyVal, ValInputsValueTuple } from "./typings";

@@ -12,2 +6,7 @@ /** Returns the value passed in. */

export const defaultCompare = <TValue = any>(
newValue: TValue,
oldValue: TValue
): boolean => newValue === oldValue;
const getValue = <TValue>(val: ReadonlyVal<TValue>): TValue => val.value;

@@ -33,4 +32,2 @@

const VAL_SYMBOL = "$\u2009val\u2009";
/**

@@ -42,15 +39,8 @@ * Checks if `val` is `ReadonlyVal` or `Val`.

export const isVal = <T>(val: T): val is T extends ReadonlyVal ? T : never =>
!!(val && (val as any)[VAL_SYMBOL]);
!!(val as ReadonlyVal | undefined)?.$valCompute;
/**
* Marks an object that implements `ReadonlyVal` interface to be `isVal` detectable.
* @ignore
* @deprecated No longer needed. `isVal` works without `markVal` now.
*/
export const markVal = <T extends ReadonlyVal>(val: T): T => {
Object.defineProperty(val, VAL_SYMBOL, { value: 1 });
return val;
};
export const compute = (
val: ReadonlyVal,
subscriber: ValSubscriber<void>
): ValDisposer => (val as ReadonlyValImpl)._compute_(subscriber);
export const markVal: <T extends ReadonlyVal>(val: T) => T = identity;

@@ -1,22 +0,29 @@

import { ReadonlyValImpl } from "./readonly-val";
import type { Val, ValConfig } from "./typings";
class ValImpl<TValue = any>
extends ReadonlyValImpl<TValue>
implements Val<TValue>
{
public constructor(value: TValue, config?: ValConfig<TValue>) {
super(value, config);
import { ReadonlyValImpl } from "./readonly-val";
class ValImpl<TValue = any> extends ReadonlyValImpl<TValue> {
public constructor(currentValue: TValue, config?: ValConfig<TValue>) {
const get = () => currentValue;
super(get, config);
this.set = (value: TValue) => {
if (!this.compare(value, currentValue)) {
this._subs_.dirty_ = true;
currentValue = value;
this._subs_.notify_();
}
};
}
public override get value(): TValue {
return this._value_;
public set: (this: void, value: TValue) => void;
public override get value() {
return this.get();
}
public override set value(value: TValue) {
this._set_(value);
this.set(value);
}
/** Set new value */
public set: (value: TValue) => void = this._set_;
}

@@ -28,3 +35,3 @@

*/
export function val(): Val<undefined>;
export function val<TValue>(): Val<TValue | undefined>;
/**

@@ -31,0 +38,0 @@ * Creates a writable val.

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

import type { ReadonlyVal, Val, ValSubscriber, ValDisposer } from "./typings";
import type { ReadonlyVal, Val, ValDisposer, ValSubscriber } from "./typings";

@@ -11,3 +11,3 @@ /**

value: TValue
): void => (val as Val<TValue>).set && (val as Val<TValue>).set(value);
): void => (val as Val<TValue>).set?.(value);

@@ -14,0 +14,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