@cplieger/reactive 2.1.1 → 2.1.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/NOTICE ADDED
@@ -0,0 +1,3 @@
1
+ reactive
2
+ Copyright 2026 cplieger
3
+ https://github.com/cplieger/reactive
package/README.md CHANGED
@@ -1,11 +1,6 @@
1
1
  # reactive
2
2
 
3
- [![npm](https://img.shields.io/npm/v/@cplieger/reactive)](https://www.npmjs.com/package/@cplieger/reactive)
4
- [![JSR](https://jsr.io/badges/@cplieger/reactive)](https://jsr.io/@cplieger/reactive)
5
- [![Test coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cplieger/reactive/badges/coverage.json)](https://github.com/cplieger/reactive/actions/workflows/coverage.yml)
6
- [![Mutation (TS)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cplieger/reactive/badges/mutation-ts.json)](https://github.com/cplieger/reactive/issues?q=label%3Astryker-tracker)
7
- [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13218/badge)](https://www.bestpractices.dev/projects/13218)
8
- [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/cplieger/reactive/badge)](https://scorecard.dev/viewer/?uri=github.com/cplieger/reactive)
3
+ [![npm](https://img.shields.io/npm/v/@cplieger/reactive)](https://www.npmjs.com/package/@cplieger/reactive) [![JSR](https://jsr.io/badges/@cplieger/reactive)](https://jsr.io/@cplieger/reactive) [![Mutation (TS)](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cplieger/reactive/badges/mutation-ts.json)](https://github.com/cplieger/reactive/issues?q=label%3Astryker-tracker)
9
4
 
10
5
  > Signals + collections + DOM-reconciliation micro-framework for TypeScript
11
6
 
@@ -23,6 +18,8 @@ A standalone reactive app-skeleton:
23
18
 
24
19
  The store, `SignalMap`, and `Collection` are thin facades over a single signal engine: one reactive core, not several. Zero dependencies beyond the DOM API.
25
20
 
21
+ > **What needs a DOM:** the render half, `el`, `bindList`, `reconcile`, `patch` and `trackHandler`. The engine and the state tiers do not: `signal`, `effect`, `computed`, `batch`, `untracked`, `createStore`, `SignalMap`, `createCollection` and `createBus`. Nothing touches the DOM at import time, so importing the package under Node, Deno, Bun or Workers succeeds and only the DOM functions throw when called.
22
+
26
23
  Mirrors semantics from @preact/signals-core and solid-js reactivity.
27
24
 
28
25
  ## Flush model
@@ -202,3 +199,5 @@ This project was built with AI-assisted tooling using [Claude](https://claude.co
202
199
  ## License
203
200
 
204
201
  Apache-2.0. See [LICENSE](LICENSE).
202
+
203
+ Third-party attributions are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,8 @@
1
+ # Third-party notices
2
+
3
+ No third-party code is included in this repository. The signal engine is a re-derivation of an upstream design, not a copy of its source, so no license text is reproduced here.
4
+
5
+ Two designs are followed, each named at the line of ours that follows it:
6
+
7
+ - The dependency graph and the scheduler in `src/signal.ts` follow [@preact/signals-core](https://github.com/preactjs/signals) (MIT): the doubly-linked source/target edge nodes (`DepNode`, `SourceNode`, `TargetNode` at `src/signal.ts:75-100`), the pull-based glitch-free `refreshComputed` (`src/signal.ts:327`), the eager drain in `endBatch` (`src/signal.ts:397`), and the untracked `subscribe` callback (`src/signal.ts:711`, upstream `preactjs/signals#188`). The pinned baseline is `@preact/signals-core@1.14.4`; the header of `src/signal.ts` records every deliberate delta from it and the upstream machinery this engine does not carry, and `CONTRIBUTING.md` records the drift-audit procedure.
8
+ - The explicit dependency helper `on()` (`src/signal.ts:734`) follows [solid-js](https://github.com/solidjs/solid) (MIT), whose `on()` has the same deps-plus-body shape; `untracked()` (`src/signal.ts:666`) is Solid's `untrack()` under the name Preact gives it.
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/reactive",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "license": "Apache-2.0",
5
5
  "exports": {
6
6
  ".": "./src/index.ts"
@@ -8,7 +8,9 @@
8
8
  "publish": {
9
9
  "include": [
10
10
  "LICENSE",
11
+ "NOTICE",
11
12
  "README.md",
13
+ "THIRD_PARTY_NOTICES.md",
12
14
  "src/**/*.ts"
13
15
  ],
14
16
  "exclude": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/reactive",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -9,7 +9,11 @@
9
9
  "scripts": {
10
10
  "typecheck": "tsc -p tsconfig.json",
11
11
  "typecheck:tests": "tsc -p tsconfig.tests.json",
12
- "test": "vitest --run"
12
+ "test": "vitest --run",
13
+ "lint:eslint": "eslint .",
14
+ "lint:prettier": "prettier --check .",
15
+ "lint:knip": "knip",
16
+ "lint:fix": "eslint . --fix && prettier --write ."
13
17
  },
14
18
  "devDependencies": {
15
19
  "@eslint/js": "10.0.1",
@@ -17,16 +21,17 @@
17
21
  "@stryker-mutator/typescript-checker": "10.0.0",
18
22
  "@stryker-mutator/vitest-runner": "10.0.0",
19
23
  "@typescript/native": "npm:typescript@7.0.2",
20
- "@vitest/browser": "5.0.0",
21
- "@vitest/browser-playwright": "5.0.0",
22
- "@vitest/coverage-v8": "5.0.0",
24
+ "@vitest/browser": "5.0.1",
25
+ "@vitest/browser-playwright": "5.0.1",
26
+ "@vitest/coverage-v8": "5.0.1",
23
27
  "eslint": "10.10.0",
24
- "fast-check": "4.10.0",
28
+ "fast-check": "4.10.1",
29
+ "knip": "6.36.0",
25
30
  "playwright": "1.63.0",
26
- "prettier": "3.9.6",
31
+ "prettier": "3.9.7",
27
32
  "typescript": "npm:@typescript/typescript6@6.0.2",
28
33
  "typescript-eslint": "8.70.0",
29
- "vitest": "5.0.0"
34
+ "vitest": "5.0.1"
30
35
  },
31
36
  "overrides": {
32
37
  "qs": "^6.15.2"
@@ -61,6 +66,9 @@
61
66
  "files": [
62
67
  "src/",
63
68
  "jsr.json",
64
- "!src/**/*.test.ts"
69
+ "!src/**/*.test.ts",
70
+ "LICENSE",
71
+ "NOTICE",
72
+ "THIRD_PARTY_NOTICES.md"
65
73
  ]
66
74
  }
package/src/signal.ts CHANGED
@@ -746,19 +746,27 @@ export function on<T, U>(
746
746
  fn: (value: T, prev: T | undefined, prevResult: U | undefined) => U,
747
747
  options?: { defer?: false },
748
748
  ): () => U;
749
- // Single accessor, deferred: first call returns undefined.
749
+ /** Single accessor, deferred: the first call returns undefined. A `defer`
750
+ * typed as `boolean` selects this overload even when the value is `false`,
751
+ * because the type cannot rule the deferred call out; pass a literal
752
+ * `false` (or omit `options`) to keep the non-undefined return. */
750
753
  export function on<T, U>(
751
754
  deps: () => T,
752
755
  fn: (value: T, prev: T | undefined, prevResult: U | undefined) => U,
753
756
  options: { defer: boolean },
754
757
  ): () => U | undefined;
755
- // Array of accessors, non-deferred (or explicit `{ defer: false }`): never undefined.
758
+ /** Array of accessors, non-deferred (or explicit `{ defer: false }`): never
759
+ * undefined. `value` and `prev` are the accessors' results in declaration
760
+ * order, typed `unknown[]` — a heterogeneous list is not correlated
761
+ * positionally, so narrow each element before use. */
756
762
  export function on<U>(
757
763
  deps: (() => unknown)[],
758
764
  fn: (value: unknown[], prev: unknown[] | undefined, prevResult: U | undefined) => U,
759
765
  options?: { defer?: false },
760
766
  ): () => U;
761
- // Array of accessors, deferred: first call returns undefined.
767
+ /** Array of accessors, deferred: the first call returns undefined, having read
768
+ * every accessor to seed `prev`. Same `boolean`-widening caveat as the single
769
+ * deferred overload. */
762
770
  export function on<U>(
763
771
  deps: (() => unknown)[],
764
772
  fn: (value: unknown[], prev: unknown[] | undefined, prevResult: U | undefined) => U,