@pulse-js/core 0.2.1 → 0.3.0
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/README.md +43 -118
- package/dist/index.cjs +346 -62
- package/dist/index.d.cts +167 -31
- package/dist/index.d.ts +167 -31
- package/dist/index.js +338 -61
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,172 +1,97 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
|
|
3
2
|
<img width="200" height="200" alt="logo" src="https://raw.githubusercontent.com/ZtaMDev/Pulse/refs/heads/main/pulse.svg" />
|
|
4
3
|
|
|
5
|
-
# Pulse-JS
|
|
4
|
+
# Pulse-JS v2.0
|
|
6
5
|
|
|
7
|
-
[](https://www.npmjs.com/package/@pulse-js/core)
|
|
6
|
+
[](https://www.npmjs.com/package/@pulse-js/core)
|
|
8
7
|
|
|
9
|
-
> A semantic reactivity system for modern applications. Separate reactive
|
|
8
|
+
> A semantic reactivity system for modern applications. Separate reactive state (pulse) from business conditions (guards) with a declarative, composable, and proxied approach.
|
|
10
9
|
|
|
11
10
|
Official [Documentation](https://pulse-js.vercel.app)
|
|
12
11
|
|
|
13
|
-
Pulse differs from traditional signals or state managers by treating `Conditions` as first-class citizens. Instead of embedding complex boolean logic inside components
|
|
12
|
+
Pulse differs from traditional signals or state managers by treating `Conditions` as first-class citizens. Instead of embedding complex boolean logic inside components, you define **Semantic Guards** that are observed, composed, and debugged independently.
|
|
14
13
|
|
|
15
14
|
</div>
|
|
16
15
|
|
|
17
16
|
## Installation
|
|
18
17
|
|
|
19
|
-
```bash
|
|
20
|
-
npm install @pulse-js/core @pulse-js/tools
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### or
|
|
24
|
-
|
|
25
18
|
```bash
|
|
26
19
|
bun add @pulse-js/core @pulse-js/tools
|
|
27
20
|
```
|
|
28
21
|
|
|
29
|
-
Pulse works with React via adapters like `@pulse-js/react`.
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
bun add @pulse-js/react
|
|
33
|
-
```
|
|
34
|
-
|
|
35
22
|
## Core Concepts
|
|
36
23
|
|
|
37
|
-
###
|
|
24
|
+
### Pulse Objects (Universal Reactivity)
|
|
38
25
|
|
|
39
|
-
|
|
26
|
+
`pulse()` creates a deep reactive Proxy. Use it for complex objects and arrays. Track property access automatically and mutate state directly.
|
|
40
27
|
|
|
41
28
|
```typescript
|
|
42
|
-
import {
|
|
29
|
+
import { pulse } from "@pulse-js/core";
|
|
30
|
+
|
|
31
|
+
const user = pulse({
|
|
32
|
+
name: "Alice",
|
|
33
|
+
role: "admin",
|
|
34
|
+
increment() {
|
|
35
|
+
this.stats.clicks++;
|
|
36
|
+
},
|
|
37
|
+
stats: { clicks: 0 },
|
|
38
|
+
});
|
|
43
39
|
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
// Mutate directly - it's reactive!
|
|
41
|
+
user.name = "Bob";
|
|
42
|
+
user.increment();
|
|
43
|
+
```
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
console.log(user());
|
|
45
|
+
### Sources (Primitive Records)
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
user.set({ name: "Bob", id: 1 });
|
|
47
|
+
Sources are primitive containers for your application state. They hold values and notify dependents when those values change.
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
```typescript
|
|
50
|
+
import { source } from "@pulse-js/core";
|
|
51
|
+
const count = source(0);
|
|
52
|
+
count.set(5);
|
|
56
53
|
```
|
|
57
54
|
|
|
58
55
|
### Guards (Semantic Logic)
|
|
59
56
|
|
|
60
|
-
Guards represent business rules or derivations.
|
|
57
|
+
Guards represent business rules or derivations. They act as high-performance **Selectors** with built-in dependency tracking and rich failure context.
|
|
61
58
|
|
|
62
59
|
```typescript
|
|
63
60
|
import { guard } from "@pulse-js/core";
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
const isAdmin = guard("is-admin", () => {
|
|
62
|
+
const isAuthorized = guard("auth-check", async () => {
|
|
67
63
|
const u = user();
|
|
68
|
-
if (u
|
|
69
|
-
return true;
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// Guards can be checked explicitly
|
|
73
|
-
if (isAdmin.ok()) {
|
|
74
|
-
// Grant access
|
|
75
|
-
} else {
|
|
76
|
-
console.log(isAdmin.reason()); // e.g. "is-admin failed"
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Computed Values
|
|
81
|
-
|
|
82
|
-
You can derive new data from sources or other guards using `compute`. It works like a memoized transformation that automatically re-evaluates when dependencies change.
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
import { compute } from "@pulse-js/core";
|
|
86
|
-
|
|
87
|
-
const fullName = compute("full-name", [firstName, lastName], (first, last) => {
|
|
88
|
-
return `${first} ${last}`;
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Async Guards & Race Control
|
|
93
|
-
|
|
94
|
-
Pulse handles asynchronous logic natively. Guards can return Promises, and their status will automatically transition from `pending` to `ok` or `fail`.
|
|
95
|
-
|
|
96
|
-
Pulse implements internal **runId versioning** to automatically cancel stale async evaluations if the underlying sources change multiple times before a promise resolves, preventing race conditions.
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
const isServerOnline = guard("check-server", async () => {
|
|
100
|
-
const response = await fetch("/health");
|
|
101
|
-
if (!response.ok) throw new Error("Server unreachable");
|
|
64
|
+
if (!u) return false;
|
|
102
65
|
return true;
|
|
103
66
|
});
|
|
104
67
|
```
|
|
105
68
|
|
|
106
69
|
### Explanable Guards
|
|
107
70
|
|
|
108
|
-
|
|
71
|
+
Get a structured tree of the current status, failure reasons, and the status of all direct dependencies.
|
|
109
72
|
|
|
110
73
|
```ts
|
|
111
74
|
const explanation = canCheckout.explain();
|
|
112
|
-
|
|
113
|
-
// { status: 'fail', reason: 'auth failed', dependencies: [...] }
|
|
75
|
+
// { status: 'fail', reason: { code: 'AUTH', message: '...' }, dependencies: [...] }
|
|
114
76
|
```
|
|
115
77
|
|
|
116
|
-
## Server-Side Rendering (SSR)
|
|
117
|
-
|
|
118
|
-
Pulse is designed with SSR in mind. It supports isomorphic rendering where async guards can be evaluated on the server, their state serialized, and then hydrated on the client.
|
|
119
|
-
|
|
120
|
-
### Server Side
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
import { evaluate } from "@pulse-js/core";
|
|
124
|
-
|
|
125
|
-
// 1. Evaluate critical guards on the server
|
|
126
|
-
const hydrationState = await evaluate([isUserAuthenticated, appSettings]);
|
|
127
|
-
|
|
128
|
-
// 2. Serialize this state into your HTML
|
|
129
|
-
const html = `
|
|
130
|
-
<script>window.__PULSE_STATE__ = ${JSON.stringify(hydrationState)}</script>
|
|
131
|
-
`;
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Client Side (Hydration)
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import { hydrate } from "@pulse-js/core";
|
|
138
|
-
|
|
139
|
-
// 1. Hydrate before rendering
|
|
140
|
-
hydrate(window.__PULSE_STATE__);
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Mental Model
|
|
144
|
-
|
|
145
|
-
Compare Pulse primitives:
|
|
146
|
-
|
|
147
|
-
| Concept | Can be async | Has state | Observable | Purpose |
|
|
148
|
-
| :---------- | :----------: | :-------: | :--------: | :----------------------------------- |
|
|
149
|
-
| **Source** | ❌ | ❌ | ✅ | Reactive data (facts). |
|
|
150
|
-
| **Guard** | ✅ | ✅ | ✅ | Business rules (conditioned truths). |
|
|
151
|
-
| **Compute** | ❌ | ❌ | ✅ | Pure transformations (derivations). |
|
|
152
|
-
|
|
153
78
|
## Framework Integrations
|
|
154
79
|
|
|
155
|
-
Pulse provides official adapters for major frameworks
|
|
80
|
+
Pulse provides official adapters for all major frameworks.
|
|
156
81
|
|
|
157
|
-
| Framework
|
|
158
|
-
|
|
|
159
|
-
| **
|
|
160
|
-
| **
|
|
161
|
-
| **
|
|
82
|
+
| Framework | Package | Status |
|
|
83
|
+
| :----------- | :------------------- | :----- |
|
|
84
|
+
| **Astro** | `@pulse-js/astro` | NEW |
|
|
85
|
+
| **React** | `@pulse-js/react` | Stable |
|
|
86
|
+
| **Vue** | `@pulse-js/vue` | Stable |
|
|
87
|
+
| **Svelte** | `@pulse-js/svelte` | Stable |
|
|
88
|
+
| **TanStack** | `@pulse-js/tanstack` | NEW |
|
|
162
89
|
|
|
163
90
|
## Developer Tools
|
|
164
91
|
|
|
165
|
-
Debug your reactive graph with **[Pulse Tools](https://pulse-js.vercel.app/guides/devtools/)**, a
|
|
166
|
-
|
|
167
|
-
### Features
|
|
92
|
+
Debug your reactive graph with **[Pulse Tools](https://pulse-js.vercel.app/guides/devtools/)**, a decoupled Agent-Client inspector.
|
|
168
93
|
|
|
169
|
-
- **
|
|
170
|
-
- **
|
|
171
|
-
- **
|
|
94
|
+
- **Agent-Client Architecture**: Isolated UI that doesn't restart your app.
|
|
95
|
+
- **Dependency Graph**: Visualize how your guards are connected.
|
|
96
|
+
- **Glassmorphism UI**: A premium, draggable development experience.
|
|
172
97
|
- **Zero Config**: Works out of the box with `@pulse-js/tools`.
|