Skip to content

v0.1.9

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.


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 reloads

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
  • 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

@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}
  • Reordered usePulse overloads to prioritize Guard<T> over Source<T>
  • Fixed TypeScript errors like Property 'status' does not exist
  • Adopted Svelte 5 prop patterns to eliminate state_referenced_locally warnings
  • Updated package.json exports to correctly map Svelte 5 Runes entry points
  • Added optimizeDeps.exclude guidance for Vite configuration
  • Fixed .svelte.js output alignment with tsup build process

  • Global Singleton Registry: Uses globalThis to persist across HMR reloads
  • Auto-Naming Cache: Reduces stack trace parsing overhead
  • SSR Hydration: Restored _hydrate method for proper server-side rendering support
  • 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

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

  • Fixed SSR hydration test failure by restoring _hydrate method
  • Resolved package resolution errors in Svelte 5 projects
  • Fixed TypeScript inference issues in usePulse overloads
  • Fixed HMR duplication when adding/removing names from sources

  • 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

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).