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.2
to
1000.3.3
+1
-4
dist/src/index.d.ts

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

}
declare const STATE_ID: unique symbol;
type State<T> = ReadOnlyState<T> & WriteableState<T> & {
[STATE_ID]?: symbol;
};
type State<T> = ReadOnlyState<T> & WriteableState<T>;
declare const createState: <T>(initialValue: T, equalityFn?: (a: T, b: T) => boolean) => State<T>;

@@ -13,0 +10,0 @@ declare const createEffect: (fn: () => void) => Unsubscribe;

+1
-1

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

let r=Symbol("STATE_ID"),f=null,o=new Set,s=!1,u=0,a=[],l=new Set,d=new WeakMap,c=new WeakMap,v=new WeakMap,i=new WeakMap,p=new Set(["__proto__","constructor","prototype"]),y=(e,t,r)=>{let n=e.get(t);return n||(n=r(),e.set(t,n)),n},w=()=>{if(!s){s=!0;try{for(;0<o.size;){var e,t=o;o=new Set;for(e of t)e()}}finally{s=!1}}},g=e=>{o.delete(e);var t=c.get(e);if(t){for(var r of t)r.delete(e);t.clear(),c.delete(e)}},h=e=>{g(e),l.delete(e),d.delete(e);var t=v.get(e),t=(t&&(t=i.get(t))&&t.delete(e),v.delete(e),i.get(e));if(t){for(var r of t)h(r);t.clear(),i.delete(e)}},S=(e,n=Object.is)=>{let a=e,l=new Set,i=Symbol(),t=()=>{var e=f;return e&&(l.add(e),y(c,e,()=>new Set).add(l),y(d,e,()=>new Set).add(i)),a};return t.set=e=>{if(!n(a,e)){var t=f;if(t)if(d.get(t)?.has(i)&&!v.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)o.add(r);0!==u||s||w()}}},t.update=e=>{t.set(e(a))},t[r]=i,t},b=r=>{let n=()=>{if(!l.has(n)){l.add(n);var e=f;try{g(n),f=n;var t=d.get(n);t?t.clear():d.set(n,new Set),e&&(v.set(n,e),y(i,e,()=>new Set).add(n)),r()}finally{f=e,l.delete(n)}}};var e;return 0===u?n():(f&&(e=f,v.set(n,e),y(i,e,()=>new Set).add(n)),a.push(n)),()=>{h(n)}};var e=e=>{u++;try{return e()}catch(e){throw 1===u&&(o.clear(),a.length=0),e}finally{if(0===--u){if(0<a.length){var t,e=a;a=[];for(t of e)t()}0<o.size&&!s&&w()}}},t=t=>{let r=void 0,n=!1,a=S(void 0);return b(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=S(void 0);return b(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 m=(e,t,r)=>{e=[...e];return e[t]=r,e},j=(e,t,r)=>{e={...e};return e[t]=r,e},N=e=>"number"==typeof e||!Number.isNaN(Number(e))?[]:{},O=(n,a,l,i)=>{if(l>=a.length)return i;if(null==n)return O({},a,l,i);var f=a[l];if(void 0===f)return n;if(Array.isArray(n)){var o=Number(f);if(l===a.length-1)return m(n,o,i);var s=[...n];let e=l+1,t=a[e],r=n[o];return null==r&&(r=void 0===t?{}:N(t)),s[o]=O(r,a,e,i),s}o=n;if(l===a.length-1)return j(o,f,i);let e=l+1,t=a[e],r=o[f];null==r&&(r=void 0===t?{}:N(t));s={...o};return s[f]=O(r,a,e,i),s};var _=(e,t)=>{let r=!1;let n=(()=>{let r=[],n=!1,a=new Proxy({},{get:(e,t)=>(n||"string"!=typeof t&&"number"!=typeof t||(p.has(String(t))?n=!0:r.push(t)),a)});try{t(a)}catch{}return n?[]:r})(),a=S(t(e())),l=a.set;return b(function(){if(!r){r=!0;try{a.set(t(e()))}finally{r=!1}}}),a.set=function(t){if(!r&&0!==n.length){r=!0;try{l(t),e.update(e=>O(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=S(e,t);return[k(r),{set:e=>r.set(e),update:e=>r.update(e)}]};export{t as derive,b as effect,_ as lens,M as protectedState,k as readonlyState,n as select,S as state,e as batch};
let o=null,r=new Set,a=new Set,s=a,u=!1,c=0,n=[],f=new Set,i=new WeakMap,v=new WeakMap,d=new WeakMap,l=new WeakMap,w=new Set(["__proto__","constructor","prototype"]),p=(e,t,r)=>{let a=e.get(t);return a||(a=r(),e.set(t,a)),a},y=()=>{if(!u){u=!0;try{for(;0<s.size;){var e,t=s;s=t===a?r:a;for(e of t)e();t.clear()}}finally{u=!1}}},S=e=>{s.delete(e);var t=v.get(e);if(t){for(var r of t)r.delete(e);t.clear(),v.delete(e)}},g=e=>{S(e),f.delete(e),i.delete(e);var t=d.get(e),t=(t&&(t=l.get(t))&&t.delete(e),d.delete(e),l.get(e));if(t){for(var r of t)g(r);t.clear(),l.delete(e)}},h=(e,a=Object.is)=>{let n=e,f=new Set,l=Symbol(),t=()=>{var e=o;return e&&(f.add(e),p(v,e,()=>new Set).add(f),p(i,e,()=>new Set).add(l)),n};return t.set=e=>{if(!a(n,e)){var t=o;if(t)if(i.get(t)?.has(l)&&!d.get(t))throw new Error("Infinite loop detected: effect() cannot update a state() it depends on!");if(n=e,0!==f.size){for(var r of f)s.add(r);0!==c||u||y()}}},t.update=e=>{t.set(e(n))},t},b=r=>{let a=()=>{if(!f.has(a)){f.add(a);var e=o;try{S(a),o=a;var t=i.get(a);t?t.clear():i.set(a,new Set),e&&(d.set(a,e),p(l,e,()=>new Set).add(a)),r()}finally{o=e,f.delete(a)}}};var e;return 0===c?a():(o&&(e=o,d.set(a,e),p(l,e,()=>new Set).add(a)),n.push(a)),()=>{g(a)}};var e=e=>{c++;try{return e()}catch(e){throw 1===c&&(s.clear(),n.length=0),e}finally{if(0===--c){if(0<n.length){var t,e=n;n=[];for(t of e)t()}0<s.size&&!u&&y()}}},t=r=>{let a=void 0,n=!1,f=new Set;return b(function(){var e=r();if(!n||!Object.is(a,e)){a=e;for(var t of f)s.add(t);0!==c||u||y()}n=!0}),function(){var e=o;return e&&(f.add(e),p(v,e,()=>new Set).add(f)),n||(a=r(),n=!0),a}},j=(r,a,n=Object.is)=>{let f=!1,l,i,d=new Set;return b(function(){var e=r();if(!f||!Object.is(i,e)){i=e;e=a(e);if(!f||void 0===l||!n(l,e)){l=e,f=!0;for(var t of d)s.add(t);0!==c||u||y()}}}),function(){var e=o;return e&&(d.add(e),p(v,e,()=>new Set).add(d)),f||(i=r(),l=a(i),f=!0),l}};let N=(e,t)=>null!=e?e:void 0===t||Number.isNaN(Number(t))?{}:[],O=(t,e,r,a)=>{if(r>=e.length)return a;if(null==t)return O({},e,r,a);var n=e[r];if(void 0===n)return t;var f=Array.isArray(t),n=f?Number(n):n;if(r===e.length-1){if(f)return(l=[...t])[n]=a,l;let e={...t};return e[n]=a,e}var l=r+1,r=e[l],i=t[n],i=N(i,r);if(f)return(r=[...t])[n]=O(i,e,l,a),r;let d={...t};return d[n]=O(i,e,l,a),d};var k=(e,t)=>{let r=!1;let a=(()=>{let r=[],a=!1,n=new Proxy({},{get:(e,t)=>(a||"string"!=typeof t||(w.has(String(t))?a=!0:r.push(t)),n)});try{t(n)}catch{}return a?[]:r})(),n=h(t(e())),f=n.set;return b(function(){if(!r){r=!0;try{n.set(t(e()))}finally{r=!1}}}),n.set=function(t){if(!r&&0!==a.length){r=!0;try{f(t),e.update(e=>O(e,a,0,t))}finally{r=!1}}},n.update=function(e){n.set(e(n()))},n};let m=e=>()=>e();var M=(e,t=Object.is)=>{let r=h(e,t);return[m(r),{set:e=>r.set(e),update:e=>r.update(e)}]};export{t as derive,b as effect,k as lens,M as protectedState,m as readonlyState,j as select,h as state,e as batch};

@@ -5,6 +5,6 @@ {

"devDependencies": {
"@biomejs/biome": "2.3.14",
"@types/node": "25.2.2",
"npm-check-updates": "19.3.2",
"typescript": "5.9.3",
"@biomejs/biome": "2.4.11",
"@types/node": "25.5.2",
"npm-check-updates": "20.0.0",
"typescript": "6.0.2",
"uglify-js": "3.19.3"

@@ -36,16 +36,9 @@ },

"backend",
"batching",
"computed-values",
"dependency-tracking",
"effects",
"fine-grained",
"lightweight",
"memory-management",
"batch",
"dependency-graph",
"effect",
"nodejs",
"performance",
"reactive",
"server-side",
"signals",
"state-management",
"typescript"
"state"
],

@@ -55,3 +48,3 @@ "license": "MIT",

"name": "@nerdalytics/beacon",
"packageManager": "npm@11.9.0",
"packageManager": "npm@11.12.1",
"repository": {

@@ -63,3 +56,3 @@ "type": "git",

"benchmark": "node --expose-gc scripts/benchmark.ts -R 3",
"benchmark:naiv": "node scripts/naiv-benchmark.ts",
"build": "npm run build:lts",

@@ -78,21 +71,6 @@ "build:lts": "tsc -p tsconfig.lts.json",

"test": "node --test --test-skip-pattern=\"COMPONENT NAME\" tests/**/*.ts",
"test:behavior": "node --test tests/infinite-loop.test.ts tests/cyclic-dependency.test.ts tests/cleanup.test.ts",
"test:core": "node --test tests/*-core.test.ts",
"test:coverage": "node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info tests/**/*.test.ts",
"test:integration": "node --test tests/state-*.test.ts tests/batch-integration.test.ts",
"test:lts:20": "node --test dist/tests/**.js",
"test:lts:22": "node --test --test-skip-pattern=\"COMPONENT NAME\" dist/tests/**/*.js",
"test:unit:batch": "node --test tests/batch.test.ts",
"test:unit:cleanup": "node --test tests/cleanup.test.ts",
"test:unit:custom-equality": "node --test tests/custom-equality.test.ts",
"test:unit:cyclic-dependency": "node --test tests/cyclic-dependency.test.ts",
"test:unit:deep-chain": "node --test tests/deep-chain.test.ts",
"test:unit:derive": "node --test tests/derive.test.ts",
"test:unit:effect": "node --test tests/effect.test.ts",
"test:unit:infinite-loop": "node --test tests/infinite-loop.test.ts",
"test:unit:lens": "node --test tests/lens.test.ts",
"test:unit:select": "node --test tests/select.test.ts",
"test:unit:state": "node --test tests/state.test.ts",
"update-dependencies": "npx npm-check-updates --interactive --upgrade --removeRange",
"update-performance-docs": "node --experimental-config-file=node.config.json scripts/update-performance-docs.ts"
"update-dependencies": "npx npm-check-updates --interactive --upgrade --removeRange"
},

@@ -102,3 +80,3 @@ "sideEffects": false,

"types": "dist/src/index.d.ts",
"version": "1000.3.2"
"version": "1000.3.3"
}

@@ -7,3 +7,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"/>

[![registry:npm:version](https://img.shields.io/npm/v/@nerdalytics/beacon.svg)](https://www.npmjs.com/package/@nerdalytics/beacon)
[![Socket Badge](https://badge.socket.dev/npm/package/@nerdalytics/beacon/1000.3.0)](https://socket.dev/npm/package/@nerdalytics/beacon/overview/1000.3.0)
[![Socket Badge](https://badge.socket.dev/npm/package/@nerdalytics/beacon/1000.3.3)](https://socket.dev/npm/package/@nerdalytics/beacon/overview/1000.3.3)

@@ -10,0 +10,0 @@ [![tech:nodejs](https://img.shields.io/badge/Node%20js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)](https://nodejs.org/)

@@ -10,13 +10,9 @@ // Core types for reactive primitives

// Special symbol used for internal tracking
const STATE_ID: unique symbol = Symbol('STATE_ID')
type State<T> = ReadOnlyState<T> & WriteableState<T>
type State<T> = ReadOnlyState<T> &
WriteableState<T> & {
[STATE_ID]?: symbol
}
// Module-level reactive state
let currentSubscriber: Subscriber | null = null
let pendingSubscribers: Set<Subscriber> = new Set<Subscriber>()
const flushing: Set<Subscriber> = new Set<Subscriber>()
const queued: Set<Subscriber> = new Set<Subscriber>()
let pendingSubscribers: Set<Subscriber> = queued
let isNotifying = false

@@ -58,3 +54,3 @@ let batchDepth = 0

const subscribers = pendingSubscribers
pendingSubscribers = new Set()
pendingSubscribers = subscribers === queued ? flushing : queued

@@ -64,2 +60,3 @@ for (const effect of subscribers) {

}
subscribers.clear()
}

@@ -157,3 +154,2 @@ } finally {

get[STATE_ID] = stateId
return get as State<T>

@@ -243,3 +239,3 @@ }

let initialized = false
const valueState = createState<T | undefined>(undefined)
const subscribers = new Set<Subscriber>()

@@ -251,3 +247,9 @@ createEffect(function deriveEffect(): void {

cachedValue = newValue
valueState.set(newValue)
for (const sub of subscribers) {
pendingSubscribers.add(sub)
}
if (batchDepth === 0 && !isNotifying) {
notifySubscribers()
}
}

@@ -259,8 +261,13 @@

return function deriveGetter(): T {
const currentEffect = currentSubscriber
if (currentEffect) {
subscribers.add(currentEffect)
getOrCreate(subscriberDependencies, currentEffect, () => new Set()).add(subscribers)
}
if (!initialized) {
cachedValue = computeFn()
initialized = true
valueState.set(cachedValue)
}
return valueState() as T
return cachedValue
}

@@ -277,3 +284,3 @@ }

let lastSourceValue: T | undefined
const valueState = createState<R | undefined>(undefined)
const subscribers = new Set<Subscriber>()

@@ -295,46 +302,36 @@ createEffect(function selectEffect(): void {

lastSelectedValue = newSelectedValue
valueState.set(newSelectedValue)
initialized = true
for (const sub of subscribers) {
pendingSubscribers.add(sub)
}
if (batchDepth === 0 && !isNotifying) {
notifySubscribers()
}
})
return function selectGetter(): R {
const currentEffect = currentSubscriber
if (currentEffect) {
subscribers.add(currentEffect)
getOrCreate(subscriberDependencies, currentEffect, () => new Set()).add(subscribers)
}
if (!initialized) {
lastSourceValue = source()
lastSelectedValue = selectorFn(lastSourceValue)
valueState.set(lastSelectedValue)
initialized = true
}
return valueState() as R
return lastSelectedValue as R
}
}
// Helper for array updates
const updateArrayItem = <V>(arr: unknown[], index: number, value: V): unknown[] => {
const copy = [
...arr,
]
copy[index] = value
return copy
// Returns the value if non-nullish, otherwise creates the appropriate container type
const ensureContainer = (value: unknown, nextKey: string | undefined): unknown => {
if (value != null) return value
if (nextKey !== undefined && !Number.isNaN(Number(nextKey))) return []
return {}
}
// Helper for single-level updates (optimization)
const updateShallowProperty = <V>(
obj: Record<string | number, unknown>,
key: string | number,
value: V
): Record<string | number, unknown> => {
const result = {
...obj,
}
result[key] = value
return result
}
// Helper to create the appropriate container type
const createContainer = (key: string | number): Record<string | number, unknown> | unknown[] => {
const isArrayKey = typeof key === 'number' || !Number.isNaN(Number(key))
return isArrayKey ? [] : {}
}
const setValueAtPath = <V, O>(obj: O, pathSegments: (string | number)[], depth: number, value: V): O => {
const setValueAtPath = <V, O>(obj: O, pathSegments: string[], depth: number, value: V): O => {
if (depth >= pathSegments.length) {

@@ -344,3 +341,3 @@ return value as unknown as O

if (obj === undefined || obj === null) {
if (obj == null) {
return setValueAtPath({} as O, pathSegments, depth, value)

@@ -354,42 +351,38 @@ }

if (Array.isArray(obj)) {
const index = Number(currentKey)
const isArray = Array.isArray(obj)
const key = isArray ? Number(currentKey) : currentKey
if (depth === pathSegments.length - 1) {
return updateArrayItem(obj, index, value) as unknown as O
if (depth === pathSegments.length - 1) {
if (isArray) {
const copy = [
...(obj as unknown[]),
]
copy[key as number] = value
return copy as unknown as O
}
const copy = [
...obj,
]
const nextDepth = depth + 1
const nextKey = pathSegments[nextDepth]
let nextValue = obj[index]
if (nextValue === undefined || nextValue === null) {
nextValue = nextKey === undefined ? {} : createContainer(nextKey)
const result = {
...(obj as Record<string, unknown>),
}
copy[index] = setValueAtPath(nextValue, pathSegments, nextDepth, value)
return copy as unknown as O
result[key] = value
return result as unknown as O
}
const record = obj as Record<string | number, unknown>
if (depth === pathSegments.length - 1) {
return updateShallowProperty(record, currentKey, value) as unknown as O
}
const nextDepth = depth + 1
const nextKey = pathSegments[nextDepth]
const source = isArray ? (obj as unknown[])[key as number] : (obj as Record<string | number, unknown>)[key]
let currentValue = record[currentKey]
if (currentValue === undefined || currentValue === null) {
currentValue = nextKey === undefined ? {} : createContainer(nextKey)
const nextValue = ensureContainer(source, nextKey)
if (isArray) {
const copy = [
...(obj as unknown[]),
]
copy[key as number] = setValueAtPath(nextValue, pathSegments, nextDepth, value)
return copy as unknown as O
}
const result = {
...record,
...(obj as Record<string | number, unknown>),
}
result[currentKey] = setValueAtPath(currentValue, pathSegments, nextDepth, value)
result[key] = setValueAtPath(nextValue, pathSegments, nextDepth, value)
return result as unknown as O

@@ -401,4 +394,4 @@ }

const extractPath = (): (string | number)[] => {
const pathCollector: (string | number)[] = []
const extractPath = (): string[] => {
const pathCollector: string[] = []
let tainted = false

@@ -409,3 +402,3 @@ const proxy = new Proxy(

get: (_: object, prop: string | symbol): unknown => {
if (!tainted && (typeof prop === 'string' || typeof prop === 'number')) {
if (!tainted && typeof prop === 'string') {
if (DANGEROUS_KEYS.has(String(prop))) {

@@ -412,0 +405,0 @@ tainted = true