@nerdalytics/beacon 1000.3.1 → 1000.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/src/index.min.js +1 -1
- package/package.json +2 -2
- package/src/index.ts +14 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 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"/>
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Reactive dependency graph runtime for Node.js backends. Tracks dependencies between signals and propagates updates automatically.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/nerdalytics/beacon/blob/trunk/LICENSE)
|
|
6
6
|
[](https://www.npmjs.com/package/@nerdalytics/beacon)
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
[](https://typescriptlang.org/)
|
|
11
11
|
[](https://biomejs.dev/)
|
|
12
12
|
|
|
13
|
-
A lightweight reactive state library for Node.js backends. Enables reactive state management with automatic dependency tracking and efficient updates for server-side applications.
|
|
14
|
-
|
|
15
13
|
## Installation
|
|
16
14
|
|
|
17
15
|
```
|
|
@@ -39,6 +37,16 @@ count.set(5);
|
|
|
39
37
|
Full documentation, API reference, and examples available at:
|
|
40
38
|
**[nerdalytics.github.io/beacon](https://nerdalytics.github.io/beacon/)**
|
|
41
39
|
|
|
40
|
+
### LLM-friendly docs
|
|
41
|
+
|
|
42
|
+
The handbook has plain-text endpoints for LLMs:
|
|
43
|
+
|
|
44
|
+
- [`llms.txt`](https://nerdalytics.github.io/beacon/llms.txt) lists available versions
|
|
45
|
+
- [`<version>/llms.txt`](https://nerdalytics.github.io/beacon/latest/llms.txt) lists pages for a version
|
|
46
|
+
- [`<version>/llms-full.txt`](https://nerdalytics.github.io/beacon/latest/llms-full.txt) concatenates every page into one file
|
|
47
|
+
|
|
48
|
+
You can also append `.md` to any handbook page URL for its Markdown source (e.g. [`<version>/introduction.md`](https://nerdalytics.github.io/beacon/latest/introduction.md)).
|
|
49
|
+
|
|
42
50
|
## License
|
|
43
51
|
|
|
44
52
|
MIT - See [LICENSE](./LICENSE) for details.
|
package/dist/src/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let r=Symbol("STATE_ID"),f=null,
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Denny Trebbin (nerdalytics)",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "Reactive dependency graph runtime for Node.js backends. Tracks dependencies between signals and propagates updates automatically.",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@biomejs/biome": "2.3.14",
|
|
6
6
|
"@types/node": "25.2.2",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"sideEffects": false,
|
|
95
95
|
"type": "module",
|
|
96
96
|
"types": "dist/src/index.d.ts",
|
|
97
|
-
"version": "1000.3.
|
|
97
|
+
"version": "1000.3.2"
|
|
98
98
|
}
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,11 @@ const subscriberDependencies: WeakMap<Subscriber, Set<Set<Subscriber>>> = new We
|
|
|
29
29
|
>()
|
|
30
30
|
const parentSubscriber: WeakMap<Subscriber, Subscriber> = new WeakMap<Subscriber, Subscriber>()
|
|
31
31
|
const childSubscribers: WeakMap<Subscriber, Set<Subscriber>> = new WeakMap<Subscriber, Set<Subscriber>>()
|
|
32
|
+
const DANGEROUS_KEYS: ReadonlySet<string> = new Set([
|
|
33
|
+
'__proto__',
|
|
34
|
+
'constructor',
|
|
35
|
+
'prototype',
|
|
36
|
+
])
|
|
32
37
|
|
|
33
38
|
const getOrCreate = <K extends object, V>(map: WeakMap<K, V>, key: K, factory: () => V): V => {
|
|
34
39
|
let value = map.get(key)
|
|
@@ -384,12 +389,17 @@ const createLens = <T, K>(source: State<T>, accessor: (state: T) => K): State<K>
|
|
|
384
389
|
|
|
385
390
|
const extractPath = (): (string | number)[] => {
|
|
386
391
|
const pathCollector: (string | number)[] = []
|
|
392
|
+
let tainted = false
|
|
387
393
|
const proxy = new Proxy(
|
|
388
394
|
{},
|
|
389
395
|
{
|
|
390
396
|
get: (_: object, prop: string | symbol): unknown => {
|
|
391
|
-
if (typeof prop === 'string' || typeof prop === 'number') {
|
|
392
|
-
|
|
397
|
+
if (!tainted && (typeof prop === 'string' || typeof prop === 'number')) {
|
|
398
|
+
if (DANGEROUS_KEYS.has(String(prop))) {
|
|
399
|
+
tainted = true
|
|
400
|
+
} else {
|
|
401
|
+
pathCollector.push(prop)
|
|
402
|
+
}
|
|
393
403
|
}
|
|
394
404
|
return proxy
|
|
395
405
|
},
|
|
@@ -402,7 +412,7 @@ const createLens = <T, K>(source: State<T>, accessor: (state: T) => K): State<K>
|
|
|
402
412
|
// Ignore errors, we're just collecting the path
|
|
403
413
|
}
|
|
404
414
|
|
|
405
|
-
return pathCollector
|
|
415
|
+
return tainted ? [] : pathCollector
|
|
406
416
|
}
|
|
407
417
|
|
|
408
418
|
const path = extractPath()
|
|
@@ -423,7 +433,7 @@ const createLens = <T, K>(source: State<T>, accessor: (state: T) => K): State<K>
|
|
|
423
433
|
})
|
|
424
434
|
|
|
425
435
|
lensState.set = function lensSet(value: K): void {
|
|
426
|
-
if (isUpdating) {
|
|
436
|
+
if (isUpdating || path.length === 0) {
|
|
427
437
|
return
|
|
428
438
|
}
|
|
429
439
|
|