Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@nerdalytics/beacon

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nerdalytics/beacon - npm Package Compare versions

Comparing version
1000.3.0
to
1000.3.1
+1
-1
dist/src/index.d.ts

@@ -19,3 +19,3 @@ type Unsubscribe = () => void;

declare const createProtectedState: <T>(initialValue: T, equalityFn?: (a: T, b: T) => boolean) => [ReadOnlyState<T>, WriteableState<T>];
export type { ReadOnlyState, State, Unsubscribe, WriteableState };
export { createDerive as derive, createEffect as effect, createLens as lens, createProtectedState as protectedState, createReadonlyState as readonlyState, createSelect as select, createState as state, executeBatch as batch, };
export type { ReadOnlyState, State, Unsubscribe, WriteableState };

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

let a=Symbol("STATE_ID"),s=null,u=new Set,d=!1,c=0,l=[],i=new Set,o=new WeakMap,f=new WeakMap,S=new WeakMap,r=new WeakMap,v=()=>{if(!d){d=!0;try{for(;0<u.size;){var e,t=u;u=new Set;for(e of t)e()}}finally{d=!1}}},n=e=>{u.delete(e);var t=f.get(e);if(t){for(var a of t)a.delete(e);t.clear(),f.delete(e)}},p=(e,l=Object.is)=>{let i=e,r=new Set,n=Symbol(),t=()=>{var a=s;if(a){r.add(a);let e=f.get(a),t=(e||(e=new Set,f.set(a,e)),e.add(r),o.get(a));t||(t=new Set,o.set(a,t)),t.add(n)}return i};return t.set=e=>{if(!l(i,e)){var t=s;if(t)if(o.get(t)?.has(n)&&!S.get(t))throw new Error("Infinite loop detected: effect() cannot update a state() it depends on!");if(i=e,0!==r.size){for(var a of r)u.add(a);0!==c||d||v()}}},t.update=e=>{t.set(e(i))},t[a]=n,t},g=e=>{let a=()=>{if(!i.has(a)){i.add(a);var t=s;try{if(n(a),s=a,o.set(a,new Set),t){S.set(a,t);let e=r.get(t);e||(e=new Set,r.set(t,e)),e.add(a)}e()}finally{s=t,i.delete(a)}}};if(0===c)a();else{if(s){var t=s;S.set(a,t);let e=r.get(t);e||(e=new Set,r.set(t,e)),e.add(a)}l.push(a)}return()=>{n(a),u.delete(a),i.delete(a),o.delete(a);var e=S.get(a),e=(e&&(e=r.get(e))&&e.delete(a),S.delete(a),r.get(a));if(e){for(var t of e)n(t);e.clear(),r.delete(a)}}};var e=e=>{c++;try{return e()}catch(e){throw 1===c&&(u.clear(),l.length=0),e}finally{if(0===--c){if(0<l.length){var t,e=l;l=[];for(t of e)t()}0<u.size&&!d&&v()}}},t=e=>{let t={cachedValue:void 0,computeFn:e,initialized:!1,valueState:p(void 0)};return g(function(){var e=t.computeFn();t.initialized&&Object.is(t.cachedValue,e)||(t.cachedValue=e,t.valueState.set(e)),t.initialized=!0}),function(){return t.initialized||(t.cachedValue=t.computeFn(),t.initialized=!0,t.valueState.set(t.cachedValue)),t.valueState()}},h=(e,t,a=Object.is)=>{let l={equalityFn:a,initialized:!1,lastSelectedValue:void 0,lastSourceValue:void 0,selectorFn:t,source:e,valueState:p(void 0)};return g(function(){var e=l.source();l.initialized&&Object.is(l.lastSourceValue,e)||(l.lastSourceValue=e,e=l.selectorFn(e),l.initialized&&void 0!==l.lastSelectedValue&&l.equalityFn(l.lastSelectedValue,e))||(l.lastSelectedValue=e,l.valueState.set(e),l.initialized=!0)}),function(){return l.initialized||(l.lastSourceValue=l.source(),l.lastSelectedValue=l.selectorFn(l.lastSourceValue),l.valueState.set(l.lastSelectedValue),l.initialized=!0),l.valueState()}};let y=(e,t,a)=>{e=[...e];return e[t]=a,e},w=(e,t,a)=>{e={...e};return e[t]=a,e},V=e=>"number"==typeof e||!Number.isNaN(Number(e))?[]:{},z=(e,t,a)=>{var l=Number(t[0]);if(1===t.length)return y(e,l,a);var i=[...e],t=t.slice(1),r=t[0];let n=e[l];return null==n&&(n=void 0!==r?V(r):{}),i[l]=m(n,t,a),i},b=(e,t,a)=>{var l=t[0];if(void 0===l)return e;if(1===t.length)return w(e,l,a);var t=t.slice(1),i=t[0];let r=e[l];null==r&&(r=void 0!==i?V(i):{});i={...e};return i[l]=m(r,t,a),i},m=(e,t,a)=>0===t.length?a:null==e?m({},t,a):void 0===t[0]?e:(Array.isArray(e)?z:b)(e,t,a);var F=(e,t)=>{let i={accessor:t,isUpdating:!1,lensState:null,originalSet:null,path:[],source:e};return i.path=(()=>{let a=[],l=new Proxy({},{get:(e,t)=>("string"!=typeof t&&"number"!=typeof t||a.push(t),l)});try{i.accessor(l)}catch{}return a})(),i.lensState=p(i.accessor(i.source())),i.originalSet=i.lensState.set,g(function(){if(!i.isUpdating){i.isUpdating=!0;try{i.lensState.set(i.accessor(i.source()))}finally{i.isUpdating=!1}}}),i.lensState.set=function(t){if(!i.isUpdating){i.isUpdating=!0;try{i.originalSet(t),i.source.update(e=>m(e,i.path,t))}finally{i.isUpdating=!1}}},i.lensState.update=function(e){i.lensState.set(e(i.lensState()))},i.lensState};let U=e=>()=>e();var j=(e,t=Object.is)=>{let a=p(e,t);return[()=>U(a)(),{set:e=>a.set(e),update:e=>a.update(e)}]};export{t as derive,g as effect,F as lens,j as protectedState,U as readonlyState,h as select,p as state,e as batch};
let r=Symbol("STATE_ID"),f=null,u=new Set,s=!1,d=0,a=[],l=new Set,o=new WeakMap,v=new WeakMap,c=new WeakMap,i=new WeakMap,y=(e,t,r)=>{let n=e.get(t);return n||(n=r(),e.set(t,n)),n},p=()=>{if(!s){s=!0;try{for(;0<u.size;){var e,t=u;u=new Set;for(e of t)e()}}finally{s=!1}}},w=e=>{u.delete(e);var t=v.get(e);if(t){for(var r of t)r.delete(e);t.clear(),v.delete(e)}},g=e=>{w(e),l.delete(e),o.delete(e);var t=c.get(e),t=(t&&(t=i.get(t))&&t.delete(e),c.delete(e),i.get(e));if(t){for(var r of t)g(r);t.clear(),i.delete(e)}},h=(e,n=Object.is)=>{let a=e,l=new Set,i=Symbol(),t=()=>{var e=f;return e&&(l.add(e),y(v,e,()=>new Set).add(l),y(o,e,()=>new Set).add(i)),a};return t.set=e=>{if(!n(a,e)){var t=f;if(t)if(o.get(t)?.has(i)&&!c.get(t))throw new Error("Infinite loop detected: effect() cannot update a state() it depends on!");if(a=e,0!==l.size){for(var r of l)u.add(r);0!==d||s||p()}}},t.update=e=>{t.set(e(a))},t[r]=i,t},S=r=>{let n=()=>{if(!l.has(n)){l.add(n);var e=f;try{w(n),f=n;var t=o.get(n);t?t.clear():o.set(n,new Set),e&&(c.set(n,e),y(i,e,()=>new Set).add(n)),r()}finally{f=e,l.delete(n)}}};var e;return 0===d?n():(f&&(e=f,c.set(n,e),y(i,e,()=>new Set).add(n)),a.push(n)),()=>{g(n)}};var e=e=>{d++;try{return e()}catch(e){throw 1===d&&(u.clear(),a.length=0),e}finally{if(0===--d){if(0<a.length){var t,e=a;a=[];for(t of e)t()}0<u.size&&!s&&p()}}},t=t=>{let r=void 0,n=!1,a=h(void 0);return S(function(){var e=t();n&&Object.is(r,e)||(r=e,a.set(e)),n=!0}),function(){return n||(r=t(),n=!0,a.set(r)),a()}},n=(t,r,n=Object.is)=>{let a=!1,l,i,f=h(void 0);return S(function(){var e=t();a&&Object.is(i,e)||(i=e,e=r(e),a&&void 0!==l&&n(l,e))||(l=e,f.set(e),a=!0)}),function(){return a||(i=t(),l=r(i),f.set(l),a=!0),f()}};let b=(e,t,r)=>{e=[...e];return e[t]=r,e},m=(e,t,r)=>{e={...e};return e[t]=r,e},j=e=>"number"==typeof e||!Number.isNaN(Number(e))?[]:{},N=(n,a,l,i)=>{if(l>=a.length)return i;if(null==n)return N({},a,l,i);var f=a[l];if(void 0===f)return n;if(Array.isArray(n)){var u=Number(f);if(l===a.length-1)return b(n,u,i);var s=[...n];let e=l+1,t=a[e],r=n[u];return null==r&&(r=void 0===t?{}:j(t)),s[u]=N(r,a,e,i),s}u=n;if(l===a.length-1)return m(u,f,i);let e=l+1,t=a[e],r=u[f];null==r&&(r=void 0===t?{}:j(t));s={...u};return s[f]=N(r,a,e,i),s};var O=(e,t)=>{let r=!1;let n=(()=>{let r=[],n=new Proxy({},{get:(e,t)=>("string"!=typeof t&&"number"!=typeof t||r.push(t),n)});try{t(n)}catch{}return r})(),a=h(t(e())),l=a.set;return S(function(){if(!r){r=!0;try{a.set(t(e()))}finally{r=!1}}}),a.set=function(t){if(!r){r=!0;try{l(t),e.update(e=>N(e,n,0,t))}finally{r=!1}}},a.update=function(e){a.set(e(a()))},a};let k=e=>()=>e();var M=(e,t=Object.is)=>{let r=h(e,t);return[k(r),{set:e=>r.set(e),update:e=>r.update(e)}]};export{t as derive,S as effect,O as lens,M as protectedState,k as readonlyState,n as select,h as state,e as batch};

@@ -16,11 +16,11 @@ {

".": {
"types": "./dist/src/index.d.ts",
"typescript": "./src/index.ts",
"import": {
"default": "./dist/src/index.min.js",
"types": "./dist/src/index.d.ts"
"types": "./dist/src/index.d.ts",
"default": "./dist/src/index.min.js"
},
"require": {
"default": "./dist/src/index.min.js"
},
"types": "./dist/src/index.d.ts",
"typescript": "./src/index.ts"
}
}

@@ -60,3 +60,3 @@ },

"scripts": {
"benchmark": "node --expose-gc scripts/benchmark.ts",
"benchmark": "node --expose-gc scripts/benchmark.ts -R 3",
"benchmark:naiv": "node scripts/naiv-benchmark.ts",

@@ -99,3 +99,3 @@ "build": "npm run build:lts",

"types": "dist/src/index.d.ts",
"version": "1000.3.0"
"version": "1000.3.1"
}

@@ -40,3 +40,3 @@ # Beacon <img align="right" src="https://raw.githubusercontent.com/nerdalytics/beacon/refs/heads/trunk/assets/beacon-logo-v2.svg" width="128px" alt="A stylized lighthouse beacon with golden light against a dark blue background, representing the reactive state library"/>

Full documentation, API reference, and examples available at:
**[github.com/nerdalytics/beacon](https://github.com/nerdalytics/beacon)**
**[nerdalytics.github.io/beacon](https://nerdalytics.github.io/beacon/)**

@@ -43,0 +43,0 @@ ## License

+132
-197

@@ -33,2 +33,11 @@ // Core types for reactive primitives

const getOrCreate = <K extends object, V>(map: WeakMap<K, V>, key: K, factory: () => V): V => {
let value = map.get(key)
if (!value) {
value = factory()
map.set(key, value)
}
return value
}
const notifySubscribers = (): void => {

@@ -68,5 +77,26 @@ if (isNotifying) {

/**
* Creates a reactive state container with the provided initial value.
*/
const disposeEffect = (effect: Subscriber): void => {
cleanupEffect(effect)
activeSubscribers.delete(effect)
stateTracking.delete(effect)
const parent = parentSubscriber.get(effect)
if (parent) {
const siblings = childSubscribers.get(parent)
if (siblings) {
siblings.delete(effect)
}
}
parentSubscriber.delete(effect)
const children = childSubscribers.get(effect)
if (children) {
for (const child of children) {
disposeEffect(child)
}
children.clear()
childSubscribers.delete(effect)
}
}
const createState = <T>(initialValue: T, equalityFn: (a: T, b: T) => boolean = Object.is): State<T> => {

@@ -82,15 +112,5 @@ let value = initialValue

let dependencies = subscriberDependencies.get(currentEffect)
if (!dependencies) {
dependencies = new Set()
subscriberDependencies.set(currentEffect, dependencies)
}
dependencies.add(subscribers)
getOrCreate(subscriberDependencies, currentEffect, () => new Set()).add(subscribers)
let readStates = stateTracking.get(currentEffect)
if (!readStates) {
readStates = new Set()
stateTracking.set(currentEffect, readStates)
}
readStates.add(stateId)
getOrCreate(stateTracking, currentEffect, () => new Set()).add(stateId)
}

@@ -136,5 +156,2 @@ return value

/**
* Registers a function to run whenever its reactive dependencies change.
*/
const createEffect = (fn: () => void): Unsubscribe => {

@@ -153,12 +170,12 @@ const runEffect = (): void => {

currentSubscriber = runEffect
stateTracking.set(runEffect, new Set())
const existingStates = stateTracking.get(runEffect)
if (existingStates) {
existingStates.clear()
} else {
stateTracking.set(runEffect, new Set())
}
if (parentEffect) {
parentSubscriber.set(runEffect, parentEffect)
let children = childSubscribers.get(parentEffect)
if (!children) {
children = new Set()
childSubscribers.set(parentEffect, children)
}
children.add(runEffect)
getOrCreate(childSubscribers, parentEffect, () => new Set()).add(runEffect)
}

@@ -179,8 +196,3 @@

parentSubscriber.set(runEffect, parent)
let children = childSubscribers.get(parent)
if (!children) {
children = new Set()
childSubscribers.set(parent, children)
}
children.add(runEffect)
getOrCreate(childSubscribers, parent, () => new Set()).add(runEffect)
}

@@ -192,30 +204,6 @@

return (): void => {
cleanupEffect(runEffect)
pendingSubscribers.delete(runEffect)
activeSubscribers.delete(runEffect)
stateTracking.delete(runEffect)
const parent = parentSubscriber.get(runEffect)
if (parent) {
const siblings = childSubscribers.get(parent)
if (siblings) {
siblings.delete(runEffect)
}
}
parentSubscriber.delete(runEffect)
const children = childSubscribers.get(runEffect)
if (children) {
for (const child of children) {
cleanupEffect(child)
}
children.clear()
childSubscribers.delete(runEffect)
}
disposeEffect(runEffect)
}
}
/**
* Groups multiple state updates to trigger effects only once at the end.
*/
const executeBatch = <T>(fn: () => T): T => {

@@ -250,37 +238,28 @@ batchDepth++

/**
* Creates a read-only computed value that updates when its dependencies change.
*/
const createDerive = <T>(computeFn: () => T): ReadOnlyState<T> => {
const container = {
cachedValue: undefined as unknown as T,
computeFn,
initialized: false,
valueState: createState<T | undefined>(undefined),
}
let cachedValue: T = undefined as unknown as T
let initialized = false
const valueState = createState<T | undefined>(undefined)
createEffect(function deriveEffect(): void {
const newValue = container.computeFn()
const newValue = computeFn()
if (!(container.initialized && Object.is(container.cachedValue, newValue))) {
container.cachedValue = newValue
container.valueState.set(newValue)
if (!(initialized && Object.is(cachedValue, newValue))) {
cachedValue = newValue
valueState.set(newValue)
}
container.initialized = true
initialized = true
})
return function deriveGetter(): T {
if (!container.initialized) {
container.cachedValue = container.computeFn()
container.initialized = true
container.valueState.set(container.cachedValue)
if (!initialized) {
cachedValue = computeFn()
initialized = true
valueState.set(cachedValue)
}
return container.valueState() as T
return valueState() as T
}
}
/**
* Creates an efficient subscription to a subset of a state value.
*/
const createSelect = <T, R>(

@@ -291,43 +270,34 @@ source: ReadOnlyState<T>,

): ReadOnlyState<R> => {
const container = {
equalityFn,
initialized: false,
lastSelectedValue: undefined as R | undefined,
lastSourceValue: undefined as T | undefined,
selectorFn,
source,
valueState: createState<R | undefined>(undefined),
}
let initialized = false
let lastSelectedValue: R | undefined
let lastSourceValue: T | undefined
const valueState = createState<R | undefined>(undefined)
createEffect(function selectEffect(): void {
const sourceValue = container.source()
const sourceValue = source()
if (container.initialized && Object.is(container.lastSourceValue, sourceValue)) {
if (initialized && Object.is(lastSourceValue, sourceValue)) {
return
}
container.lastSourceValue = sourceValue
const newSelectedValue = container.selectorFn(sourceValue)
lastSourceValue = sourceValue
const newSelectedValue = selectorFn(sourceValue)
if (
container.initialized &&
container.lastSelectedValue !== undefined &&
container.equalityFn(container.lastSelectedValue, newSelectedValue)
) {
if (initialized && lastSelectedValue !== undefined && equalityFn(lastSelectedValue, newSelectedValue)) {
return
}
container.lastSelectedValue = newSelectedValue
container.valueState.set(newSelectedValue)
container.initialized = true
lastSelectedValue = newSelectedValue
valueState.set(newSelectedValue)
initialized = true
})
return function selectGetter(): R {
if (!container.initialized) {
container.lastSourceValue = container.source()
container.lastSelectedValue = container.selectorFn(container.lastSourceValue)
container.valueState.set(container.lastSelectedValue)
container.initialized = true
if (!initialized) {
lastSourceValue = source()
lastSelectedValue = selectorFn(lastSourceValue)
valueState.set(lastSelectedValue)
initialized = true
}
return container.valueState() as R
return valueState() as R
}

@@ -364,32 +334,12 @@ }

// Helper for handling array path updates
const updateArrayPath = <V>(array: unknown[], pathSegments: (string | number)[], value: V): unknown[] => {
const index = Number(pathSegments[0])
if (pathSegments.length === 1) {
return updateArrayItem(array, index, value)
const setValueAtPath = <V, O>(obj: O, pathSegments: (string | number)[], depth: number, value: V): O => {
if (depth >= pathSegments.length) {
return value as unknown as O
}
const copy = [
...array,
]
const nextPathSegments = pathSegments.slice(1)
const nextKey = nextPathSegments[0]
let nextValue = array[index]
if (nextValue === undefined || nextValue === null) {
nextValue = nextKey !== undefined ? createContainer(nextKey) : {}
if (obj === undefined || obj === null) {
return setValueAtPath({} as O, pathSegments, depth, value)
}
copy[index] = setValueAtPath(nextValue, nextPathSegments, value)
return copy
}
// Helper for handling object path updates
const updateObjectPath = <V>(
obj: Record<string | number, unknown>,
pathSegments: (string | number)[],
value: V
): Record<string | number, unknown> => {
const currentKey = pathSegments[0]
const currentKey = pathSegments[depth]
if (currentKey === undefined) {

@@ -399,54 +349,47 @@ return obj

if (pathSegments.length === 1) {
return updateShallowProperty(obj, currentKey, value)
}
if (Array.isArray(obj)) {
const index = Number(currentKey)
const nextPathSegments = pathSegments.slice(1)
const nextKey = nextPathSegments[0]
if (depth === pathSegments.length - 1) {
return updateArrayItem(obj, index, value) as unknown as O
}
let currentValue = obj[currentKey]
if (currentValue === undefined || currentValue === null) {
currentValue = nextKey !== undefined ? createContainer(nextKey) : {}
}
const copy = [
...obj,
]
const nextDepth = depth + 1
const nextKey = pathSegments[nextDepth]
const result = {
...obj,
}
result[currentKey] = setValueAtPath(currentValue, nextPathSegments, value)
return result
}
let nextValue = obj[index]
if (nextValue === undefined || nextValue === null) {
nextValue = nextKey === undefined ? {} : createContainer(nextKey)
}
const setValueAtPath = <V, O>(obj: O, pathSegments: (string | number)[], value: V): O => {
if (pathSegments.length === 0) {
return value as unknown as O
copy[index] = setValueAtPath(nextValue, pathSegments, nextDepth, value)
return copy as unknown as O
}
if (obj === undefined || obj === null) {
return setValueAtPath({} as O, pathSegments, value)
const record = obj as Record<string | number, unknown>
if (depth === pathSegments.length - 1) {
return updateShallowProperty(record, currentKey, value) as unknown as O
}
const currentKey = pathSegments[0]
if (currentKey === undefined) {
return obj
const nextDepth = depth + 1
const nextKey = pathSegments[nextDepth]
let currentValue = record[currentKey]
if (currentValue === undefined || currentValue === null) {
currentValue = nextKey === undefined ? {} : createContainer(nextKey)
}
if (Array.isArray(obj)) {
return updateArrayPath(obj, pathSegments, value) as unknown as O
const result = {
...record,
}
return updateObjectPath(obj as Record<string | number, unknown>, pathSegments, value) as unknown as O
result[currentKey] = setValueAtPath(currentValue, pathSegments, nextDepth, value)
return result as unknown as O
}
/**
* Creates a lens for direct updates to nested properties of a state.
*/
const createLens = <T, K>(source: State<T>, accessor: (state: T) => K): State<K> => {
const container = {
accessor,
isUpdating: false,
lensState: null as unknown as State<K>,
originalSet: null as unknown as (value: K) => void,
path: [] as (string | number)[],
source,
}
let isUpdating = false

@@ -468,3 +411,3 @@ const extractPath = (): (string | number)[] => {

try {
container.accessor(proxy as unknown as T)
accessor(proxy as unknown as T)
} catch {

@@ -477,45 +420,40 @@ // Ignore errors, we're just collecting the path

container.path = extractPath()
const path = extractPath()
const lensState = createState<K>(accessor(source()))
const originalSet = lensState.set
container.lensState = createState<K>(container.accessor(container.source()))
container.originalSet = container.lensState.set
createEffect(function lensEffect(): void {
if (container.isUpdating) {
if (isUpdating) {
return
}
container.isUpdating = true
isUpdating = true
try {
container.lensState.set(container.accessor(container.source()))
lensState.set(accessor(source()))
} finally {
container.isUpdating = false
isUpdating = false
}
})
container.lensState.set = function lensSet(value: K): void {
if (container.isUpdating) {
lensState.set = function lensSet(value: K): void {
if (isUpdating) {
return
}
container.isUpdating = true
isUpdating = true
try {
container.originalSet(value)
container.source.update((current: T): T => setValueAtPath(current, container.path, value))
originalSet(value)
source.update((current: T): T => setValueAtPath(current, path, 0, value))
} finally {
container.isUpdating = false
isUpdating = false
}
}
container.lensState.update = function lensUpdate(fn: (value: K) => K): void {
container.lensState.set(fn(container.lensState()))
lensState.update = function lensUpdate(fn: (value: K) => K): void {
lensState.set(fn(lensState()))
}
return container.lensState
return lensState
}
/**
* Creates a read-only view of a state, hiding mutation methods.
*/
const createReadonlyState =

@@ -526,5 +464,2 @@ <T>(source: State<T>): ReadOnlyState<T> =>

/**
* Creates a state with access control, returning a tuple of reader and writer.
*/
const createProtectedState = <T>(

@@ -538,4 +473,5 @@ initialValue: T,

const fullState = createState(initialValue, equalityFn)
const reader = createReadonlyState(fullState)
return [
(): T => createReadonlyState(fullState)(),
reader,
{

@@ -548,2 +484,3 @@ set: (value: T): void => fullState.set(value),

export type { ReadOnlyState, State, Unsubscribe, WriteableState }
export {

@@ -559,3 +496,1 @@ createDerive as derive,

}
export type { ReadOnlyState, State, Unsubscribe, WriteableState }