logic-runtime-react-z 3.1.1 → 3.1.3
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 +198 -228
- package/build/core/effect.d.ts +4 -0
- package/build/index.cjs.js +1 -1
- package/build/index.d.ts +1 -5
- package/build/index.esm.js +1 -1
- package/build/logic/createLogic.d.ts +15 -10
- package/build/react/useLogic.d.ts +6 -4
- package/build/react/withLogic.d.ts +2 -1
- package/package.json +7 -12
- package/build/logic/composeLogic.d.ts +0 -21
- package/build/react/useActions.d.ts +0 -4
- package/build/react/useComputed.d.ts +0 -6
- package/build/react/useLogicSelector.d.ts +0 -2
- package/build/react/useRuntime.d.ts +0 -5
package/README.md
CHANGED
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
<a href="https://codesandbox.io/p/sandbox/jnd992" target="_blank">LIVE EXAMPLE</a>
|
|
6
6
|
|
|
7
|
-
**Intent-
|
|
7
|
+
**Intent-First Business Logic Runtime.**. React is a view layer. Business logic lives elsewhere.
|
|
8
8
|
|
|
9
|
-
A headless, deterministic, intent-driven runtime for frontend
|
|
10
|
-
React components stay pure. Business logic is fully testable, replayable, and framework-agnostic.
|
|
9
|
+
A headless, deterministic, intent-driven runtime for frontend and backend systems.
|
|
11
10
|
|
|
12
|
-
> **Intent is the only entry point.**
|
|
13
|
-
> **React is optional
|
|
11
|
+
> **Intent is the only entry point. Logic is deterministic.**
|
|
12
|
+
> **React is optional** — `createLogic` is the product; everything else is an adapter.
|
|
14
13
|
|
|
15
14
|
---
|
|
16
15
|
|
|
@@ -59,7 +58,7 @@ npm install logic-runtime-react-z
|
|
|
59
58
|
import { createLogic } from "logic-runtime-react-z"
|
|
60
59
|
|
|
61
60
|
const counterLogic = createLogic({
|
|
62
|
-
state: { count: 0 },
|
|
61
|
+
state: { count: 0, loading: false },
|
|
63
62
|
|
|
64
63
|
intents: bus => {
|
|
65
64
|
bus.on("inc", ({ setState }) => {
|
|
@@ -73,6 +72,23 @@ const counterLogic = createLogic({
|
|
|
73
72
|
s.count += payload
|
|
74
73
|
})
|
|
75
74
|
})
|
|
75
|
+
|
|
76
|
+
bus.on("dec", ({ setState }) => {
|
|
77
|
+
setState(s => {
|
|
78
|
+
s.count--
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
bus.on("asyncInc", async ({ setState }) => {
|
|
83
|
+
setState(s => { s.loading = true })
|
|
84
|
+
|
|
85
|
+
await new Promise(r => setTimeout(r, 1000))
|
|
86
|
+
|
|
87
|
+
setState(s => {
|
|
88
|
+
s.count++
|
|
89
|
+
s.loading = false
|
|
90
|
+
})
|
|
91
|
+
})
|
|
76
92
|
},
|
|
77
93
|
})
|
|
78
94
|
|
|
@@ -111,124 +127,111 @@ computed: {
|
|
|
111
127
|
- Reading `state.count` automatically tracks dependencies.
|
|
112
128
|
- Computed values are cached and only re-evaluated when tracked dependencies change.
|
|
113
129
|
|
|
130
|
+
|
|
114
131
|
---
|
|
115
132
|
|
|
116
|
-
## ⚛️ React Integration
|
|
133
|
+
## ⚛️ React Integration
|
|
117
134
|
|
|
118
|
-
|
|
135
|
+
React is a thin adapter.
|
|
119
136
|
|
|
120
|
-
|
|
121
|
-
// counter.logic.ts
|
|
122
|
-
import { createLogic, effect } from "logic-runtime-react-z"
|
|
137
|
+
You have **2 integration styles**:
|
|
123
138
|
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
- `withLogic` → Recommended
|
|
140
|
+
- `useLogic` → Direct hook usage
|
|
126
141
|
|
|
127
|
-
|
|
128
|
-
count: 1,
|
|
129
|
-
loading: false,
|
|
130
|
-
},
|
|
142
|
+
#### 🧩 Option 1 — withLogic (Recommended)
|
|
131
143
|
|
|
132
|
-
|
|
133
|
-
double: ({ state }) => state.count * 2,
|
|
134
|
-
triple: ({ state }) => state.count * 3,
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
intents: bus => {
|
|
138
|
-
bus.on("inc", ({ setState }) => {
|
|
139
|
-
setState(s => {
|
|
140
|
-
s.count++
|
|
141
|
-
})
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
bus.on<number>("add", ({ payload, setState }) => {
|
|
145
|
-
setState(s => {
|
|
146
|
-
s.count += payload
|
|
147
|
-
})
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
bus.on<number>("inc-async", async ({ payload, setState }) => {
|
|
151
|
-
setState(s => {
|
|
152
|
-
s.loading = true
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
await new Promise(r => setTimeout(r, 1000))
|
|
144
|
+
Keeps view pure and declarative.
|
|
156
145
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
})
|
|
161
|
-
})
|
|
146
|
+
```tsx
|
|
147
|
+
import { withLogic, LogicViewProps } from "logic-runtime-react-z"
|
|
148
|
+
import { counterLogic } from "./counter.logic"
|
|
162
149
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"inc-async",
|
|
166
|
-
effect(async ({ payload }) => {
|
|
167
|
-
console.log("effect run:", payload)
|
|
168
|
-
}).takeLatest()
|
|
169
|
-
)
|
|
170
|
-
},
|
|
150
|
+
type CounterInjected =
|
|
151
|
+
LogicViewProps<typeof counterLogic>
|
|
171
152
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
153
|
+
const CounterView = ({ state, computed, intent }: LogicViewProps) => {
|
|
154
|
+
return (
|
|
155
|
+
<div>
|
|
156
|
+
<h2>Count: {state.count}</h2>
|
|
157
|
+
<p>Double: {computed.double}</p>
|
|
158
|
+
<p>Triple: {computed.triple}</p>
|
|
159
|
+
|
|
160
|
+
<button onClick={() => intent("inc")}>+</button>
|
|
161
|
+
<button onClick={() => intent("dec")}>-</button>
|
|
162
|
+
<button onClick={() => intent("asyncInc")}>
|
|
163
|
+
{state.loading ? "Loading..." : "Async +"}
|
|
164
|
+
</button>
|
|
165
|
+
</div>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
176
168
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
169
|
+
// export default withLogic(counterLogic)(CounterView)
|
|
170
|
+
export const CounterPage = withLogic(counterLogic, CounterView)
|
|
171
|
+
```
|
|
180
172
|
|
|
181
|
-
|
|
182
|
-
return (n: number) => emit("inc-async", n)
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
})
|
|
173
|
+
<b> Why this is recommended?</b>
|
|
186
174
|
|
|
187
|
-
|
|
175
|
+
- View is fully testable
|
|
176
|
+
- No hooks inside view
|
|
177
|
+
- Logic can be reused outside React
|
|
178
|
+
- Clear separation of concerns
|
|
188
179
|
|
|
189
180
|
---
|
|
190
181
|
|
|
191
|
-
|
|
182
|
+
#### 🪝 Option 2 — useLogic
|
|
183
|
+
|
|
184
|
+
Use directly inside a component.
|
|
192
185
|
|
|
193
186
|
```tsx
|
|
194
|
-
import
|
|
195
|
-
import { withLogic } from "logic-runtime-react-z"
|
|
187
|
+
import { useLogic } from "logic-runtime-react-z"
|
|
196
188
|
import { counterLogic } from "./counter.logic"
|
|
197
189
|
|
|
198
|
-
function
|
|
199
|
-
const { state,
|
|
190
|
+
export function Counter() {
|
|
191
|
+
const { state, computed, intent } = useLogic(counterLogic)
|
|
200
192
|
|
|
201
193
|
return (
|
|
202
|
-
<div
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
<button
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
>
|
|
212
|
-
Async +5
|
|
213
|
-
</button>
|
|
214
|
-
|
|
215
|
-
<hr />
|
|
216
|
-
|
|
217
|
-
<button onClick={() => emit("inc")}>
|
|
218
|
-
emit("inc")
|
|
194
|
+
<div>
|
|
195
|
+
<h2>Count: {state.count}</h2>
|
|
196
|
+
<p>Double: {computed.double}</p>
|
|
197
|
+
<p>Triple: {computed.triple}</p>
|
|
198
|
+
|
|
199
|
+
<button onClick={() => intent("inc")}>+</button>
|
|
200
|
+
<button onClick={() => intent("dec")}>-</button>
|
|
201
|
+
<button onClick={() => intent("asyncInc")}>
|
|
202
|
+
{state.loading ? "Loading..." : "Async +"}
|
|
219
203
|
</button>
|
|
220
204
|
</div>
|
|
221
205
|
)
|
|
222
206
|
}
|
|
207
|
+
```
|
|
223
208
|
|
|
224
|
-
|
|
209
|
+
✔ Props are inferred when using useLogic, no manual generics required.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 🌊 Async Support
|
|
214
|
+
|
|
215
|
+
Async logic is just another intent.
|
|
225
216
|
|
|
217
|
+
```ts
|
|
218
|
+
bus.on("fetchUser", async ({ setState }) => {
|
|
219
|
+
setState(s => { s.loading = true })
|
|
220
|
+
|
|
221
|
+
const data = await api.getUser()
|
|
222
|
+
|
|
223
|
+
setState(s => {
|
|
224
|
+
s.user = data
|
|
225
|
+
s.loading = false
|
|
226
|
+
})
|
|
227
|
+
})
|
|
226
228
|
```
|
|
227
229
|
|
|
228
|
-
|
|
230
|
+
No special async API needed.
|
|
229
231
|
|
|
230
232
|
---
|
|
231
233
|
|
|
234
|
+
|
|
232
235
|
## 🧪 Backend Usage (Same Runtime)
|
|
233
236
|
|
|
234
237
|
```ts
|
|
@@ -274,197 +277,164 @@ async function run() {
|
|
|
274
277
|
run()
|
|
275
278
|
```
|
|
276
279
|
|
|
277
|
-
✔ Same runtime, same behavior
|
|
278
|
-
✔ No React
|
|
279
|
-
✔ Replayable
|
|
280
|
+
✔ Same runtime, same behavior.
|
|
281
|
+
✔ No React dependency
|
|
282
|
+
✔ Replayable execution
|
|
280
283
|
|
|
281
284
|
---
|
|
282
285
|
|
|
283
|
-
## 🪝 Hooks Examples (Optional, Thin Adapters)
|
|
284
286
|
|
|
285
|
-
|
|
286
|
-
They do not own state, they only subscribe to it.
|
|
287
|
+
## 🧪 Unit Test Example
|
|
287
288
|
|
|
288
|
-
#### useRuntime – full snapshot
|
|
289
289
|
```ts
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
function Debug() {
|
|
293
|
-
const snapshot = useRuntime(counterLogic)
|
|
294
|
-
return <pre>{JSON.stringify(snapshot, null, 2)}</pre>
|
|
295
|
-
}
|
|
296
|
-
```
|
|
290
|
+
const logic = createLogic({
|
|
291
|
+
state: { value: 0 },
|
|
297
292
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
293
|
+
computed: {
|
|
294
|
+
squared: ({ state }) => state.value * state.value,
|
|
295
|
+
},
|
|
301
296
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
297
|
+
intents: bus => {
|
|
298
|
+
bus.on("set", ({ payload, setState }) => {
|
|
299
|
+
setState(s => {
|
|
300
|
+
s.value = payload
|
|
301
|
+
})
|
|
302
|
+
})
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
305
|
|
|
306
|
-
|
|
307
|
-
const actions = useActions(counterLogic)
|
|
306
|
+
const runtime = logic.create()
|
|
308
307
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
<button onClick={actions.inc}>+1</button>
|
|
312
|
-
<button onClick={() => actions.add(5)}>+5</button>
|
|
313
|
-
</>
|
|
314
|
-
)
|
|
315
|
-
}
|
|
308
|
+
await runtime.emit("set", 4)
|
|
309
|
+
expect(runtime.computed.squared).toBe(16)
|
|
316
310
|
```
|
|
317
311
|
|
|
312
|
+
---
|
|
318
313
|
|
|
319
|
-
|
|
320
|
-
✔ Fully inferred action types
|
|
321
|
-
✔ Ideal for buttons / handlers
|
|
322
|
-
|
|
323
|
-
#### useComputed – Subscribe to computed values
|
|
324
|
-
```ts
|
|
325
|
-
import { useComputed } from "logic-runtime-react-z"
|
|
314
|
+
## 🔍 Comparison
|
|
326
315
|
|
|
327
|
-
|
|
328
|
-
const { double, triple } = useComputed(counterLogic)
|
|
316
|
+
This is not about “better” — it's about architectural intent.
|
|
329
317
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
318
|
+
| Criteria | logic-runtime-react-z | Redux Toolkit | Zustand | Recoil | MobX |
|
|
319
|
+
|---------------------------------|------------------------------|----------------------|----------------|---------------|----------------|
|
|
320
|
+
| **Primary abstraction** | Intent runtime | Reducer store | Store | Atom graph | Observable |
|
|
321
|
+
| **Mental model** | Intent → Behavior → State | Action → Reducer | Mutate store | Atom graph | Reactive graph |
|
|
322
|
+
| **Single mutation entry** | ✅ | ✅ | ❌ | ❌ | ❌ |
|
|
323
|
+
| **Business logic isolation** | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
|
|
324
|
+
| **Built-in async orchestration**| ✅ | ⚠️ | ❌ | ❌ | ❌ |
|
|
325
|
+
| **Deterministic execution** | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
|
|
326
|
+
| **Derived state built-in** | ✅ | ❌ | ⚠️ | ✅ | ✅ |
|
|
327
|
+
| **Headless runtime** | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ |
|
|
328
|
+
| **Backend / worker ready** | ✅ | ⚠️ | ⚠️ | ❌ | ❌ |
|
|
329
|
+
| **Side-effect centralization** | ✅ | ⚠️ | ❌ | ❌ | ⚠️ |
|
|
330
|
+
| **Devtools maturity** | ⚠️ | ✅ | ⚠️ | ⚠️ | ⚠️ |
|
|
337
331
|
|
|
338
|
-
function DoubleOnly() {
|
|
339
|
-
const double = useComputed(counterLogic, c => c.double)
|
|
340
|
-
return <div>{double}</div>
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
332
|
|
|
344
|
-
|
|
345
|
-
✔ Cached & reactive
|
|
346
|
-
✔ No state mutation possible
|
|
333
|
+
<br />
|
|
347
334
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const double = useComputed(
|
|
352
|
-
counterLogic,
|
|
353
|
-
c => c.double
|
|
354
|
-
)
|
|
335
|
+
✅ Built-in / first-class
|
|
336
|
+
⚠️ Possible / usage-dependent
|
|
337
|
+
❌ Not built-in
|
|
355
338
|
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
```
|
|
339
|
+
---
|
|
359
340
|
|
|
360
|
-
|
|
361
|
-
✔ No extra dependencies
|
|
362
|
-
✔ Type-safe selector
|
|
341
|
+
### 🧠 Architectural Difference
|
|
363
342
|
|
|
364
|
-
|
|
365
|
-
```ts
|
|
366
|
-
import { useLogicSelector } from "logic-runtime-react-z"
|
|
343
|
+
Most state libraries focus on:
|
|
367
344
|
|
|
368
|
-
|
|
369
|
-
const count = useLogicSelector(
|
|
370
|
-
counterLogic.create(),
|
|
371
|
-
state => state.count
|
|
372
|
-
)
|
|
345
|
+
> **How state is stored and updated**
|
|
373
346
|
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
✔ Memoized selector
|
|
379
|
-
✔ Fine-grained subscriptions
|
|
380
|
-
✔ Familiar mental model
|
|
381
|
-
|
|
382
|
-
---
|
|
347
|
+
`logic-runtime-react-z` focuses on:
|
|
383
348
|
|
|
384
|
-
|
|
349
|
+
> **How behavior is orchestrated through intents**
|
|
385
350
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
import { userLogic } from "./user.logic"
|
|
389
|
-
import { cartLogic } from "./cart.logic"
|
|
351
|
+
Redux/Zustand answer:
|
|
352
|
+
> "Where is my state and how do I change it?"
|
|
390
353
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
cart: cartLogic,
|
|
394
|
-
})
|
|
354
|
+
This runtime answers:
|
|
355
|
+
> "What behavior is triggered by this event, and how should it execute?"
|
|
395
356
|
|
|
396
|
-
|
|
357
|
+
---
|
|
397
358
|
|
|
398
|
-
|
|
399
|
-
state.user
|
|
400
|
-
state.cart
|
|
359
|
+
### 🧭 Positioning Summary
|
|
401
360
|
|
|
402
|
-
|
|
361
|
+
- Redux → Structured state container
|
|
362
|
+
- Zustand → Lightweight mutable store
|
|
363
|
+
- Recoil → Declarative dependency graph
|
|
364
|
+
- MobX → Reactive observable system
|
|
365
|
+
- **logic-runtime-react-z → Intent-first behavior runtime**
|
|
403
366
|
|
|
404
367
|
---
|
|
405
368
|
|
|
406
|
-
|
|
369
|
+
### 🎯 When This Makes Sense
|
|
407
370
|
|
|
408
|
-
|
|
409
|
-
const logic = createLogic({
|
|
410
|
-
state: { value: 0 },
|
|
371
|
+
Choose this if you need:
|
|
411
372
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
373
|
+
- Complex async flows
|
|
374
|
+
- Deterministic replayable behavior
|
|
375
|
+
- Logic shared between frontend & backend
|
|
376
|
+
- Strong separation between UI and domain behavior
|
|
377
|
+
- An explicit event-driven boundary
|
|
415
378
|
|
|
416
|
-
|
|
417
|
-
bus.on("set", ({ payload, setState }) => {
|
|
418
|
-
setState(s => {
|
|
419
|
-
s.value = payload
|
|
420
|
-
})
|
|
421
|
-
})
|
|
422
|
-
},
|
|
423
|
-
})
|
|
379
|
+
Choose simpler state tools if:
|
|
424
380
|
|
|
425
|
-
|
|
381
|
+
- You mostly manage UI state
|
|
382
|
+
- You don’t need orchestration
|
|
383
|
+
- Your async flows are trivial
|
|
384
|
+
- Your team prefers mutable patterns
|
|
426
385
|
|
|
427
|
-
|
|
428
|
-
expect(runtime.computed.squared).toBe(16)
|
|
429
|
-
```
|
|
386
|
+
---
|
|
430
387
|
|
|
431
|
-
|
|
388
|
+
## 🧠 One-liner Takeaway
|
|
432
389
|
|
|
433
|
-
|
|
390
|
+
- Redux & Zustand manage **state**
|
|
391
|
+
- logic-runtime-react-z orchestrates **logic**
|
|
434
392
|
|
|
435
|
-
|
|
393
|
+
---
|
|
436
394
|
|
|
437
|
-
|
|
438
|
-
|--------------------------|:---------------------:|:-----:|:-------:|
|
|
439
|
-
| Intent-first model | ✅ | ❌ | ❌ |
|
|
440
|
-
| State-first model | ❌ | ✅ | ✅ |
|
|
441
|
-
| First-class effects | ✅ | ❌ | ❌ |
|
|
442
|
-
| Computed graph | ✅ | ❌ | ⚠️ |
|
|
443
|
-
| Deterministic execution | ✅ | ❌ | ❌ |
|
|
444
|
-
| Logic outside React | ✅ | ❌ | ❌ |
|
|
445
|
-
| Backend-safe | ✅ | ❌ | ❌ |
|
|
395
|
+
## 🧬 Deterministic Execution Model
|
|
446
396
|
|
|
397
|
+
- Intents are processed sequentially
|
|
398
|
+
- State mutations are isolated
|
|
399
|
+
- Async effects can follow declared execution strategies.
|
|
400
|
+
- Execution order is predictable
|
|
447
401
|
|
|
448
|
-
|
|
402
|
+
Given the same intent sequence, the resulting state is reproducible.
|
|
449
403
|
|
|
450
404
|
---
|
|
451
405
|
|
|
452
|
-
##
|
|
406
|
+
## 📐 Architecture Diagram (High-level)
|
|
453
407
|
|
|
454
|
-
|
|
455
|
-
|
|
408
|
+
```bash
|
|
409
|
+
┌─────────────┐
|
|
410
|
+
│ React UI │
|
|
411
|
+
└──────┬──────┘
|
|
412
|
+
│ adapter
|
|
413
|
+
┌──────▼──────┐
|
|
414
|
+
│ Runtime │
|
|
415
|
+
│ (create) │
|
|
416
|
+
├─────────────┤
|
|
417
|
+
│ Intent Bus │
|
|
418
|
+
│ Effects │
|
|
419
|
+
│ Handlers │
|
|
420
|
+
│ State │
|
|
421
|
+
│ Computed │
|
|
422
|
+
└─────────────┘
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
<b>Runtime is the product. React is an adapter.</b>
|
|
456
426
|
|
|
457
427
|
---
|
|
458
428
|
|
|
459
|
-
##
|
|
429
|
+
## ⚠️ When Not to Use
|
|
460
430
|
|
|
461
|
-
-
|
|
462
|
-
-
|
|
463
|
-
-
|
|
464
|
-
- Same inputs → same outputs
|
|
431
|
+
- Simple local component state
|
|
432
|
+
- Small apps without async complexity
|
|
433
|
+
- Teams unfamiliar with event-driven models
|
|
465
434
|
|
|
466
435
|
---
|
|
467
436
|
|
|
437
|
+
|
|
468
438
|
## License
|
|
469
439
|
|
|
470
440
|
MIT
|
package/build/core/effect.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type EffectStrategy = "default" | "takeLatest" | "debounce";
|
|
|
2
2
|
export type EffectHandler<S = any> = (context: S) => void | Promise<void>;
|
|
3
3
|
export type EffectDef<S = any> = {
|
|
4
4
|
_kind: "effect";
|
|
5
|
+
id: symbol;
|
|
5
6
|
handler: EffectHandler<S>;
|
|
6
7
|
strategy: EffectStrategy;
|
|
7
8
|
wait: number;
|
|
@@ -11,6 +12,7 @@ export declare function effect<S = any>(fn: EffectHandler<S>): {
|
|
|
11
12
|
takeLatest(): any;
|
|
12
13
|
debounce(ms: number): any;
|
|
13
14
|
_kind: "effect";
|
|
15
|
+
id: symbol;
|
|
14
16
|
handler: EffectHandler<S>;
|
|
15
17
|
strategy: EffectStrategy;
|
|
16
18
|
wait: number;
|
|
@@ -19,11 +21,13 @@ export declare function effect<S = any>(fn: EffectHandler<S>): {
|
|
|
19
21
|
takeLatest(): any;
|
|
20
22
|
debounce(ms: number): any;
|
|
21
23
|
_kind: "effect";
|
|
24
|
+
id: symbol;
|
|
22
25
|
handler: EffectHandler<S>;
|
|
23
26
|
strategy: EffectStrategy;
|
|
24
27
|
wait: number;
|
|
25
28
|
};
|
|
26
29
|
_kind: "effect";
|
|
30
|
+
id: symbol;
|
|
27
31
|
handler: EffectHandler<S>;
|
|
28
32
|
strategy: EffectStrategy;
|
|
29
33
|
wait: number;
|
package/build/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("chrono-state-z"),e=require("intentx-core-z"),s=require("react/jsx-runtime")
|
|
1
|
+
"use strict";var t=require("chrono-state-z"),e=require("intentx-core-z"),s=require("react/jsx-runtime");function n(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(s){if("default"!==s){var n=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,n.get?n:{enumerable:!0,get:function(){return t[s]}})}}),e.default=t,Object.freeze(e)}var o=n(require("react"));class i{constructor(){this.handlers={},this.effects={},this.middlewares=[]}use(t){this.middlewares.push(t)}effect(t,e){var s,n;(null!==(s=(n=this.effects)[t])&&void 0!==s?s:n[t]=[]).push(e)}on(t,e){var s,n;const o=this.handlers[t];o&&o.length>0?console.warn(`[IntentBus] Duplicate intent handler "${t}" detected. Only the first handler will be used.`):(null!==(s=(n=this.handlers)[t])&&void 0!==s?s:n[t]=[]).push(e)}async emit(t,e){var s,n;const o=null!==(s=this.handlers[t])&&void 0!==s?s:[],i=null!==(n=this.effects[t])&&void 0!==n?n:[],r=(a=this.middlewares,c=async t=>{t.effects=i;for(const e of o)await e(t)},a.reduceRight((t,e)=>e(t),c));var a,c;await r(e)}}class r{constructor(t,s=e.createScope("logic")){this.computedAtoms={},this.subs=new Set,this.bus=new i,this.dirty=!0,this.isComputing=!1,this.computedKeys=new Set,this.markDirty=()=>{this.dirty=!0,this.subs.forEach(t=>t())},this.getSnapshot=()=>(this.dirty&&(this.snapshotCache=this.buildSnapshot(),this.dirty=!1),this.snapshotCache),this.subscribe=t=>(this.subs.add(t),()=>this.subs.delete(t)),this.onIntent=(t,e)=>{this.bus.on(t,e)},this.emit=async(t,e)=>{const s=new AbortController;await this.bus.emit(t,{payload:e,scope:this.scope,signal:s.signal,state:this.getSnapshot,setState:t=>this.setStateInternal(t),emit:this.emit})},this.scope=s,this.stateAtoms=this.createStateAtoms(t);for(const t in this.stateAtoms)this.stateAtoms[t].subscribe(this.markDirty);this.bus.use(function(){const t=new Map,e=new Map;return s=>async n=>{var o;const i=n.effects;if(!(null==i?void 0:i.length))return s(n);for(const s of i){const i=s.id;if("takeLatest"===s.strategy){null===(o=t.get(i))||void 0===o||o.abort();const e=new AbortController;t.set(i,e),await s.handler({...n,signal:e.signal})}else"debounce"===s.strategy?(clearTimeout(e.get(i)),e.set(i,setTimeout(()=>s.handler(n),s.wait))):await s.handler(n)}await s(n)}}())}createStateAtoms(e){const s={};for(const n in e)s[n]=t.atom(e[n]);return s}buildSnapshot(){const t={};for(const e in this.stateAtoms)t[e]=this.stateAtoms[e]();for(const e in this.computedAtoms)t[e]=this.computedAtoms[e]();return t}createReactiveState(){return new Proxy({},{get:(t,e)=>{const s=this.stateAtoms[e];return s?s():void 0}})}get state(){return this.getSnapshot()}get computed(){const t={};return this.computedKeys.forEach(e=>{t[e]=this.computedAtoms[e]()}),t}getComputedKey(t){return this.computedAtoms[t]()}getComputed(t){const e={};return this.computedKeys.forEach(s=>{e[s]=t[s]}),e}setStateInternal(t){this.isComputing&&console.warn("[logic-runtime] setState() called inside computed()");const e={};for(const t in this.stateAtoms)e[t]=this.stateAtoms[t]();t(e);for(const t in this.stateAtoms)e[t]!==this.stateAtoms[t]()&&this.stateAtoms[t].set(e[t])}useEffect(t,e){this.bus.effect(t,e)}attachComputed(e,s){const n=t.atom(void 0),o=this.createReactiveState();this.computedAtoms[e]=n,this.computedKeys.add(e);const i=()=>{this.isComputing=!0,n.set(s({state:o})),this.isComputing=!1};t.effect(i),i(),n.subscribe(this.markDirty)}}function a(t){const e=function(){let t=0,e=[];return{get records(){return e.slice()},record:function(s){e.push({...s,id:++t,state:structuredClone(s.state)})},replay:async function(t,s){const{from:n=0,to:o=1/0,scope:i}=null!=s?s:{},r=e.filter(t=>"emit"===t.type&&t.id>=n&&t.id<=o&&(!i||t.scope===i));for(const e of r){const s=t(e.intent,e.payload);s instanceof Promise&&await s}},clear:function(){e=[],t=0}}}();function s(){return"string"==typeof t.scope?t.scope:t.scope.name}return{timeline:e,wrap:function(){const n=t.emit.bind(t);t.emit=async(o,i)=>{e.record({type:"emit:start",intent:o,payload:i,scope:s(),state:t.getSnapshot(),timestamp:Date.now()});try{const t=n(o,i);t instanceof Promise&&await t}finally{e.record({type:"emit:end",intent:o,payload:i,scope:s(),state:t.getSnapshot(),timestamp:Date.now()})}}}}}Object.defineProperty(exports,"createSelector",{enumerable:!0,get:function(){return t.createSelector}}),exports.LogicRuntime=r,exports.attachDevtools=a,exports.createBackendRuntime=function(t){var s,n;let o=structuredClone(t);const i=()=>o,r=t=>{o={...o,...t}},c=e.createScope("backend");async function u(t,e){await l.emit(t,e,c)}const l=e.createIntentBus(t=>{const e=new AbortController;return{scope:c,payload:t,signal:e.signal,get state(){return i()},setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}}),h={state:i,reset:()=>{o=structuredClone(t)},emit:u,registerIntents:function(t){for(const e in t){const s=t[e];l.on(e,async(t,e)=>{var n;const o={get state(){return i()},signal:null!==(n=t.signal)&&void 0!==n?n:(new AbortController).signal,set:r,emit:u};await s(o)},c)}},onIntent:l.on,effect:l.effect};if("production"!==(null===(n=null===(s=null===globalThis||void 0===globalThis?void 0:globalThis.process)||void 0===s?void 0:s.env)||void 0===n?void 0:n.NODE_ENV)){const t=a(h);t.wrap(h),h.devtools=t}return h},exports.createLogic=function(t){return{name:t.name,create(e){var s;const n=new r(structuredClone(t.state),e);if(t.computed)for(const e in t.computed)n.attachComputed(e,t.computed[e]);null===(s=t.intents)||void 0===s||s.call(t,{on:n.onIntent,effect:n.useEffect.bind(n)});const o={};if(t.actions){const e=Object.keys(t.actions);for(const s of e){const e=t.actions[s];o[s]=e({emit:n.emit,getState:n.getSnapshot})}}return n.actions=o,n}}},exports.effect=function(t){const e={_kind:"effect",id:Symbol("effect"),handler:t,strategy:"default",wait:0};return{...e,takeLatest(){return e.strategy="takeLatest",this},debounce(t){return e.strategy="debounce",e.wait=t,this}}},exports.useLogic=function(t,s){const n=o.useRef(null);n.current||(n.current=t.create("string"==typeof s?e.createScope(s):s));const i=n.current,r=o.useSyncExternalStore(i.subscribe,i.getSnapshot,i.getSnapshot),a=o.useCallback((t,e)=>i.emit(t,e),[i]),c=i.actions;return o.useMemo(()=>({state:r,actions:c,emit:a}),[r,c,a])},exports.withLogic=function(t,n,i){var r,a;const c=r=>{const a=o.useRef(null);a.current||(a.current=t.create("string"==typeof i?e.createScope(i):i));const c=a.current,u=o.useSyncExternalStore(c.subscribe,c.getSnapshot,c.getSnapshot),l=o.useCallback((t,e)=>c.emit(t,e),[c]),h=o.useMemo(()=>({state:u,actions:c.actions,emit:l}),[u,l,c]);return s.jsx(n,{...r,...h})};return c.displayName=`withLogic(${null!==(a=null!==(r=n.displayName)&&void 0!==r?r:n.name)&&void 0!==a?a:"View"})`,c};
|
package/build/index.d.ts
CHANGED
|
@@ -5,12 +5,8 @@ export { effect } from "./core/effect";
|
|
|
5
5
|
export type { IntentMiddleware, IntentNext, } from "./core/middleware";
|
|
6
6
|
export { createLogic } from "./logic/createLogic";
|
|
7
7
|
export type { LogicFactory, LogicActions, } from "./logic/createLogic";
|
|
8
|
-
export { composeLogic } from "./logic/composeLogic";
|
|
9
8
|
export { createBackendRuntime } from "./logic/createBackendRuntime";
|
|
10
9
|
export { withLogic } from "./react/withLogic";
|
|
11
|
-
export {
|
|
12
|
-
export { useComputed } from "./react/useComputed";
|
|
10
|
+
export type { LogicViewProps } from "./react/withLogic";
|
|
13
11
|
export { useLogic } from "./react/useLogic";
|
|
14
|
-
export { useLogicSelector } from "./react/useLogicSelector";
|
|
15
|
-
export { useRuntime } from "./react/useRuntime";
|
|
16
12
|
export * from "./devtools";
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{atom as t,effect as e
|
|
1
|
+
import{atom as t,effect as e}from"chrono-state-z";export{createSelector}from"chrono-state-z";import{createScope as s,createIntentBus as n}from"intentx-core-z";import{jsx as o}from"react/jsx-runtime";import*as i from"react";class a{constructor(){this.handlers={},this.effects={},this.middlewares=[]}use(t){this.middlewares.push(t)}effect(t,e){var s,n;(null!==(s=(n=this.effects)[t])&&void 0!==s?s:n[t]=[]).push(e)}on(t,e){var s,n;const o=this.handlers[t];o&&o.length>0?console.warn(`[IntentBus] Duplicate intent handler "${t}" detected. Only the first handler will be used.`):(null!==(s=(n=this.handlers)[t])&&void 0!==s?s:n[t]=[]).push(e)}async emit(t,e){var s,n;const o=null!==(s=this.handlers[t])&&void 0!==s?s:[],i=null!==(n=this.effects[t])&&void 0!==n?n:[],a=(r=this.middlewares,c=async t=>{t.effects=i;for(const e of o)await e(t)},r.reduceRight((t,e)=>e(t),c));var r,c;await a(e)}}class r{constructor(t,e=s("logic")){this.computedAtoms={},this.subs=new Set,this.bus=new a,this.dirty=!0,this.isComputing=!1,this.computedKeys=new Set,this.markDirty=()=>{this.dirty=!0,this.subs.forEach(t=>t())},this.getSnapshot=()=>(this.dirty&&(this.snapshotCache=this.buildSnapshot(),this.dirty=!1),this.snapshotCache),this.subscribe=t=>(this.subs.add(t),()=>this.subs.delete(t)),this.onIntent=(t,e)=>{this.bus.on(t,e)},this.emit=async(t,e)=>{const s=new AbortController;await this.bus.emit(t,{payload:e,scope:this.scope,signal:s.signal,state:this.getSnapshot,setState:t=>this.setStateInternal(t),emit:this.emit})},this.scope=e,this.stateAtoms=this.createStateAtoms(t);for(const t in this.stateAtoms)this.stateAtoms[t].subscribe(this.markDirty);this.bus.use(function(){const t=new Map,e=new Map;return s=>async n=>{var o;const i=n.effects;if(!(null==i?void 0:i.length))return s(n);for(const s of i){const i=s.id;if("takeLatest"===s.strategy){null===(o=t.get(i))||void 0===o||o.abort();const e=new AbortController;t.set(i,e),await s.handler({...n,signal:e.signal})}else"debounce"===s.strategy?(clearTimeout(e.get(i)),e.set(i,setTimeout(()=>s.handler(n),s.wait))):await s.handler(n)}await s(n)}}())}createStateAtoms(e){const s={};for(const n in e)s[n]=t(e[n]);return s}buildSnapshot(){const t={};for(const e in this.stateAtoms)t[e]=this.stateAtoms[e]();for(const e in this.computedAtoms)t[e]=this.computedAtoms[e]();return t}createReactiveState(){return new Proxy({},{get:(t,e)=>{const s=this.stateAtoms[e];return s?s():void 0}})}get state(){return this.getSnapshot()}get computed(){const t={};return this.computedKeys.forEach(e=>{t[e]=this.computedAtoms[e]()}),t}getComputedKey(t){return this.computedAtoms[t]()}getComputed(t){const e={};return this.computedKeys.forEach(s=>{e[s]=t[s]}),e}setStateInternal(t){this.isComputing&&console.warn("[logic-runtime] setState() called inside computed()");const e={};for(const t in this.stateAtoms)e[t]=this.stateAtoms[t]();t(e);for(const t in this.stateAtoms)e[t]!==this.stateAtoms[t]()&&this.stateAtoms[t].set(e[t])}useEffect(t,e){this.bus.effect(t,e)}attachComputed(s,n){const o=t(void 0),i=this.createReactiveState();this.computedAtoms[s]=o,this.computedKeys.add(s);const a=()=>{this.isComputing=!0,o.set(n({state:i})),this.isComputing=!1};e(a),a(),o.subscribe(this.markDirty)}}function c(t){const e={_kind:"effect",id:Symbol("effect"),handler:t,strategy:"default",wait:0};return{...e,takeLatest(){return e.strategy="takeLatest",this},debounce(t){return e.strategy="debounce",e.wait=t,this}}}function u(t){return{name:t.name,create(e){var s;const n=new r(structuredClone(t.state),e);if(t.computed)for(const e in t.computed)n.attachComputed(e,t.computed[e]);null===(s=t.intents)||void 0===s||s.call(t,{on:n.onIntent,effect:n.useEffect.bind(n)});const o={};if(t.actions){const e=Object.keys(t.actions);for(const s of e){const e=t.actions[s];o[s]=e({emit:n.emit,getState:n.getSnapshot})}}return n.actions=o,n}}}function l(t){const e=function(){let t=0,e=[];return{get records(){return e.slice()},record:function(s){e.push({...s,id:++t,state:structuredClone(s.state)})},replay:async function(t,s){const{from:n=0,to:o=1/0,scope:i}=null!=s?s:{},a=e.filter(t=>"emit"===t.type&&t.id>=n&&t.id<=o&&(!i||t.scope===i));for(const e of a){const s=t(e.intent,e.payload);s instanceof Promise&&await s}},clear:function(){e=[],t=0}}}();function s(){return"string"==typeof t.scope?t.scope:t.scope.name}return{timeline:e,wrap:function(){const n=t.emit.bind(t);t.emit=async(o,i)=>{e.record({type:"emit:start",intent:o,payload:i,scope:s(),state:t.getSnapshot(),timestamp:Date.now()});try{const t=n(o,i);t instanceof Promise&&await t}finally{e.record({type:"emit:end",intent:o,payload:i,scope:s(),state:t.getSnapshot(),timestamp:Date.now()})}}}}}function h(t){var e,o;let i=structuredClone(t);const a=()=>i,r=t=>{i={...i,...t}},c=s("backend");async function u(t,e){await h.emit(t,e,c)}const h=n(t=>{const e=new AbortController;return{scope:c,payload:t,signal:e.signal,get state(){return a()},setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}});const d={state:a,reset:()=>{i=structuredClone(t)},emit:u,registerIntents:function(t){for(const e in t){const s=t[e];h.on(e,async(t,e)=>{var n;const o={get state(){return a()},signal:null!==(n=t.signal)&&void 0!==n?n:(new AbortController).signal,set:r,emit:u};await s(o)},c)}},onIntent:h.on,effect:h.effect};if("production"!==(null===(o=null===(e=null===globalThis||void 0===globalThis?void 0:globalThis.process)||void 0===e?void 0:e.env)||void 0===o?void 0:o.NODE_ENV)){const t=l(d);t.wrap(d),d.devtools=t}return d}function d(t,e,n){var a,r;const c=a=>{const r=i.useRef(null);r.current||(r.current=t.create("string"==typeof n?s(n):n));const c=r.current,u=i.useSyncExternalStore(c.subscribe,c.getSnapshot,c.getSnapshot),l=i.useCallback((t,e)=>c.emit(t,e),[c]),h=i.useMemo(()=>({state:u,actions:c.actions,emit:l}),[u,l,c]);return o(e,{...a,...h})};return c.displayName=`withLogic(${null!==(r=null!==(a=e.displayName)&&void 0!==a?a:e.name)&&void 0!==r?r:"View"})`,c}function m(t,e){const n=i.useRef(null);n.current||(n.current=t.create("string"==typeof e?s(e):e));const o=n.current,a=i.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot),r=i.useCallback((t,e)=>o.emit(t,e),[o]),c=o.actions;return i.useMemo(()=>({state:a,actions:c,emit:r}),[a,c,r])}export{r as LogicRuntime,l as attachDevtools,h as createBackendRuntime,u as createLogic,c as effect,m as useLogic,d as withLogic};
|
|
@@ -6,18 +6,23 @@ export type LogicFactory<S extends object, C extends ComputedDef<S>, A extends L
|
|
|
6
6
|
name?: string;
|
|
7
7
|
create(scope?: Scope): LogicRuntime<S, C, A>;
|
|
8
8
|
};
|
|
9
|
-
export
|
|
9
|
+
export type ExtractLogicTypes<T> = T extends LogicFactory<infer S, infer C, infer A> ? {
|
|
10
|
+
state: Readonly<S & InferComputed<C>>;
|
|
11
|
+
actions: A;
|
|
12
|
+
emit: (intent: string, payload?: any) => Promise<void>;
|
|
13
|
+
} : never;
|
|
14
|
+
export declare function createLogic<S extends object, C extends ComputedDef<S>, ActionsDef extends Record<string, (context: {
|
|
15
|
+
emit: LogicRuntime<S, C, any>["emit"];
|
|
16
|
+
getState: () => Readonly<S & InferComputed<C>>;
|
|
17
|
+
}) => (...args: any[]) => any>>(config: {
|
|
10
18
|
name?: string;
|
|
11
19
|
state: S;
|
|
12
|
-
computed
|
|
20
|
+
computed: C;
|
|
13
21
|
intents?: (bus: {
|
|
14
|
-
on: LogicRuntime<S, C,
|
|
22
|
+
on: LogicRuntime<S, C, any>["onIntent"];
|
|
15
23
|
effect: (type: string, eff: EffectDef) => void;
|
|
16
24
|
}) => void;
|
|
17
|
-
actions
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}) => A[K];
|
|
22
|
-
};
|
|
23
|
-
}): LogicFactory<S, C, A>;
|
|
25
|
+
actions: ActionsDef;
|
|
26
|
+
}): LogicFactory<S, C, {
|
|
27
|
+
[K in keyof ActionsDef]: ReturnType<ActionsDef[K]>;
|
|
28
|
+
}>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Scope } from "intentx-core-z";
|
|
2
|
+
import type { LogicActions, LogicFactory } from "../logic/createLogic";
|
|
3
|
+
import type { ComputedDef } from "../core/runtime";
|
|
4
|
+
export declare function useLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>, scope?: Scope | string): {
|
|
5
|
+
state: Readonly<S & import("../core/runtime").InferComputed<C>>;
|
|
5
6
|
actions: A;
|
|
7
|
+
emit: (intent: string, payload?: any) => Promise<void>;
|
|
6
8
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Scope } from "intentx-core-z";
|
|
3
|
-
import type { LogicActions, LogicFactory } from "../logic/createLogic";
|
|
3
|
+
import type { ExtractLogicTypes, LogicActions, LogicFactory } from "../logic/createLogic";
|
|
4
4
|
import type { ComputedDef, InferComputed } from "../core/runtime";
|
|
5
5
|
type InjectedProps<S extends object, C extends ComputedDef<S>, A extends LogicActions> = {
|
|
6
6
|
state: Readonly<S & InferComputed<C>>;
|
|
7
7
|
actions: A;
|
|
8
8
|
emit: (intent: string, payload?: any) => Promise<void>;
|
|
9
9
|
};
|
|
10
|
+
export type LogicViewProps<T extends LogicFactory<any, any, any>> = ExtractLogicTypes<T>;
|
|
10
11
|
export declare function withLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions, P extends object>(logic: LogicFactory<S, C, A>, View: React.ComponentType<P & InjectedProps<S, C, A>>, scope?: Scope | string): React.FC<Omit<P, keyof InjectedProps<S, C, A>>>;
|
|
11
12
|
export {};
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logic-runtime-react-z",
|
|
3
|
-
"version": "3.1.
|
|
4
|
-
"description": "Intent-first business logic runtime.
|
|
3
|
+
"version": "3.1.3",
|
|
4
|
+
"description": "Intent-first business logic runtime. Deterministic, headless, and framework-agnostic.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Delpi.Kye",
|
|
7
7
|
"sideEffects": false,
|
|
8
|
+
|
|
8
9
|
"main": "build/index.cjs.js",
|
|
9
10
|
"module": "build/index.esm.js",
|
|
10
11
|
"types": "build/index.d.ts",
|
|
@@ -13,27 +14,19 @@
|
|
|
13
14
|
"types": "./build/index.d.ts",
|
|
14
15
|
"import": "./build/index.esm.js",
|
|
15
16
|
"require": "./build/index.cjs.js"
|
|
16
|
-
},
|
|
17
|
-
"./react": {
|
|
18
|
-
"types": "./build/react/index.d.ts",
|
|
19
|
-
"import": "./build/react/index.esm.js",
|
|
20
|
-
"require": "./build/react/index.cjs.js"
|
|
21
|
-
},
|
|
22
|
-
"./devtools": {
|
|
23
|
-
"types": "./build/devtools/index.d.ts",
|
|
24
|
-
"import": "./build/devtools/index.esm.js",
|
|
25
|
-
"require": "./build/devtools/index.cjs.js"
|
|
26
17
|
}
|
|
27
18
|
},
|
|
28
19
|
"files": [
|
|
29
20
|
"build"
|
|
30
21
|
],
|
|
22
|
+
|
|
31
23
|
"scripts": {
|
|
32
24
|
"clean": "rimraf build",
|
|
33
25
|
"build": "rollup -c",
|
|
34
26
|
"cb": "npm run clean && npm run build",
|
|
35
27
|
"prepublishOnly": "npm run cb"
|
|
36
28
|
},
|
|
29
|
+
|
|
37
30
|
"repository": {
|
|
38
31
|
"type": "git",
|
|
39
32
|
"url": "https://github.com/delpikye-v/logic-runtime-react.git"
|
|
@@ -42,6 +35,7 @@
|
|
|
42
35
|
"bugs": {
|
|
43
36
|
"url": "https://github.com/delpikye-v/logic-runtime-react/issues"
|
|
44
37
|
},
|
|
38
|
+
|
|
45
39
|
"keywords": [
|
|
46
40
|
"intent-first",
|
|
47
41
|
"intent-runtime",
|
|
@@ -60,6 +54,7 @@
|
|
|
60
54
|
"takeLatest",
|
|
61
55
|
"state-management"
|
|
62
56
|
],
|
|
57
|
+
|
|
63
58
|
"peerDependencies": {
|
|
64
59
|
"react": ">=18.0.0",
|
|
65
60
|
"react-dom": ">=18.0.0"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Scope } from "intentx-core-z";
|
|
2
|
-
import type { ComputedDef, InferComputed } from "../core/runtime";
|
|
3
|
-
import { LogicRuntime } from "../core/runtime";
|
|
4
|
-
import type { LogicFactory } from "../logic/createLogic";
|
|
5
|
-
type AnyLogicFactory = LogicFactory<any, ComputedDef<any>, any>;
|
|
6
|
-
type LogicMap = Record<string, AnyLogicFactory>;
|
|
7
|
-
type InferRuntime<L> = L extends LogicFactory<infer S, infer C, infer A> ? LogicRuntime<S, C, A> : never;
|
|
8
|
-
type InferState<M extends LogicMap> = {
|
|
9
|
-
[K in keyof M]: InferRuntime<M[K]> extends LogicRuntime<infer S, infer C, any> ? Readonly<S & InferComputed<C>> : never;
|
|
10
|
-
};
|
|
11
|
-
type InferActions<M extends LogicMap> = {
|
|
12
|
-
[K in keyof M]: InferRuntime<M[K]> extends LogicRuntime<any, any, infer A> ? A : never;
|
|
13
|
-
};
|
|
14
|
-
export declare function composeLogic<M extends LogicMap>(map: M): {
|
|
15
|
-
scope: Scope;
|
|
16
|
-
runtimes: { [K in keyof M]: InferRuntime<M[K]>; };
|
|
17
|
-
emit: <P = any>(type: string, payload?: P) => Promise<void>;
|
|
18
|
-
actions: InferActions<M>;
|
|
19
|
-
getState: () => InferState<M>;
|
|
20
|
-
};
|
|
21
|
-
export {};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { LogicFactory, LogicActions } from "../logic/createLogic";
|
|
2
|
-
import { LogicRuntime, ComputedDef } from "../core/runtime";
|
|
3
|
-
export declare function useActions<A extends LogicActions>(runtime: LogicRuntime<any, any, A>): A;
|
|
4
|
-
export declare function useActions<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>): A;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { LogicFactory } from "../logic/createLogic";
|
|
2
|
-
import { LogicRuntime, ComputedDef, InferComputed } from "../core/runtime";
|
|
3
|
-
export declare function useComputed<S extends object, C extends ComputedDef<S>>(runtime: LogicRuntime<S, C, any>): Readonly<InferComputed<C>>;
|
|
4
|
-
export declare function useComputed<S extends object, C extends ComputedDef<S>, R>(runtime: LogicRuntime<S, C, any>, selector: (computed: Readonly<InferComputed<C>>) => R): R;
|
|
5
|
-
export declare function useComputed<S extends object, C extends ComputedDef<S>, A extends Record<string, any>>(logic: LogicFactory<S, C, A>): Readonly<InferComputed<C>>;
|
|
6
|
-
export declare function useComputed<S extends object, C extends ComputedDef<S>, A extends Record<string, any>, R>(logic: LogicFactory<S, C, A>, selector: (computed: Readonly<InferComputed<C>>) => R): R;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { ComputedDef, InferComputed } from "../core/runtime";
|
|
2
|
-
import { LogicRuntime } from "../core/runtime";
|
|
3
|
-
import type { LogicFactory } from "../logic/createLogic";
|
|
4
|
-
export declare function useRuntime<S extends object, C extends ComputedDef<S>, A extends Record<string, any>>(runtime: LogicRuntime<S, C, A>): Readonly<S & InferComputed<C>>;
|
|
5
|
-
export declare function useRuntime<S extends object, C extends ComputedDef<S>, A extends Record<string, any>>(logic: LogicFactory<S, C, A>): Readonly<S & InferComputed<C>>;
|