## 🔶⚡ intentx-svelte

[![NPM](https://img.shields.io/npm/v/intentx-svelte.svg)](https://www.npmjs.com/package/intentx-svelte) ![Downloads](https://img.shields.io/npm/dt/intentx-svelte.svg)

<a href="https://codesandbox.io/p/devbox/clever-bogdan-ct75fx" target="_blank">LIVE EXAMPLE</a>

---

`intentx-svelte` is an architectural layer for Svelte. It enforces a strict separation between:

- Business Logic (deterministic runtime)
- UI Rendering (Svelte reactivity)

It is **not a store library.**

> It is a bridge between deterministic logic and Svelte’s reactive UI.

---

## ✨ Why intentx-svelte?

Use it when your UI starts to feel like business logic.

✅ Complex async workflows  
✅ Intent-based architecture  
✅ Microfrontend communication  
✅ Testable business logic  
✅ Cross-runtime reuse (Node / SSR / workers)

Avoid it when:

❌ You only need `$:` reactive statements  
❌ Your state is purely local UI  
❌ You want reducer-style state  

---

## 🤔 Why not just Svelte stores?

Svelte stores are excellent for reactivity.

But they do not provide:

- Intent routing
- Cross-logic orchestration
- Deterministic runtime snapshotting
- Cross-framework runtime reuse
- Explicit business boundaries

Stores solve reactivity.

intentx solves orchestration.

---

## 🧠  Mental Model

```txt
UI / HTTP / Queue / Cron
        ↓
  intentx-runtime
        ↓
Fine-grained reactivity updates UI
```

Core principle:

> Intent is the only mutation entry point.
> The [runtime](https://www.npmjs.com/package/intentx-runtime) owns behavior. UI only triggers intent.

---

## 📦 Installation

```bash
npm install intentx-svelte
```

---

## 🧩 Core Logic (Framework-Agnostic)

Define logic outside components:

```ts
import { createLogic } from "intentx-svelte"

export const counterLogic = createLogic({
  name: "counter",

  state: {
    count: 0
  },

  computed: {
    double: ({ state }) => state.count * 2
  },

  intents: (bus) => {
    bus.on("inc", ({ setState }) => {
      setState((s) => {
        s.count++;
      });
    });
  },

  actions: {
    inc({ emit }) {
      return () => emit("inc");
    },
  },
})

```

Logic is:

- Serializable
- Deterministic
- Testable without UI
- Reusable across runtimes

---

## 🚀 Usage

```ts
// counter.ts
import { useLogic } from "intentx-svelte"
import { counterLogic } from "./counter.logic"

export const counter = useLogic(counterLogic)
```

```svelte
<script>
  import { counter } from "./counter"
</script>

<button on:click={counter.actions.inc}>
  {$counter.store.count}
</button>

<p>Double: {$counter.store.double}</p>
```

No wrapper components.  
No magic subscriptions.  

UI only consumes state.

---

## 📦 What `useLogic` Returns

```ts
const counter = useLogic(counterLogic)
```

```ts
{
  runtime,   // ⚙ LogicRuntime instance
  store,     // 🗂 merged state + computed (Svelte store)
  state,     // 🪞 alias of store
  actions,   // 🎯 logic actions
  emit       // 📡 emit intent
}
```

🔥 Important

- `store` is readonly
- Mutations must go through actions
- Svelte reactivity remains untouched

---

## 📡  Multiple Logic (Bus)

Each `logic` instance is isolated by default.

To enable communication between runtimes, you can share an Intent Bus.

---

### 1️⃣ Scoped Shared Bus (Recommended)

```ts
import { useLogic } from "intentx-react"

// ✅ Same scope → shared bus
useLogic(logic, {
  scope: "dashboard",
  sharedBus: true
})

// ❌ Different scope → different bus
useLogic(logic, {
  scope: "settings",
  sharedBus: true
})
```

<b>How it works</b>

When sharedBus: true is enabled:

- A singleton bus is created per scope

- Same scope → same bus instance

- Different scope → different bus

- No global leakage

If no `scope` is provided:

```ts
useLogic(logic, {
  sharedBus: true
})
```

→ uses a default global scope bus.

---

### 2️⃣ Custom Bus (Advanced / Cross-Scope)

```ts
import { createIntentBus } from "intentx-svelte"

const bus = createIntentBus()

useLogic(logicA, { bus })
useLogic(logicB, { bus })

```

<b>Behavior</b>

- Full cross-scope communication
- Manual orchestration control
- Suitable for:
  - Microfrontend
  - App-wide coordination
  - Complex workflow systems

### 🔍 Behavior Comparison

| Mode                 | Isolation    | Scope-aware | Cross-scope  | Recommended           |
| -------------------- | -----------  | ----------- | ------------ | --------------------- |
| Default (no options) | ✅ Full      | ❌           | ❌           | Small/local logic     |
| `sharedBus: true`    | ❌ Per scope | ✅           | ❌           | Modular apps          |
| Custom `bus`         | ❌ Manual    | ❌           | ✅           | Advanced architecture |

### 🎯 Recommendation

✅ Use sharedBus for modular communication.  
✅ Use custom bus for orchestration layer.  
🚫 Avoid global single bus without scope in large apps.  

---

## 🧩 Context API

Provide logic via Svelte context:

```ts
import { setLogicContext, useLogicContext } from "intentx-svelte"
import { counterLogic } from "./counter.logic"
```

Provider:

```svelte
<script>
  setLogicContext("counter", counterLogic)
</script>

<slot />
```

Consume:

```ts
const counter = useLogicContext("counter")
```

---

## 🌍 SSR

- Runtime created during SSR
- Deterministic snapshot
- Hydration-safe
- No fake empty stores
- Server snapshot serializable
- Client rehydrates from deterministic state

Works with:

- SvelteKit
- Node SSR
- Edge runtimes

---

## 🧪 Testability Upgrade

No Svelte required:

```ts
const runtime = counterLogic.create()

runtime.actions.inc()
expect(runtime.state.count).toBe(1)
```

No DOM.  
No component mounting.  
Pure deterministic logic.

That is the real split.

---

## 🔍 Comparison

This is not about “better”.
It’s about solving different layers of the architecture.

| Problem / Responsibility         | Svelte Only | intentx-svelte |
|----------------------------------|-------------|----------------|
| Local UI state                   | ✅ Perfect  | ❌ Overkill    |
| Simple derived values            | ✅ `$:`     | ❌ Unnecessary |
| Complex async workflows          | ⚠️ Manual   | ✅ Structured  |
| Cross-component orchestration    | ⚠️ Implicit | ✅ Explicit    |
| Cross-runtime reuse (Node/SSR)   | ❌          | ✅             |
| Deterministic snapshotting       | ❌          | ✅             |
| Intent-based communication       | ❌          | ✅             |
| Microfrontend signaling          | ❌          | ✅             |

Svelte handles reactivity.

intentx handles orchestration.

---

## 🎯 Philosophy

Rendering is reactive.

Business logic should be deterministic.

intentx-svelte ensures they never mix.

---

## 📜 License

MIT