Repository navigation
Releases: ZtaMDev/Pulse-js
Release list
v0.3.0
v0.3.0 Universal Reactivity & DevTools 2.0
Release Date: February 8, 2026
v0.3.0 is the most significant update to Pulse.js since its inception. We've completely rebuilt the core engine to support Universal Proxy Reactivity, implemented a HMR-Stable Registry, and launched a brand new Agent-Client DevTools architecture.
Major Features
Proxy-Based Reactivity (pulse())
Pulse v3 moves away from explicit .set() and .get() calls for objects. The new pulse() function creates a deep reactive proxy that tracks property access automatically.
import { pulse } from "@pulse-js/core";
// Create a reactive object
const state = pulse({
count: 0,
user: { name: "Alice" },
increment() {
this.count++;
},
});
// Mutate directly - it's reactive!
state.count++;
state.user.name = "Bob";- Deep Guard Inspection: See full dependency trees, execution status, and detailed failure reasons directly in the UI.
Normalized GuardReason
Evaluation failures now guarantee a structured GuardReason object. Simple strings or thrown errors are automatically wrapped, ensuring you can always safely access .code and .message in your UI.
const { reason } = usePulse(myGuard);
console.log(reason.code); // Always available
console.log(reason.message); // Always availableNew Integrations
Astro Integration (@pulse-js/astro)
Pulse now native-supports Astro. Use Pulse state on the server during SSR and have it seamlessly hydrate on the client.
TanStack Query Bridge (@pulse-js/tanstack)
Easily bridge asynchronous remote state from TanStack Query into Pulse's reactive ecosystem using the new guardFromQuery selector.
📦 Package Versions
@pulse-js/core: 0.3.0@pulse-js/tools: 0.3.0@pulse-js/react: 0.3.0@pulse-js/vue: 0.3.0@pulse-js/svelte: 0.3.0@pulse-js/astro: 0.3.0@pulse-js/tanstack: 0.3.0
v0.2.2
v0.2.2 - Async GuardReason Integrity Fix
Release Date: January 19, 2026
This release addresses a critical data integrity issue where structured reasons passed to guardFail() were being lost in asynchronous guards, and normalizes all failure reasons to objects for a better developer experience.
Critical Fixes & DX Improvements
Async GuardReason Integrity & Normalization
In previous versions, reason could be a string or a GuardReason object, leading to complex TypeScript checks like typeof reason === 'object'.
v0.2.2 fixes the async loss bug and guarantees that reason is always a GuardReason object. Even simple string failures are now automatically wrapped as { code: 'ERROR', message: '...' }.
// ✅ Guaranteed object structure in v0.2.2
const { reason } = usePulse(isAdmin);
// No more "property does not exist on type string" errors!
console.log(reason?.code);
console.log(reason?.message);Critical Fixes
Async GuardReason Integrity
In previous versions, if a guard was asynchronous (returning a Promise), any structured object passed to guardFail() (e.g., { code: 'AUTH', message: '...' }) would be converted to a plain string in the Promise's catch handler.
v0.2.2 fixes this by ensuring the internal _pulseFail signal is respected in both synchronous and asynchronous evaluation paths.
// ✅ Now works perfectly in v0.2.2
const isAdmin = guard("admin-check", async () => {
const user = await fetchUser();
if (!user) {
return guardFail({
code: "AUTH",
message: "Authentication required",
});
}
return true;
});
// In your UI component:
const { reason } = usePulse(isAdmin);
console.log(reason?.code); // "AUTH" (previously would be undefined)Improvements
Cross-Package Version Synchronization
To ensure total consistency across the monorepo, all official adapters and tools have been bumped to align with Core v0.2.2.
- React (
@pulse-js/react): Now at v0.2.0, utilizing the latest Core version for stable async guard tracking. - Tools (
@pulse-js/tools): Now at v0.2.0, improved stability for structured reason inspection. - Documentation: New examples for structured error handling in guides.
📦 Package Versions
@pulse-js/core: 0.2.2@pulse-js/tools: 0.2.0@pulse-js/react: 0.2.0@pulse-js/vue: 0.1.4@pulse-js/svelte: 0.1.6
v0.2.1
v0.2.1 - Advanced Guard Features
Release Date: January 19, 2026
This release introduces powerful new guard composition utilities and enhanced debugging for complex dependency trees.
New Features
guard.map() Composition Helper
A new way to transform sources directly into guards with full semantic tracking. This replaces the legacy compute for most use cases.
const todos = source([{ done: false }, { done: true }]);
// Reactive guard derived from source
const doneCount = guard.map(todos, (list) => list.filter((t) => t.done).length);
// doneCount works as a full Guard<number>
console.log(doneCount.state()); // { status: "ok", value: 1 }InferGuardType<T> Type Helper
Extracting types from guards is now seamless with the new InferGuardType utility. Perfect for creating robust TypeScript interfaces.
import { guard, type InferGuardType } from "@pulse-js/core";
const authGuard = guard("auth", async () => fetchUser());
type AuthUser = InferGuardType<typeof authGuard>; // User | undefinedEnhanced Guard Debugging
The .explain() tree now includes the specific failure reasons for every sub-dependency, eliminating the guesswork in complex guard chains.
/* New explain() output for a failed guard: */
{
"name": "can-place-order",
"status": "fail",
"dependencies": [
{ "name": "has-items", "status": "ok" },
{
"name": "sufficient-balance",
"status": "fail",
"reason": "Balance is too low" // ✅ Detail now included
}
]
}Core (@pulse-js/core v0.2.1)
- guard.map: Native implementation for source transformations
- Improved explain(): Deep dependency trees now propagate reasons
Documentation
- Updated Guards Guide with composition and type helpers
- Updated Logic Composition with
guard.map - Refreshed API Reference
📦 Package Versions
@pulse-js/core: 0.2.1@pulse-js/tools: 0.1.9@pulse-js/react: 0.1.9@pulse-js/vue: 0.1.3@pulse-js/svelte: 0.1.5
v0.2.0
v0.2.0 - HMR Stability & Smart Cleanup
Release Date: January 19, 2026
This major release focuses on Hot Module Replacement (HMR) stability, introducing a professional mark-and-sweep cleanup system and enhanced DevTools with customizable shortcuts.
New Features
Smart HMR Cleanup System
Pulse now uses a mark-and-sweep garbage collection approach for HMR:
- Mark Phase: When HMR is detected, the generation counter increments and all units that re-register are marked as "alive"
- Sweep Phase: After 100ms, units from previous generations that weren't re-registered are automatically removed
- Result: Only truly deleted units are cleaned up; units that remain in your code are preserved
Example:
// Initial load (generation 0)
const count = source(0, { name: "count" });
const user = source(null, { name: "user" });
// After HMR (generation 1)
// - Both units re-register and are marked with generation 1
// - No cleanup needed, both units preserved
// If you delete 'user' from code and save
// - Only 'count' re-registers with generation 2
// - 'user' (still at generation 1) is swept after 100msNamed Units Requirement for DevTools
To ensure HMR stability, only units with explicit names are now visible in DevTools:
// ✅ Visible in DevTools
const count = source(0, { name: "count" });
const isEven = guard("is-even", () => count() % 2 === 0);
// ❌ Not visible in DevTools (but works perfectly)
const temp = source(0);
const check = guard(() => temp() > 5);Why? Unnamed units create new object instances on every HMR reload, making stable tracking impossible. This is a fundamental JavaScript/HMR limitation shared by all state management libraries (Redux, Zustand, Jotai, etc.).
Customizable DevTools Shortcuts
The keyboard shortcut for toggling DevTools is now fully customizable:
<!-- Default -->
<pulse-inspector></pulse-inspector>
<!-- Shortcut: Ctrl+M -->
<!-- Custom -->
<pulse-inspector shortcut="Ctrl+P"></pulse-inspector>
<pulse-inspector shortcut="Ctrl+Shift+D"></pulse-inspector>
<pulse-inspector shortcut="Alt+D"></pulse-inspector>React:
import { PulseDevTools } from "@pulse-js/react/devtools";
<PulseDevTools shortcut="Ctrl+Shift+P" />;DevTools Refresh Button
Added a refresh button (🔄) to the DevTools header for manual registry refresh.
Improvements
Core (@pulse-js/core v0.2.0)
- Mark-and-Sweep Cleanup: Intelligent HMR cleanup that only removes truly deleted units
- Generation Tracking: Each unit is marked with a generation number for precise lifecycle management
- Improved Registry: Simplified registration logic with better HMR detection
- Performance: Eliminated unnecessary stack trace parsing overhead
Tools (@pulse-js/tools v0.1.8)
- Customizable Shortcuts: Support for any key combination via
shortcutattribute - Refresh Button: Manual refresh capability for DevTools
- Improved Tooltips: Dynamic tooltip showing current shortcut
- Named Units Only: Cleaner, more stable unit tracking
Framework Integrations
React (@pulse-js/react v0.1.8)
- Updated to use core 0.2.0 and tools 0.1.8
- Shortcut prop support in
PulseDevToolscomponent
Vue (@pulse-js/vue v0.1.3)
- Updated to use core 0.2.0 and tools 0.1.8
Svelte (@pulse-js/svelte v0.1.3)
- Updated to use core 0.2.0
Documentation
- Updated DevTools Guide with named units requirement
- Added examples of customizable shortcuts
- Removed non-existent
themeprop from documentation - Clarified HMR behavior and limitations
Migration Guide
From v0.1.x to v0.2.0
Breaking Change: Named Units for DevTools Visibility
Unnamed sources and guards will no longer appear in DevTools. To see them:
// Before (won't appear in DevTools)
const count = source(0);
const isValid = guard(() => count() > 0);
// After (visible in DevTools)
const count = source(0, { name: "count" });
const isValid = guard("is-valid", () => count() > 0);Note: This only affects DevTools visibility. Unnamed units continue to work perfectly in your application.
Shortcut Changes
The default shortcut has changed from Ctrl+Shift+P to Ctrl+M. If you prefer the old shortcut:
<pulse-inspector shortcut="Ctrl+Shift+P"></pulse-inspector>Testing
- All 33 tests passing
- Verified HMR stability with mark-and-sweep cleanup
- Tested customizable shortcuts across different key combinations
- Validated DevTools refresh functionality
📦 Package Versions
@pulse-js/core: 0.2.0@pulse-js/tools: 0.1.8@pulse-js/react: 0.1.8@pulse-js/vue: 0.1.3@pulse-js/svelte: 0.1.3
v0.1.9
v0.1.9 HMR Stability & Svelte 5 Runes Integration
Release Date: January 17, 2026
This release brings major improvements to Hot Module Replacement (HMR) stability and completes the Svelte 5 Runes integration, making Pulse more robust for modern development workflows.
New Features
HMR-Safe Auto-Naming System
Pulse now automatically assigns stable, location-based names to unnamed sources and guards, preventing duplicates during HMR reloads.
How it works:
- Unnamed units receive auto-generated names based on their source location (e.g.,
source@react-example:7) - Names remain stable across HMR reloads, even when code changes
- Automatic cleanup of stale units after HMR using generation-based tracking
Example:
// Before: Would duplicate on HMR
const count = source(0);
// Now: Automatically named as "source@MyComponent:5"
// Stable across HMR reloadsGeneration-Based Cleanup
The registry now tracks unit "generations" and automatically removes orphaned units after HMR:
- Each HMR reload increments the generation counter
- Units from previous generations are cleaned up after 100ms
- Console logs show cleanup activity:
[Pulse] Cleaned up X stale units after HMR
Performance Optimizations
- Stack Trace Caching: Auto-naming now uses a cache to avoid repeated stack trace parsing
- Lazy Evaluation: Names are only generated when needed, reducing overhead
- 10k sources test: Maintains performance (~2.3s) with minimal production overhead
Svelte 5 Runes Integration
Complete Runes Support
@pulse-js/svelte now provides first-class support for Svelte 5's Runes system:
Native Reactivity:
<script lang="ts">
import { source } from "@pulse-js/core";
import { usePulse } from "@pulse-js/svelte";
const countSource = source(0);
const count = usePulse(countSource);
</script>
<button onclick={() => countSource.update(n => n + 1)}>
Count: {count.value}
</button>Guard Integration:
<script lang="ts">
import { useGuard } from "@pulse-js/svelte";
import { authGuard } from "./logic";
const state = useGuard(authGuard);
</script>
{#if state.status === "ok"}
<p>Welcome, {state.value.name}</p>
{:else if state.status === "fail"}
<p style="color: red">Error: {state.reason}</p>
{/if}Improved Type Inference
- Reordered
usePulseoverloads to prioritizeGuard<T>overSource<T> - Fixed TypeScript errors like
Property 'status' does not exist - Adopted Svelte 5 prop patterns to eliminate
state_referenced_locallywarnings
Package Resolution Fixes
- Updated
package.jsonexports to correctly map Svelte 5 Runes entry points - Added
optimizeDeps.excludeguidance for Vite configuration - Fixed
.svelte.jsoutput alignment with tsup build process
Improvements
Core (@pulse-js/core v0.1.9)
- Global Singleton Registry: Uses
globalThisto persist across HMR reloads - Auto-Naming Cache: Reduces stack trace parsing overhead
- SSR Hydration: Restored
_hydratemethod for proper server-side rendering support
Tools (@pulse-js/tools v0.1.7)
- Improved Display: Auto-generated names now show in DevTools with clean format
- Better Tracking: Uses stable IDs for editing unnamed sources
- HMR Awareness: DevTools correctly updates when units are replaced during HMR
Framework Integrations
React (@pulse-js/react v0.1.7)
- Updated dependencies to use latest core and tools
Vue (@pulse-js/vue v0.1.2)
- Updated dependencies to use latest core and tools
Svelte (@pulse-js/svelte v0.1.2)
- Complete Svelte 5 Runes integration
- Backward compatibility with Svelte 4 via
usePulseStore - Proxy-based Guards for stable object identity
- Updated documentation with Runes examples
Bug Fixes
- Fixed SSR hydration test failure by restoring
_hydratemethod - Resolved package resolution errors in Svelte 5 projects
- Fixed TypeScript inference issues in
usePulseoverloads - Fixed HMR duplication when adding/removing names from sources
Documentation
- Updated Svelte Integration guide with Runes examples
- Added Vite configuration instructions for Svelte 5
- Documented auto-naming behavior and HMR cleanup
- Added examples for both Runes and Store APIs
Migration Guide
For Svelte users:
If you're using Svelte 5, update your vite.config.ts:
import { defineConfig } from "vite";
export default defineConfig({
resolve: {
conditions: ["browser", "module", "jsnext:main", "jsnext"],
},
optimizeDeps: {
exclude: ["@pulse-js/svelte"],
},
});Unnamed sources and guards will now automatically receive location-based names. This is transparent and requires no code changes, but you'll see cleaner names in DevTools (e.g., source@MyComponent:7 instead of random IDs).
v0.1.8
v0.1.8 (React Compatibility & Cyclic Fixes)
This release significantly improves React ergonomics and fixes critical bugs in the cyclic dependency detection logic.
Core Improvements (@pulse-js/core 0.1.8)
- Fixed Cyclic Dependency Detection: The detection logic has been completely overhauled. It now correctly identifies true cycles (A -> A) without false positives for nested guard compositions (e.g.,
guard.allreading children). GuardReasonInterface: TheGuardReasoninterface now includes atoString()signature. This ensures that reason objects can be safely converted to strings in all environments.
React Integration (@pulse-js/react 0.1.5)
formatReasonHelper: A new utility function to easily render guard failure reasons in JSX.import { formatReason } from "@pulse-js/react"; // ... <p>{formatReason(reason)}</p>;
- Improved Types: Internal improvements to how types are exported to prevent circular dependencies during builds.
DevTools 2.0 (@pulse-js/tools 0.1.5)
- Tabbed Interface: New split view with "Inspector" (list) and "Pulse Tree" (dependency graph).
- Pulse Tree Visualization: Recursive tree view showing the entire dependency graph of your guards.
- Expand/Collapse nodes to trace logic flows.
- View status and failure reasons at every level of the tree.
- Editable Sources: Click on any Source value in the inspector to edit it directly. Supports JSON syntax for objects/arrays.
- Enhanced UI: Improved "Pill" design, better colors, and drag-and-drop mechanics.
Pulse v0.1.7
v0.1.7 (Enterprise Reactivity & Cycle Detection)
This release focuses on hardening the core engine for large-scale applications with improved failure tracking, cyclic dependency detection, and enterprise-grade metadata.
Core Improvements (@pulse-js/core 0.1.7)
- Cyclic Dependency Detection: Added a robust stack-based detection mechanism that catches infinite reactive loops (A -> B -> A) and reports them as descriptive failure reasons instead of causing stack overflows.
- Persistent Dependency Insights: The
.explain()graph now persists even after a failure. Previously, failing early would clear downstream dependencies; now it remembers the last known graph for better debugging. - Structured Reason Metadata: Introduced the
GuardReasoninterface. Evaluators can now throw objects withcode,message, andmetato provide rich error context to the UI. - Semantic State Preservation: When a failed Guard re-evaluates, its
lastReasonis preserved whilepending, preventing UI flickering and allowing users to see the previous error while the next attempt is in progress. - Flexible Pending State: Returning
undefinedfrom a Guard evaluator now explicitly marks it aspending, simplifying data fetching and "not ready" patterns.
DevTools Improvements (@pulse-js/tools 0.1.4)
- Metadata Rendering: The inspector now renders structured failure reasons, including error codes and JSON metadata snippets.
- Evaluation State Tracking: Visual indicators for
lastReasonwhen a guard is in apendingstate after a failure. - Dependency Status: Dependency lists now show the status of each dependent guard for faster troubleshooting.
React Integration (@pulse-js/react 0.1.4)
- Updated Dependencies: Bumped to use
@pulse-js/core@0.1.7and@pulse-js/tools@0.1.4.
Pulse v0.1.1
v0.1.1 (Initial Base Release)
We are excited to announce the first public release of Pulse, a semantic reactivity system for modern applications. This release establishes the core primitives and ecosystem under the new @pulse-js namespace.
📦 Packages
@pulse-js/core: The reactivity engine.@pulse-js/react: React 18+ integration hooks.@pulse-js/tools: Visual debugging suite (formerly devtools).
Features
Core Reactivity
- Sources: Primitive containers for state values.
- Guards: First-class "Conditions" that track status (
ok,fail,pending) and failure reasons. - Composition: Logic helpers
guard.all,guard.any,guard.not, andguard.compute. - Async Support: Native Promise handling for async guards.
- SSR: Isomorphic
evaluate(server) andhydrate(client) methods.
React Integration
usePulseHook: Universal hook for both Sources and Guards.- Concurrent Mode: Built on
useSyncExternalStorefor safe concurrent updates. - Smart Re-renders: Components only update when semantic state changes.
Developer Experience
- Pulse Tools: A zero-config, draggable overlay for inspecting the reactive graph.
- Type Safety: Full TypeScript support with inferred types.
Getting Started
npm install @pulse-js/core @pulse-js/react @pulse-js/tools