Skip to content

Solidart v3: Refactor v3 core API and align ecosystem packages#167

Open
medz wants to merge 122 commits intomainfrom
refactor/3.0-dev
Open

Solidart v3: Refactor v3 core API and align ecosystem packages#167
medz wants to merge 122 commits intomainfrom
refactor/3.0-dev

Conversation

@medz
Copy link
Collaborator

@medz medz commented Dec 8, 2025

before PR:#166, resolves #156

Summary by CodeRabbit

  • New Features

    • v3 surface: ReadonlySignal, LazySignal, toReadonly(), toValueNotifier() interop; richer Resource API (resolve/untilReady, state helpers).
    • New List/Map/Set reactive collections and Observer hooks.
  • Bug Fixes & Improvements

    • Simplified Effect API (manual start/run); improved dependency tracking in SignalBuilder and Show; Signals now integrate with Listenable semantics; prefer direct value assignment.
  • Chores

    • Version bumps and dependency updates.
  • Tests

    • Expanded test coverage for signals, effects, resources, collections, and devtools.

✏️ Tip: You can customize this high-level summary in your review settings.

medz added 23 commits December 6, 2025 23:26
- Remove _AlienEffect wrapper class
- Simplify delayed callback logic
- Improve dependency cleanup in ReadableSignal
- Reorder imports consistently
Introduce a `Disposable` interface and `DisponsableMixin` (note: typo in
name) to provide a common disposal mechanism for `Signal`, `Computed`,
and `Effect`. This allows registering cleanup callbacks and ensures
proper resource disposal.
- Add SolidartConfig with static autoDispose flag
- Make ReadonlySignal implement Configuration
- Add name and autoDispose parameters to Signal, LazySignal, and
  Computed
- Export Configuration and Disposable from the main library
The Effect class now implements Configuration and accepts optional name
and autoDispose parameters, defaulting autoDispose to the global
SolidartConfig.autoDispose value when not provided.
Introduce an `Identifier` class that provides a unique integer value
alongside an optional name. This replaces the simple `name` property on
signals, computed values, and effects to ensure each reactive primitive
has a distinct identifier for debugging and tracking.
Check isInitialized in value getter to throw a clearer error. The error
message now instructs to set `.value = <newValue>`.
Ensure Effect is properly stopped when disposed by calling preset.stop
before super.dispose.
The default value of `SolidartConifg.autoDispose` is changed from
`false` to `true`. New static methods `Disposable.canAutoDispose`,
`unlinkDeps`, and `unlinkSubs` manage dependency cleanup. Signal,
Computed, and Effect dispose methods now cascade disposal to dependent
nodes when auto-dispose is enabled.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 8, 2025

Walkthrough

Major v3 refactor: replaces the custom reactive system with alien_signals preset, redesigns core primitives (Signal, ReadonlySignal, LazySignal, Computed, Effect, Resource), introduces disposable/configuration/identifier APIs, rewrites collection signals and Flutter wrappers, and updates tests, examples, and docs for the new surface.

Changes

Cohort / File(s) Summary
Signal core & API
packages/solidart/lib/src/core/signal.dart, packages/solidart/lib/src/core/readonly_signal.dart, packages/solidart/lib/src/core/lazy_signal.dart
New v3 Signal/ReadonlySignal/LazySignal shapes: value property, toReadonly(), previous/untracked accessors, lazy initialization, equals comparator, identifier and autoDispose semantics.
Effect & reactive preset
packages/solidart/lib/src/core/effect.dart, packages/solidart/lib/src/core/reactive_system.dart, packages/solidart/lib/deps/preset.dart, packages/solidart/lib/deps/system.dart
Removes custom ReactiveSystem; adopts alien_signals preset API, adds Effect.manual/run/dispose semantics, and re-exports preset/system.
Computed & derived
packages/solidart/lib/src/core/computed.dart, packages/flutter_solidart/lib/src/core/computed.dart
Reimplemented Computed atop preset.ComputedNode with didUpdate lifecycle, optional previous-value tracking, and Flutter wrapper adapted to core.Computed.
Collections (List/Map/Set)
packages/solidart/lib/src/core/collections/..., packages/flutter_solidart/lib/src/core/*_signal.dart
Introduces copy-on-write core ListSignal/MapSignal/SetSignal; removes many older wrapper files and updates Flutter wrappers to new SignalValueListenableMixin integrations.
Resource system
packages/solidart/lib/src/resources/resource.dart, .../resource_state.dart, .../resource_state_extensions.dart, packages/flutter_solidart/lib/src/core/resource.dart
Rebuilds Resource with sealed ResourceState (Ready/Loading/Error), resolve()/untilReady(), stream support, debouncing/source integration, and Flutter wrapper updates.
Disposal, configuration, identifiers
packages/solidart/lib/src/core/disposable.dart, .../configuration.dart, .../identifier.dart, .../signal_configuration.dart
Adds Disposable interface & DisposableMixin, Configuration contract, Identifier for DevTools/diagnostics, and signal-specific configuration APIs.
DevTools & observers
packages/solidart/lib/src/core/devtools.dart, packages/solidart/lib/src/core/observer.dart, packages/solidart_devtools_extension/lib/main.dart
Refactors devtools payloads to use Identifier and ReadonlySignal, private event types, new notify hooks, and extension mapping updates for readonly/lazy signals.
SignalBuilder (Flutter)
packages/flutter_solidart/lib/src/widgets/signal_builder.dart
Replaces reactiveSystem.activeSub with preset.setActiveSub plus element-level _effect; adds explicit lifecycle state, purge-and-recapture dependency flow, _isBuilding guard, re-entrancy and unmount handling.
ValueListenable interop & mixins
packages/flutter_solidart/lib/src/core/value_listenable_signal_mixin.dart, packages/flutter_solidart/lib/src/utils/extensions.dart
Replaces ValueNotifier mixin with SignalValueListenableMixin bound to ReadonlySignal; adds _SignalValueNotifier and ValueListenable↔Signal conversion helpers.
Hooks & Flutter wrappers
packages/solidart_hooks/lib/solidart_hooks.dart, packages/flutter_solidart/lib/flutter_solidart.dart
Hooks rebinding to ReadonlySignal, simplified hook signatures (no per-call disposeOnUnmount), updated Flutter exports and hidden list adjustments.
Extensions & utilities
packages/solidart/lib/src/extensions/until.dart, packages/solidart/lib/src/extensions/observe_signal.dart, packages/solidart/lib/src/core/batch.dart, packages/solidart/lib/src/core/untracked.dart
Renames/rewires extensions to ReadonlySignal (UntilSignal, ObserveSignal.observe), and switches batch/untracked to preset APIs.
Tests, examples, docs, manifests
packages/solidart/test/*, packages/flutter_solidart/example/*, docs-v2/src/content/docs/migration.mdx, */pubspec.yaml, */CHANGELOG.md
Large addition/update of tests validating v3 behavior, example migrations to v3 APIs, migration guide, and package version bumps to 3.0.0-dev.0 plus alien_signals upgrades.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant SB as SignalBuilder
    participant Preset as alien_signals<br/>Preset
    participant Effect as _SignalBuilderElement._effect
    participant Signal as Signal<T>

    App->>SB: build(context)
    SB->>SB: set _isBuilding = true
    SB->>Preset: preset.setActiveSub(Effect)
    SB->>App: execute builder() (reads signals)
    App->>Signal: read .value
    Signal->>Preset: link dependency to active sub
    Preset->>Effect: register dependency
    SB->>SB: purgeDeps(Effect) and recapture -> _depsHead/_depsTail
    SB->>Preset: preset.setActiveSub(previous)
    SB->>SB: _isBuilding = false, return widget
Loading
sequenceDiagram
    participant Caller as User
    participant Resource as Resource<T>
    participant Fetcher as Future/Stream
    participant State as ResourceState

    Caller->>Resource: access .state or call resolve()
    Resource->>Resource: _resolveIfNeeded()
    Resource->>Fetcher: start fetch/stream
    Fetcher-->>Resource: emits value / error
    Resource->>State: _transition -> Ready / Error
    Resource-->>Caller: updated state via ReadonlySignal
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • nank1ro

Poem

🐰 I hopped through presets and mended each thread,
Signals now tidy, lazy values well fed.
Effects sit patient until I say "run",
Resources bloom when their fetchers are done.
DevTools now name them — a hop, skip, and fun!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Solidart v3: Refactor v3 core API and align ecosystem packages' clearly summarizes the main objective of a major version refactor to v3 with ecosystem alignment.
Linked Issues check ✅ Passed The PR successfully implements the requirements from #156: upgrades alien_signals to v2.0, enables direct collection signal triggering, implements autoDispose fully, reduces codebase by ~50%, improves maintenance complexity, and aligns ecosystem packages to v3.
Out of Scope Changes check ✅ Passed All changes are in-scope: v3 core API refactoring with new types (ReadonlySignal, LazySignal, Disposable, Configuration, Option), migration of dependencies to alien_signals v2.1.1, ecosystem package updates, test suite rewrite, and documentation. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/3.0-dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Dec 8, 2025

Codecov Report

❌ Patch coverage is 98.90710% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.99%. Comparing base (40119f4) to head (9fe9d76).

Files with missing lines Patch % Lines
packages/solidart/lib/src/core/devtools.dart 91.48% 4 Missing ⚠️
packages/solidart/lib/src/resources/resource.dart 97.11% 3 Missing ⚠️
packages/solidart/lib/src/core/signal.dart 97.50% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##              main     #167      +/-   ##
===========================================
- Coverage   100.00%   98.99%   -1.01%     
===========================================
  Files           18       26       +8     
  Lines          931      793     -138     
===========================================
- Hits           931      785     -146     
- Misses           0        8       +8     
Files with missing lines Coverage Δ
...ckages/flutter_solidart/lib/src/core/computed.dart 100.00% <ø> (ø)
...ckages/flutter_solidart/lib/src/core/resource.dart 100.00% <ø> (ø)
packages/flutter_solidart/lib/src/core/signal.dart 100.00% <100.00%> (ø)
...rt/lib/src/core/value_listenable_signal_mixin.dart 100.00% <100.00%> (ø)
...ges/flutter_solidart/lib/src/utils/extensions.dart 100.00% <100.00%> (ø)
...ackages/flutter_solidart/lib/src/widgets/show.dart 100.00% <100.00%> (ø)
...utter_solidart/lib/src/widgets/signal_builder.dart 100.00% <100.00%> (ø)
packages/solidart/lib/src/core/batch.dart 100.00% <100.00%> (ø)
packages/solidart/lib/src/core/computed.dart 100.00% <100.00%> (ø)
packages/solidart/lib/src/core/config.dart 100.00% <ø> (ø)
... and 16 more
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (5)
packages/solidart/test/v3_auto_dispose_test.dart (1)

122-130: Consider adding a doc comment for the test helper.

The _depsOf helper is useful for test introspection. A brief comment explaining its purpose would aid future maintainers.

+/// Returns the list of dependencies for a reactive node by traversing the linked list.
 List<system.ReactiveNode> _depsOf(system.ReactiveNode node) {
packages/solidart/lib/src/core/effect.dart (2)

171-187: Effect linking and execution logic is correct but complex.

The conditional for subscriber linking (lines 173-178) correctly handles the detach scenarios. The logic ensures detached effects don't create unwanted dependencies on parent subscribers.

Consider adding a brief inline comment explaining the detach conditions for future maintainability.


216-225: Redundant disposed check in _mayDispose().

Line 217 already returns if _disposed is true, making the || _disposed check on line 220 redundant.

   @override
   void _mayDispose() {
     if (_disposed) return;
 
     if (SolidartConfig.autoDispose) {
-      if (!autoDispose || _disposed) return;
+      if (!autoDispose) return;
       if (subscriber.deps?.dep == null) {
         dispose();
       }
     }
   }
packages/solidart/lib/src/v3.dart (2)

185-219: v3 Effect lacks error handling present in core Effect.

The core Effect wraps callback execution in a try-catch that converts exceptions to SolidartCaughtException with an onError handler. This v3 Effect runs the callback directly in the constructor without error handling, which could result in unhandled exceptions during reactive graph construction.

Consider adding an onError callback parameter for consistency with the core API, or document that errors propagate directly.


1-2: TODO noted for adding documentation.

The file is appropriately marked with public_member_api_docs ignore and a TODO. Consider tracking this in an issue to ensure documentation is added before the v3 release.

Would you like me to open an issue to track adding documentation for the v3 API?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c762c82 and 550c194.

📒 Files selected for processing (19)
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart (3 hunks)
  • packages/flutter_solidart/pubspec.yaml (1 hunks)
  • packages/solidart/example/main.dart (1 hunks)
  • packages/solidart/lib/advanced.dart (1 hunks)
  • packages/solidart/lib/deps/preset.dart (1 hunks)
  • packages/solidart/lib/deps/system.dart (1 hunks)
  • packages/solidart/lib/src/core/alien.dart (1 hunks)
  • packages/solidart/lib/src/core/batch.dart (1 hunks)
  • packages/solidart/lib/src/core/computed.dart (5 hunks)
  • packages/solidart/lib/src/core/core.dart (1 hunks)
  • packages/solidart/lib/src/core/effect.dart (5 hunks)
  • packages/solidart/lib/src/core/reactive_system.dart (1 hunks)
  • packages/solidart/lib/src/core/read_signal.dart (6 hunks)
  • packages/solidart/lib/src/core/signal_base.dart (1 hunks)
  • packages/solidart/lib/src/core/untracked.dart (1 hunks)
  • packages/solidart/lib/src/v3.dart (1 hunks)
  • packages/solidart/lib/v3.dart (1 hunks)
  • packages/solidart/pubspec.yaml (1 hunks)
  • packages/solidart/test/v3_auto_dispose_test.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
packages/{solidart,flutter_solidart}/lib/**/*.dart

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/{solidart,flutter_solidart}/lib/**/*.dart: Use Signals for state, Effects for side effects, and Computed for derived values in library code
Use untracked() for reads that should not trigger reactivity
Ensure proper memory management: Signals auto-dispose in Flutter contexts; manually dispose in pure Dart code

Files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/lib/src/core/batch.dart
  • packages/solidart/lib/src/core/reactive_system.dart
  • packages/solidart/lib/src/core/computed.dart
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/core/effect.dart
  • packages/solidart/lib/src/v3.dart
packages/flutter_solidart/{lib,test}/**/*.dart

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For Flutter Solidart changes, ensure widget tests cover SignalBuilder, Provider, and Show behaviors

Files:

  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
packages/solidart/test/**/*.dart

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Write unit tests covering Signal operations and state transitions

Files:

  • packages/solidart/test/v3_auto_dispose_test.dart
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Use Signals for state, Effects for side effects, and Computed for derived values in library code
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/solidart/test/solidart_test.dart : After Signal changes, always run `packages/solidart/test/solidart_test.dart`

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/pubspec.yaml
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/flutter_solidart/{lib,test}/**/*.dart : For Flutter Solidart changes, ensure widget tests cover `SignalBuilder`, `Provider`, and `Show` behaviors

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/solidart/lib/src/core/computed.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/pubspec.yaml
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/flutter_solidart/test/flutter_solidart_test.dart : After Flutter integration changes, always run `packages/flutter_solidart/test/flutter_solidart_test.dart`

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/pubspec.yaml
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Use Signals for state, Effects for side effects, and Computed for derived values in library code

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/lib/src/core/reactive_system.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/solidart/lib/src/core/computed.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/pubspec.yaml
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/core/effect.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-10-04T15:38:49.286Z
Learnt from: medz
Repo: nank1ro/solidart PR: 149
File: packages/solidart/lib/src/effect.dart:1-0
Timestamp: 2025-10-04T15:38:49.286Z
Learning: In Dart, multiple import statements can use the same prefix with the `as` keyword. For example, `import 'package:a/a.dart' as foo;` and `import 'package:b/b.dart' as foo;` is valid syntax. The symbols from both packages will be accessible under the single `foo` namespace.

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/core.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Ensure proper memory management: Signals auto-dispose in Flutter contexts; manually dispose in pure Dart code

Applied to files:

  • packages/solidart/lib/deps/preset.dart
  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/lib/src/core/reactive_system.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Use `untracked()` for reads that should not trigger reactivity

Applied to files:

  • packages/solidart/lib/advanced.dart
  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/lib/src/core/reactive_system.dart
  • packages/solidart/lib/src/core/computed.dart
  • packages/flutter_solidart/pubspec.yaml
  • packages/solidart/lib/src/core/untracked.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/alien.dart
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/solidart/test/**/*.dart : Write unit tests covering Signal operations and state transitions

Applied to files:

  • packages/solidart/lib/v3.dart
  • packages/solidart/lib/deps/system.dart
  • packages/solidart/lib/src/core/signal_base.dart
  • packages/solidart/lib/src/core/core.dart
  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/test/v3_auto_dispose_test.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/read_signal.dart
  • packages/solidart/lib/src/v3.dart
📚 Learning: 2025-10-08T11:10:13.808Z
Learnt from: nank1ro
Repo: nank1ro/solidart PR: 151
File: packages/solidart_hooks/CHANGELOG.md:12-16
Timestamp: 2025-10-08T11:10:13.808Z
Learning: In solidart/flutter_solidart, SignalBuilder supports automatic signal tracking where signals are detected when accessed inside the builder. The builder signature for automatic tracking is `(BuildContext, Widget? child)`, not requiring an explicit signal parameter or value parameter. Example: `SignalBuilder(builder: (context, child) => Text('${counter.value}'))`.

Applied to files:

  • packages/flutter_solidart/lib/src/widgets/signal_builder.dart
  • packages/solidart/lib/src/core/computed.dart
  • packages/solidart/example/main.dart
  • packages/solidart/lib/src/core/read_signal.dart
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Install Flutter stable channel and Dart SDK before development

Applied to files:

  • packages/flutter_solidart/pubspec.yaml
📚 Learning: 2025-09-10T15:36:53.390Z
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/solidart_lint/** : When changing linting rules, test the `packages/solidart_lint/` package examples

Applied to files:

  • packages/solidart/example/main.dart
📚 Learning: 2025-10-07T14:44:49.132Z
Learnt from: nank1ro
Repo: nank1ro/solidart PR: 150
File: packages/flutter_solidart/lib/src/core/value_notifier_signal_mixin.dart:14-20
Timestamp: 2025-10-07T14:44:49.132Z
Learning: In `packages/flutter_solidart/lib/src/core/value_notifier_signal_mixin.dart`, the `ValueNotifierSignalMixin` intentionally does not support duplicate listener registrations. The `putIfAbsent` pattern is a deliberate design decision by the maintainer.

Applied to files:

  • packages/solidart/lib/src/core/read_signal.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (27)
packages/solidart/lib/src/core/alien.dart (2)

3-10: LGTM! Clean migration to preset-based ComputedNode.

The refactor successfully migrates _AlienComputed from a custom alien.ReactiveNode to preset.ComputedNode<T>, eliminating the need for custom reactive system implementation. The use of system.ReactiveFlags.none and preset.stop(this) aligns with the new alien_signals v2 API.


12-21: LGTM! Proper migration to preset-based SignalNode.

The migration to preset.SignalNode<Option<T>> with system.ReactiveFlags.mutable correctly implements the new preset-based architecture. The initialization of both currentValue and pendingValue follows the expected pattern for mutable signals.

packages/solidart/example/main.dart (1)

3-3: LGTM! Example migrated to v3 API.

The import change to package:solidart/v3.dart correctly demonstrates the new v3 API surface. The example code properly uses Signal, Computed, and Effect primitives.

packages/solidart/lib/src/core/core.dart (1)

9-10: LGTM! Good abstraction over alien_signals.

Creating an abstraction layer via solidart/deps/preset.dart and solidart/deps/system.dart instead of directly importing alien_signals improves maintainability and simplifies potential future migrations. This aligns well with the PR goal to standardize the public API.

packages/solidart/lib/deps/system.dart (1)

1-1: LGTM! Centralized system types export.

This re-export provides a clean abstraction layer for accessing alien_signals system types (ReactiveNode, ReactiveFlags, etc.) through Solidart's internal dependency surface. This approach supports the PR's goal to simplify maintenance and clarify responsibilities.

packages/solidart/lib/src/core/batch.dart (1)

23-30: LGTM! Clean migration to preset-based batching.

The function correctly migrates from reactiveSystem.startBatch()/endBatch() to preset.startBatch()/endBatch() while preserving the same functionality and error-handling semantics. This aligns with the PR goal to remove the custom ReactiveSystem.

packages/solidart/lib/deps/preset.dart (1)

1-1: LGTM! Centralized preset API export.

This re-export provides clean access to alien_signals preset utilities (ComputedNode, SignalNode, EffectNode, getActiveSub, setActiveSub, stop, etc.), supporting the preset-based architecture migration throughout the codebase. This abstraction layer supports maintainability and API standardization goals.

packages/flutter_solidart/pubspec.yaml (1)

21-21: LGTM! Verify Flutter integration with updated core.

The patch version bump from ^2.8.2 to ^2.8.3 correctly aligns with the core solidart library changes in this PR. The test suite comprehensively covers Provider, SignalBuilder, and Show widget behaviors across multiple scenarios.

Run the Flutter integration tests to confirm compatibility:

#!/bin/bash
# Run flutter_solidart tests to verify integration with solidart ^2.8.3

cd packages/flutter_solidart
flutter test
packages/solidart/lib/src/core/signal_base.dart (1)

108-109: LGTM!

The lint suppression for unused_element is correctly placed. This allows the abstract method to exist in the base class even when not all implementations use it directly.

packages/solidart/lib/src/core/untracked.dart (1)

7-13: LGTM!

Clean migration to preset-based active-sub management. The pattern correctly saves the previous subscription, clears it during callback execution, and restores it in the finally block—ensuring untracked reads don't trigger reactivity as per the coding guidelines.

packages/solidart/test/v3_auto_dispose_test.dart (4)

1-15: Good test setup with proper config isolation.

The setUp/tearDown pattern correctly saves and restores the global autoDispose configuration, preventing test pollution. This aligns with the coding guidelines for writing unit tests covering Signal operations and state transitions.


17-40: Well-structured cascade disposal test.

This test verifies that disposing a signal cascades to its direct dependents (b, c) while leaving signals with other dependencies alive (d, e). The assertion on line 38-39 that e's deps no longer contain a but still contain d is a good verification of partial dependency cleanup.


42-83: Good coverage of computed and effect disposal semantics.

Both tests properly verify that:

  1. Disposing a computed cleans its subscribers but keeps shared dependencies alive
  2. Disposing an effect detaches its dependencies and triggers auto-dispose on orphaned nodes

This covers critical lifecycle management scenarios.


85-119: Explicit autoDispose flag tests are comprehensive.

These tests verify that:

  1. autoDispose: false prevents cascading disposal (lines 85-99)
  2. Explicit autoDispose: true overrides global false setting (lines 101-119)

The assertion on line 118 that d's deps are empty after a is disposed confirms proper dependency detachment even when d itself doesn't auto-dispose.

packages/solidart/lib/src/core/computed.dart (2)

156-162: Pending flag cleanup logic is sound.

The logic correctly clears the pending flag when there are no dependencies (deps == null), preventing stale state from blocking value retrieval. The bitwise operations are correct for flag manipulation.


251-257: _compare implementation correctly honors configuration.

The implementation properly supports both the equals flag (using ==) and the custom comparator function. This fulfills the abstract contract in SignalBase.

packages/flutter_solidart/lib/src/widgets/signal_builder.dart (2)

88-103: The self-referential pattern effect.setDependencies(effect) is correct API usage. During the build phase, the effect is set as the active subscriber via preset.setActiveSub(node), which allows Signals and Computeds accessed during build to register themselves in the effect's internal dependency tracking. The setDependencies() call then extracts those accumulated dependencies via getDependencies() and transfers them to _deps for formal dependency management. This is the intended design.

Likely an incorrect or invalid review comment.


103-103: Consider preserving existing flags with bitwise OR instead of direct assignment.

The direct assignment node.flags = system.ReactiveFlags.watching; overwrites all existing flags. While the current implementation appears intentional (resetting the node to a "watching" state after dependency collection), using node.flags |= system.ReactiveFlags.watching; would be safer if other flags need to be preserved alongside the watching state. This aligns with how flag modifications are handled elsewhere in the codebase (e.g., computed.dart line 159 uses flags &= ~value). Verify with the alien_signals documentation whether the watching flag should coexist with other flags set during the build process.

packages/solidart/lib/src/core/reactive_system.dart (1)

6-27: Clean migration to system.ReactiveNode types.

The extension and its methods correctly migrate from alien.ReactiveNode to system.ReactiveNode, aligning with the preset-based lifecycle management. The dependency traversal and disposal logic remains intact.

packages/solidart/lib/src/core/read_signal.dart (3)

119-123: Direct signal access for observation tracking looks correct.

Using _internalSignal.get() directly for observation recording is cleaner than the previous reactiveSystem indirection.


265-313: Comprehensive disposal handling for different subscriber types.

The enhanced disposal logic correctly differentiates between Effect, preset.EffectNode, and _AlienComputed subscribers, applying appropriate cleanup for each. The pattern of clearing deps links before calling preset.stop() prevents dangling references.

Based on coding guidelines, ensure proper memory management is maintained - this implementation correctly handles manual disposal in pure Dart contexts.


342-348: Flag-based update check is correct.

The shouldUpdate() implementation correctly checks the dirty flag using bitwise operations before delegating to didUpdate(). This aligns with the preset-based reactive model.

packages/solidart/lib/src/core/effect.dart (1)

96-110: Delayed callback timer handling is correct.

The pattern of canceling any existing timer before creating a new one prevents timer accumulation. The disposal check inside the delayed callback prevents execution after disposal.

packages/solidart/lib/src/v3.dart (4)

11-33: Clean Option type implementation.

The sealed class with pattern matching provides type-safe optional value handling. The unwrap() and safeUnwrap() methods follow common Option conventions.


54-91: Well-structured disposal helpers with correct linked list traversal.

The unlinkDeps and unlinkSubs methods correctly save the next link before unlinking, preventing iteration issues. The canAutoDispose pattern matching elegantly checks both interfaces.


99-141: Signal implementation correctly integrates with preset.SignalNode.

The disposal sequence (unlinkSubs → preset.stop → super.dispose) ensures subscribers are notified before the signal is stopped. The toReadonly() returning this is a valid pattern since Signal implements ReadonlySignal.


158-183: Computed disposal correctly handles both subscriber and dependency roles.

Unlike Signal (producer-only, unlinks subs) and Effect (consumer-only, unlinks deps), Computed correctly unlinks both since it participates in the reactive graph as both a dependency source and a subscriber.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@packages/flutter_solidart/CHANGELOG.md`:
- Around line 1-28: Add a bullet under the "Dependencies" section documenting
the upgrade to alien_signals v2.0: mention the dependency name "alien_signals",
the new version "v2.0", link the PR/issue "#156", and briefly note the key
impacts (≈10% perf improvement, reduced memory usage, improved API layering) so
users see this core objective of the release; update the existing "CHORE: Bump
`solidart` to `3.0.0-dev.0`" block only if you also changed the dependency
constraints to reference alien_signals v2.0.
- Around line 5-9: The CHANGELOG is missing explicit BREAKING entries for the
collection type renames; add separate **BREAKING** lines documenting that
ReactiveList → ListSignal, ReactiveSet → SetSignal, and ReactiveMap → MapSignal
so users can find the exact type changes. Update the existing list of breaking
changes to include three distinct entries naming the old and new types
(ReactiveList, ReactiveSet, ReactiveMap → ListSignal, SetSignal, MapSignal) and
ensure they appear alongside the other BREAKING items such as
Signal.toReadSignal() → toReadonly() and removal of ReadableSignal.

In `@packages/solidart_hooks/pubspec.yaml`:
- Line 3: The package version in packages/solidart_hooks pubspec.yaml is
incorrectly set to 3.1.3 while it depends on unreleased breaking changes in
flutter_solidart 3.0.0-dev.0; update the version field in the pubspec
(packages/solidart_hooks -> version) to 3.0.0-dev.0 so the package
major/pre-release aligns with the workspace breaking changes introduced by
flutter_solidart and solidart.

In `@packages/solidart_lint/pubspec.yaml`:
- Around line 30-31: The pubspec lists non-existent prerelease versions for the
dependencies; update the solidart and flutter_solidart versions to published
versions (e.g., set solidart to 2.8.3 and flutter_solidart to 2.7.1) or point
them to a valid hosted/git path if you intend to use unpublished 3.0.0-dev.0;
change the entries for the packages named "solidart" and "flutter_solidart"
accordingly so dependency resolution succeeds.
🧹 Nitpick comments (3)
packages/solidart/CHANGELOG.md (1)

29-32: Reduce repeated “BREAKING” starts for readability.

Four consecutive bullets begin with the same word; consider merging or rephrasing a couple to improve scanability.

packages/flutter_solidart/CHANGELOG.md (2)

14-14: Clarify the "(via core)" parenthetical.

The phrase "via core" in "Resource.resolve() is now public (via core)" may be unclear to users. Consider either removing it or expanding it to clarify that this was exposed from the core solidart package.

✨ Suggested clarification
-- **ADDED**: `Resource.resolve()` is now public (via core).
+- **ADDED**: `Resource.resolve()` is now public (exposed from solidart core).

or simply:

-- **ADDED**: `Resource.resolve()` is now public (via core).
+- **ADDED**: `Resource.resolve()` is now public.

1-28: Consider highlighting autoDispose implementation.

The PR objectives emphasize that autoDispose is "implemented fully" as a key feature of v3. While this may be implicit in the core changes, consider explicitly mentioning it in the changelog to help users understand this important memory management improvement.

Based on learnings, proper memory management is a key concern for the solidart/flutter_solidart ecosystem, with signals auto-disposing in Flutter contexts.

medz added 4 commits January 30, 2026 23:39
- Replace deprecated LazySignal constructor with Signal.lazy factory
- Use pattern matching for cleaner lazy signal state checks
- Simplify conditional logic in button handlers
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/solidart/lib/src/solidart.dart`:
- Around line 623-638: The file declares the factory constructor Signal.lazy
after the isInitialized getter, violating the sort_constructors_first lint; move
the factory constructor declaration (factory Signal.lazy { ... } / LazySignal)
so that all constructors, including Signal.lazy, appear before other members
like the bool get isInitialized => true; and then place the isInitialized getter
immediately after the constructors to satisfy the lint rule.
🧹 Nitpick comments (1)
packages/solidart/lib/src/solidart.dart (1)

2154-2166: Consider running all cleanup callbacks even if one throws.

Currently, if a cleanup callback throws an exception, subsequent callbacks in the list won't execute. This could lead to resource leaks. Consider catching exceptions from individual callbacks and running all of them.

♻️ Proposed fix
 `@mustCallSuper`
 `@override`
 void dispose() {
   if (isDisposed) return;
   isDisposed = true;
+  Object? firstError;
+  StackTrace? firstStackTrace;
   try {
     for (final callback in cleanups) {
-      callback();
+      try {
+        callback();
+      } catch (e, s) {
+        firstError ??= e;
+        firstStackTrace ??= s;
+      }
     }
   } finally {
     cleanups.clear();
   }
+  if (firstError != null) {
+    Error.throwWithStackTrace(firstError, firstStackTrace!);
+  }
 }

@medz medz marked this pull request as draft January 30, 2026 16:12
medz added 4 commits January 31, 2026 01:35
The migration guide has been completely rewritten to reflect the actual
API changes between v2 and v3. Key updates include:

- Restructured content to focus on actual public API changes rather than
  hypothetical ones
- Added detailed comparison tables for core types, naming conventions,
  and API changes
- Documented behavioral differences including autoDispose default change
  and previous value tracking
- Provided specific migration examples for Signals, Effects, Resources,
  and Flutter integration
- Added quick migration checklist for practical upgrade steps
@medz medz marked this pull request as ready for review January 30, 2026 18:17
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@docs-v2/src/content/docs/migration.mdx`:
- Around line 160-169: The checklist is missing items for migrating reactive
collections; after adding the reactive collections section, add bullets to the
Quick migration checklist that call out updating reactive collections APIs
(e.g., replace old collection types with the new reactive collections, migrate
ReactiveList/ReactiveMap/ReactiveSet usages to the new types, update method
calls like add/remove/clear/insert/replace to the new API names, and adjust
state/serialization and subscription/disposal semantics for collection signals);
reference the "reactive collections" section and the collection type names
(ReactiveList, ReactiveMap, ReactiveSet) and relevant methods so readers can
locate and update usages accordingly.
- Around line 1-169: Add a new migration subsection after the "Utils removal"
section that documents the reactive collections rename: state the type renames
ReactiveList → ListSignal, ReactiveMap → MapSignal, ReactiveSet → SetSignal and
show example before/after using those type names (use symbols ReactiveList,
ReactiveMap, ReactiveSet and ListSignal, MapSignal, SetSignal to locate
examples), include hooks renames useReactiveList → useListSignal, useReactiveMap
→ useMapSignal, useReactiveSet → useSetSignal, and update subsequent section
numbers (Behavioral differences → 7, Quick migration checklist → 8).

In `@packages/solidart/lib/src/core/disposable.dart`:
- Around line 85-88: The onDispose method currently always pushes callbacks into
the cleanups list even if the object is already disposed; update onDispose (in
class/mixin that declares isDisposed, cleanups, and onDispose) to check
isDisposed first and, if true, invoke the provided VoidCallback immediately
instead of adding it to cleanups, otherwise add it as before; ensure behavior is
consistent with dispose() (which should call all callbacks in cleanups) so
late-registered callbacks run right away when isDisposed is already true.

In `@packages/solidart/lib/src/core/lazy_signal.dart`:
- Around line 43-52: LazySignal.didUpdate currently initializes the signal
without notifying devtools or setting previous-value tracking; update the
!isInitialized branch in LazySignal.didUpdate to set flags =
system.ReactiveFlags.mutable, set _previousValue = const None() when
trackPreviousValue is true, assign currentValue = pendingValue, then call
_notifySignalUpdate(this) before returning true so the first assignment is
observable and previous value tracking matches Signal.didUpdate().

In `@packages/solidart/lib/src/core/signal.dart`:
- Around line 70-75: Signal.lazy currently declares the equals parameter as
non-nullable without a default, making it required and breaking compilation;
update the factory signature for Signal.lazy to provide a default comparator
(use the same default as the primary constructor, e.g., identical) so callers
can invoke Signal.lazy() without supplying equals, and ensure the factory
forwards that default to the underlying implementation (referencing the
Signal.lazy factory and the equals parameter).
- Around line 120-168: The current implementation updates _previousValue on
every write (in didUpdate) but previousValue calls value, causing previousValue
to return the old value immediately after a write; instead implement a
"first-read" gate: add a private boolean (e.g., _hasBeenRead = false), set it to
true inside the value getter (T get value / super.get()) so reads mark the
signal as consumed, make previousValue return null unless trackPreviousValue &&
_hasBeenRead, and change didUpdate to only assign _previousValue when
trackPreviousValue && _hasBeenRead && current is Some<T>; update references to
previousValue, untrackedPreviousValue, value, and didUpdate accordingly.

In `@packages/solidart/lib/src/resources/resource.dart`:
- Around line 249-261: The bug is that _version is incremented inside
_listenStream, allowing events emitted between cancel() and the new listen to
incorrectly update state; change the flow so the caller increments _version
before cancelling/starting a new subscription and pass the new requestId into
_listenStream (e.g., add a parameter requestId to _listenStream and use that
instead of computing requestId = ++_version inside it), update callers that
currently call _listenStream() (and places noted at lines ~274-279 and ~304-306)
to compute requestId = ++_version, cancel the old _streamSubscription, then call
_listenStream(requestId) so any events from older subscriptions are immediately
ignored via _isStale(requestId).
- Around line 177-195: The refresh() method can run fetchers or resubscribe
streams after the resource is disposed; add an early disposal guard at the top
of refresh() (check the resource's _disposed or isDisposed flag) and return
immediately if disposed to prevent calling resolve(), _refetch(), or
_resubscribe(); update refresh() to short-circuit before using _resolved,
resolve(), fetcher, _refetch(), stream, or _resubscribe() so no operations run
on a disposed resource.
🧹 Nitpick comments (6)
packages/flutter_solidart/example/lib/pages/lazy_counter.dart (1)

33-38: Consider performing the intended operation after initialization.

When pressing "add" on an uninitialized counter, the user likely expects the counter to become 1, but currently it initializes to 0 and returns without incrementing. Same for "subtract" (expected -1, actual 0). This may be intentional for demonstrating lazy initialization behavior, but could surprise users.

💡 Optional: Perform operation after initialization
           onPressed: () {
             if (!counter.isInitialized) {
-              counter.value = 0;
+              counter.value = -1;
               return;
             }

             counter.value -= 1;
           },
         ),
         const SizedBox(width: 8),
         FloatingActionButton(
           heroTag: "add hero",
           child: const Icon(Icons.add),
           onPressed: () {
             if (!counter.isInitialized) {
-              counter.value = 0;
+              counter.value = 1;
               return;
             }

             counter.value += 1;
           },

Alternatively, consolidate the logic:

onPressed: () {
  counter.value = (counter.isInitialized ? counter.value : 0) + 1;
},

Also applies to: 46-51

packages/solidart/CHANGELOG.md (1)

35-35: Remove alien_signals upgrade from CHANGELOG per project convention.

Based on learnings, alien_signals dependency updates should not be documented in CHANGELOG files, even for major upgrades. The public API and behavior changes enabled by alien_signals v2.0 are already documented in other sections (Signals, Effect, Resource, Core). Remove the alien_signals upgrade portion of this line; the fake_async test tooling addition can remain.

📝 Proposed revision
-- **CHORE**: Upgrade `alien_signals` to `^2.1.1` and add `fake_async` for tests.
+- **CHORE**: Add `fake_async` for tests.
packages/solidart/lib/src/core/map_signal.dart (1)

84-86: cast() returns a disconnected copy rather than a view.

The standard Map.cast<RK, RV>() returns a view where modifications reflect in the original. This implementation returns a new independent MapSignal — changes to either map won't affect the other, and no reactive dependency is established on the source.

This may be intentional for the reactive model, but consider documenting this behavior explicitly to avoid user confusion.

📝 Suggested documentation addition
+  /// Returns a **new** [MapSignal] containing the current values cast to
+  /// `<RK, RV>`. Unlike the standard [Map.cast], this creates an independent
+  /// copy rather than a view—changes to this signal will not propagate to
+  /// the returned signal and vice versa.
   `@override`
   Map<RK, RV> cast<RK, RV>() =>
       MapSignal<RK, RV>(untrackedValue.cast<RK, RV>());
docs-v2/src/content/docs/migration.mdx (1)

153-159: Consider adding examples for behavioral differences.

The behavioral differences section lists important changes but lacks migration guidance. Consider adding brief code examples, particularly for:

  • Handling the autoDispose default change (users upgrading may expect old behavior)
  • Safe LazySignal usage pattern (checking isInitialized before reads)
📝 Example additions
 ## 6) Behavioral differences
 
 - `SolidartConfig.autoDispose` default changed **true → false**
+  ```dart
+  // If you relied on v2's autoDispose=true default, explicitly configure:
+  SolidartConfig.devToolsEnabled = false;
+  SolidartConfig.autoDispose = true; // Restore v2 behavior
+  ```
 - `SolidartConfig.equals` removed
 - `previousValue` updates only after a tracked read
 - `LazySignal` throws if read before first assignment (check `isInitialized`)
+  ```dart
+  final lazy = LazySignal<int>();
+  if (lazy.isInitialized) {
+    print(lazy.value); // Safe
+  }
+  ```
packages/solidart/lib/src/resources/resource_state_extensions.dart (1)

46-52: Preserve the original stack trace when rethrowing errors.
throw r.error replaces the original stack trace, losing debugging context. Use Error.throwWithStackTrace() to preserve the stack trace captured in the error state.

♻️ Proposed fix
   T? get value => map(
     ready: (r) => r.value,
     // ignore: only_throw_errors
-    error: (r) => throw r.error,
+    error: (r) => Error.throwWithStackTrace(
+      r.error,
+      r.stackTrace ?? StackTrace.current,
+    ),
     loading: (_) => null,
   );
packages/solidart/test/until_test.dart (1)

9-24: Consider adding signal disposal for cleanup in pure Dart tests.

Per the coding guideline on memory management: in pure Dart code, signals should be manually disposed. Consider adding cleanup after each test to ensure proper resource release.

♻️ Optional: Add tearDown or explicit disposal
   group('until', () {
+    late Signal<int> signal;
+
+    tearDown(() {
+      signal.dispose();
+    });
+
     test('returns current value when condition already true', () async {
-      final signal = Signal(0);
+      signal = Signal(0);

       final result = signal.until((value) => value == 0);

       expect(await Future.value(result), 0);
     });

     test('completes when condition becomes true', () async {
-      final signal = Signal(0);
+      signal = Signal(0);

       final future = Future.value(signal.until((value) => value == 2));
       signal.value = 2;

       expect(await future, 2);
     });

@medz
Copy link
Collaborator Author

medz commented Jan 30, 2026

@coderabbitai Regenerate PR Summary & title

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 30, 2026

@medz I'll regenerate the PR summary and title for you.


🧠 Learnings used
Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/flutter_solidart/{lib,test}/**/*.dart : For Flutter Solidart changes, ensure widget tests cover `SignalBuilder`, `Provider`, and `Show` behaviors

Learnt from: medz
Repo: nank1ro/solidart PR: 167
File: docs-v2/src/content/docs/migration.mdx:160-169
Timestamp: 2026-01-30T18:39:37.038Z
Learning: In the solidart repository (packages/solidart, packages/flutter_solidart), the reactive collection types List/Set/MapSignal maintain the same naming between v2 and v3. Although they were briefly renamed to ReactiveList/Set/Map during early v3 development, they were renamed back to the v2 convention, so no migration is required for reactive collections between v2 and v3.

Learnt from: medz
Repo: nank1ro/solidart PR: 167
File: docs-v2/src/content/docs/migration.mdx:1-169
Timestamp: 2026-01-30T18:39:38.266Z
Learning: In the solidart repository (packages/solidart, packages/flutter_solidart), the reactive collection signal types are named `ListSignal`, `MapSignal`, and `SetSignal` in both v2 and v3. During early v3 development, they were temporarily renamed to `ReactiveList`, `ReactiveMap`, and `ReactiveSet`, but this was reverted to maintain consistency with v2 naming conventions.

Learnt from: medz
Repo: nank1ro/solidart PR: 167
File: packages/flutter_solidart/CHANGELOG.md:1-28
Timestamp: 2026-01-30T15:50:46.975Z
Learning: In the solidart repository (packages/flutter_solidart, packages/solidart), alien_signals dependency updates do not need to be documented in the CHANGELOG files, even for major version upgrades.

Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Ensure proper memory management: Signals auto-dispose in Flutter contexts; manually dispose in pure Dart code

Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/{solidart,flutter_solidart}/lib/**/*.dart : Use Signals for state, Effects for side effects, and Computed for derived values in library code

Learnt from: CR
Repo: nank1ro/solidart PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-10T15:36:53.390Z
Learning: Applies to packages/solidart/test/solidart_test.dart : After Signal changes, always run `packages/solidart/test/solidart_test.dart`
✅ Actions performed

Summary regeneration triggered.

@medz medz changed the title Solidart v3: full core rewrite with new API surface & ecosystem updates Solidart v3: Refactor v3 core API and align ecosystem packages Jan 30, 2026
@medz medz requested a review from nank1ro January 30, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] sometimes a computed doesn't autodispose Upgrade alien_signals to version 2.0 [BUG] -delayed effect callback caused incorrect dependencies.

2 participants