chrono-state-z 2.0.1 → 2.2.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 +161 -39
- package/build/core/asyncAtom.d.ts +9 -8
- package/build/core/asyncComputed.d.ts +5 -3
- package/build/core/asyncResource.d.ts +28 -0
- package/build/core/atom.d.ts +6 -6
- package/build/core/createAtomFactory.d.ts +7 -0
- package/build/core/createBaseAtom.d.ts +6 -0
- package/build/core/createStore.d.ts +2 -10
- package/build/core/factoryAtom.d.ts +7 -1
- package/build/core/index.d.ts +9 -11
- package/build/core/selector.d.ts +7 -1
- package/build/core/types.d.ts +12 -0
- package/build/core/watch.d.ts +6 -1
- package/build/index.cjs.js +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.esm.js +1 -1
- package/build/react/index.d.ts +3 -2
- package/build/react/useComputed.d.ts +2 -1
- package/build/react/useStoreSelector.d.ts +2 -2
- package/build/react/useWatch.d.ts +2 -1
- package/package.json +13 -27
- package/build/core/computed.d.ts +0 -1
- package/build/core/effect.d.ts +0 -2
- package/build/core/effectContext.d.ts +0 -3
- package/build/core/graph.d.ts +0 -22
- package/build/core/scope.d.ts +0 -4
- package/build/core/store.d.ts +0 -9
- package/build/core/testRuntime.d.ts +0 -6
- package/build/react/useScopedStore.d.ts +0 -4
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ⏱️ chrono-state-z
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/chrono-state-z) 
|
|
4
4
|
|
|
@@ -6,20 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
**chrono-state-z** is a
|
|
10
|
-
|
|
9
|
+
**chrono-state-z** is a reactive state runtime that keeps business logic outside React.
|
|
10
|
+
It provides **atoms, computed values, async state, effects, scheduling**, with a **headless core** and **thin React bindings**.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
with a **headless core** and **thin React bindings**.
|
|
14
|
-
|
|
15
|
-
> **React renders state. Logic lives elsewhere.**
|
|
12
|
+
> **React renders. Logic lives elsewhere.**
|
|
16
13
|
|
|
17
14
|
---
|
|
18
15
|
|
|
19
16
|
## ✨ Why chrono-state-z?
|
|
20
17
|
|
|
21
|
-
Use chrono-state-z when you need:
|
|
22
|
-
|
|
23
18
|
- Predictable state & side-effects
|
|
24
19
|
- Complex async flows (fetch → invalidate → retry)
|
|
25
20
|
- Logic reusable outside React (tests, workers, backend)
|
|
@@ -43,12 +38,50 @@ Use chrono-state-z when you need:
|
|
|
43
38
|
## 📦 Installation
|
|
44
39
|
|
|
45
40
|
```bash
|
|
46
|
-
npm install
|
|
47
|
-
|
|
41
|
+
npm install chrono-state-z
|
|
42
|
+
# If using React:
|
|
43
|
+
npm install react
|
|
48
44
|
```
|
|
49
45
|
|
|
50
46
|
---
|
|
51
47
|
|
|
48
|
+
## ⚡ Quick Start
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { atom, computed, asyncAtom } from "chrono-state-z";
|
|
52
|
+
|
|
53
|
+
const count = atom(0);
|
|
54
|
+
const double = computed(() => count() * 2);
|
|
55
|
+
|
|
56
|
+
const user = asyncAtom(async () =>
|
|
57
|
+
fetch("https://jsonplaceholder.typicode.com/todos/1")
|
|
58
|
+
.then(r => r.json())
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { useAtom, useComputed } from "chrono-state-z";
|
|
64
|
+
|
|
65
|
+
function App() {
|
|
66
|
+
const value = useAtom(count);
|
|
67
|
+
const doubled = useComputed(double);
|
|
68
|
+
const username = useComputed(() => user()?.title);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<button onClick={() => count.set(c => c + 1)}>
|
|
72
|
+
{value}
|
|
73
|
+
</button>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
✨ Fine-grained updates.
|
|
80
|
+
✨ Suspense-ready async.
|
|
81
|
+
✨ No reducers. No boilerplate.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
52
85
|
## 🔹 Core Usage
|
|
53
86
|
|
|
54
87
|
### Atom & Computed
|
|
@@ -208,7 +241,7 @@ import { computed, useComputed } from 'chrono-state-z'
|
|
|
208
241
|
const total = computed(() => price() * qty())
|
|
209
242
|
|
|
210
243
|
function TotalView() {
|
|
211
|
-
const value = useComputed(
|
|
244
|
+
const value = useComputed(total)
|
|
212
245
|
return <div>Total: {value}</div>
|
|
213
246
|
}
|
|
214
247
|
```
|
|
@@ -218,8 +251,7 @@ function TotalView() {
|
|
|
218
251
|
### useAtomSelector
|
|
219
252
|
|
|
220
253
|
```tsx
|
|
221
|
-
|
|
222
|
-
|
|
254
|
+
// atom() returns a callable reactive value
|
|
223
255
|
const user = atom({ id: 1, name: 'Alice', age: 20 })
|
|
224
256
|
|
|
225
257
|
function Username() {
|
|
@@ -234,11 +266,13 @@ function Username() {
|
|
|
234
266
|
|
|
235
267
|
```tsx
|
|
236
268
|
import { useStore } from 'chrono-state-z'
|
|
269
|
+
import type { Store } from 'chrono-state-z'
|
|
237
270
|
|
|
238
|
-
function StoreView({ store }) {
|
|
271
|
+
function StoreView({ store }: { store: Store<any> }) {
|
|
239
272
|
const state = useStore(store)
|
|
240
|
-
return <pre>{JSON.stringify(state)}</pre>
|
|
273
|
+
return <pre>{JSON.stringify(state, null, 2)}</pre>
|
|
241
274
|
}
|
|
275
|
+
|
|
242
276
|
```
|
|
243
277
|
|
|
244
278
|
---
|
|
@@ -246,13 +280,22 @@ function StoreView({ store }) {
|
|
|
246
280
|
### useStoreSelector
|
|
247
281
|
|
|
248
282
|
```tsx
|
|
283
|
+
// Only re-renders when saving changes, not the whole store.
|
|
249
284
|
import { useStoreSelector } from 'chrono-state-z'
|
|
250
285
|
|
|
251
286
|
function SavingBadge({ store }) {
|
|
252
287
|
const saving = useStoreSelector(store, s => s.saving)
|
|
288
|
+
// const saving = useStoreSelector(
|
|
289
|
+
// store,
|
|
290
|
+
// s => s.meta,
|
|
291
|
+
// shallowEqual
|
|
292
|
+
// )
|
|
253
293
|
return saving ? 'Saving...' : 'Idle'
|
|
254
294
|
}
|
|
295
|
+
|
|
255
296
|
```
|
|
297
|
+
- `selector` should be pure and stable.
|
|
298
|
+
- If you need dynamic selection, memoize the selector.
|
|
256
299
|
|
|
257
300
|
---
|
|
258
301
|
|
|
@@ -261,28 +304,48 @@ function SavingBadge({ store }) {
|
|
|
261
304
|
```ts
|
|
262
305
|
import { useWatch } from 'chrono-state-z'
|
|
263
306
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
)
|
|
307
|
+
const user = atom<{ role?: string } | null>(null)
|
|
308
|
+
|
|
309
|
+
function AuthGuard() {
|
|
310
|
+
useWatch(
|
|
311
|
+
() => user(),
|
|
312
|
+
(u) => {
|
|
313
|
+
if (u?.role === 'admin') {
|
|
314
|
+
redirect('/admin')
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
return null
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### AsyncAtom
|
|
325
|
+
```ts
|
|
326
|
+
const user = asyncAtom(fetchUser)
|
|
327
|
+
|
|
328
|
+
// load explicitly
|
|
329
|
+
await user.load()
|
|
330
|
+
|
|
331
|
+
// read value (throws / suspends if not ready)
|
|
332
|
+
const u = user()
|
|
270
333
|
```
|
|
271
334
|
|
|
272
335
|
---
|
|
273
336
|
|
|
274
|
-
## 🧩 Architecture
|
|
337
|
+
## 🧩 Architecture Pattern
|
|
275
338
|
|
|
276
339
|
```ts
|
|
277
340
|
import { asyncAtom, computed } from 'chrono-state-z'
|
|
278
341
|
|
|
279
342
|
export function createUserLogic() {
|
|
280
343
|
const user = asyncAtom(fetchUser)
|
|
281
|
-
const
|
|
344
|
+
const name = computed(() => user()?.name ?? 'Guest')
|
|
282
345
|
|
|
283
346
|
return {
|
|
284
347
|
user,
|
|
285
|
-
|
|
348
|
+
name,
|
|
286
349
|
reload: () => user.invalidate()
|
|
287
350
|
}
|
|
288
351
|
}
|
|
@@ -291,29 +354,88 @@ export function createUserLogic() {
|
|
|
291
354
|
```tsx
|
|
292
355
|
function UserView({ logic }) {
|
|
293
356
|
const user = useAtom(logic.user)
|
|
294
|
-
const name = useComputed(
|
|
357
|
+
const name = useComputed(logic.name)
|
|
295
358
|
|
|
296
359
|
return (
|
|
297
|
-
|
|
298
|
-
<
|
|
360
|
+
<>
|
|
361
|
+
<div>Hello {name}</div>
|
|
299
362
|
<button onClick={logic.reload}>Reload</button>
|
|
300
|
-
|
|
363
|
+
</>
|
|
301
364
|
)
|
|
302
365
|
}
|
|
366
|
+
|
|
303
367
|
```
|
|
304
368
|
|
|
305
369
|
---
|
|
306
370
|
|
|
307
|
-
##
|
|
371
|
+
## 🔍 Comparison
|
|
372
|
+
|
|
373
|
+
<b>This is not about “better” — it's about architectural.</b>
|
|
374
|
+
|
|
375
|
+
| Feature | chrono-state-z | Redux Toolkit | Zustand | Jotai | MobX |
|
|
376
|
+
| --------------------------- | -------------- | ------------- | -------- | ----- | ---- |
|
|
377
|
+
| Fine-grained reactivity | ✅ | ❌ | ⚠️ | ✅ | ✅ |
|
|
378
|
+
| Built-in async primitives | ✅ | ⚠️ | ❌ | ⚠️ | ❌ |
|
|
379
|
+
| Scheduler / priority system | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
380
|
+
| Headless (non-React) core | ✅ | ✅ | ⚠️ | ⚠️ | ✅ |
|
|
381
|
+
| Boilerplate level | ✅ | ❌ | ✅ | ✅ | ⚠️ |
|
|
382
|
+
| Devtools maturity | ⚠️ | ✅ | ✅ | ⚠️ | ✅ |
|
|
383
|
+
| Learning curve | ⚠️ | ⚠️ | ✅ | ✅ | ⚠️ |
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
<br />
|
|
387
|
+
|
|
388
|
+
<b>📝 Notes</b>
|
|
389
|
+
|
|
390
|
+
⚠️ Fine-grained in Zustand: achieved via selectors, but not dependency-tracked graph-level.
|
|
391
|
+
|
|
392
|
+
⚠️ Async in Redux / Jotai / Recoil: supported via patterns (thunks, query libs, async selectors), not core-first primitives.
|
|
393
|
+
|
|
394
|
+
⚠️ Headless in Zustand/Jotai: possible, but primarily designed for React usage.
|
|
395
|
+
|
|
396
|
+
⚠️ Devtools: Redux and MobX have mature ecosystems; newer libs are still evolving.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## ⚖️ Strengths Compared to Others
|
|
401
|
+
|
|
402
|
+
<b>vs Redux Toolkit</b>
|
|
403
|
+
|
|
404
|
+
- More fine-grained updates
|
|
405
|
+
- Less reducer boilerplate
|
|
406
|
+
- Built-in reactive primitives
|
|
407
|
+
- Redux has stronger ecosystem & devtools
|
|
408
|
+
|
|
409
|
+
<b>vs Zustand</b>
|
|
410
|
+
|
|
411
|
+
- More structured async handling
|
|
412
|
+
- Explicit intent layer
|
|
413
|
+
- Built-in scheduler support
|
|
414
|
+
- Zustand is simpler & lighter for small apps
|
|
415
|
+
|
|
416
|
+
<b>vs Jotai</b>
|
|
417
|
+
|
|
418
|
+
- More explicit effect + scheduler control
|
|
419
|
+
- Async-first primitives
|
|
420
|
+
- Jotai is more minimal and React-native
|
|
421
|
+
|
|
422
|
+
<b>vs MobX</b>
|
|
423
|
+
|
|
424
|
+
- More explicit dependency graph (no proxy magic)
|
|
425
|
+
- Better control over update priority
|
|
426
|
+
- MobX is more ergonomic for mutable patterns
|
|
427
|
+
|
|
428
|
+
<b>vs Recoil</b>
|
|
429
|
+
|
|
430
|
+
- Headless core (not React-bound)
|
|
431
|
+
- Explicit effect system
|
|
432
|
+
- Recoil has better React DevTools integration
|
|
433
|
+
|
|
434
|
+
<b>vs Solid signals</b>
|
|
308
435
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
| Async primitives | ✅ | ⚠️ | ❌ | ⚠️ |
|
|
313
|
-
| Intent / effect layer | ✅ | ⚠️ | ❌ | ❌ |
|
|
314
|
-
| Scheduler / priority | ✅ | ❌ | ❌ | ❌ |
|
|
315
|
-
| Headless (non-React) core | ✅ | ❌ | ⚠️ | ❌ |
|
|
316
|
-
| Testability | ✅ | ⚠️ | ⚠️ | ❌ |
|
|
436
|
+
- Similar fine-grained reactive model
|
|
437
|
+
- Designed for React ecosystem
|
|
438
|
+
- Solid is framework-native and extremely optimized
|
|
317
439
|
|
|
318
440
|
---
|
|
319
441
|
|
|
@@ -337,4 +459,4 @@ function UserView({ logic }) {
|
|
|
337
459
|
|
|
338
460
|
## 📜 License
|
|
339
461
|
|
|
340
|
-
MIT
|
|
462
|
+
MIT
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommonResource } from "./asyncResource";
|
|
2
2
|
export type AsyncAtom<T> = {
|
|
3
|
-
(): T;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
(): T | undefined;
|
|
4
|
+
} & CommonResource<T>;
|
|
5
|
+
export declare function asyncAtom<T>(fetcher: (signal?: AbortSignal) => Promise<T>, options?: {
|
|
6
|
+
suspense?: boolean;
|
|
7
|
+
}): AsyncAtom<T>;
|
|
8
|
+
export declare function asyncAtomFamily<K, T>(factory: (key: K) => (signal?: AbortSignal) => Promise<T>, options?: {
|
|
9
|
+
suspense?: boolean;
|
|
10
|
+
}): (key: K) => AsyncAtom<T>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Priority } from "intentx-core-z";
|
|
2
2
|
export type AsyncComputed<T> = {
|
|
3
|
-
(): T;
|
|
4
|
-
invalidate(
|
|
3
|
+
(): T | undefined;
|
|
4
|
+
invalidate(priority?: Priority): void;
|
|
5
|
+
status(): string;
|
|
6
|
+
error(): any;
|
|
5
7
|
};
|
|
6
|
-
export declare function asyncComputed<T>(getter: () => Promise<T>, priority?: Priority): AsyncComputed<T>;
|
|
8
|
+
export declare function asyncComputed<T>(getter: (signal?: AbortSignal) => Promise<T>, priority?: Priority): AsyncComputed<T>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Priority } from "intentx-core-z";
|
|
2
|
+
export type CommonResource<T> = {
|
|
3
|
+
load(): Promise<T>;
|
|
4
|
+
cancel(): void;
|
|
5
|
+
invalidate(priority?: Priority): void;
|
|
6
|
+
status(): AsyncState<T>["status"];
|
|
7
|
+
error(): any;
|
|
8
|
+
setSuccess(value: T, priority?: Priority): void;
|
|
9
|
+
};
|
|
10
|
+
export type AsyncState<T> = {
|
|
11
|
+
status: "idle";
|
|
12
|
+
} | {
|
|
13
|
+
status: "loading";
|
|
14
|
+
promise: Promise<T>;
|
|
15
|
+
} | {
|
|
16
|
+
status: "success";
|
|
17
|
+
data: T;
|
|
18
|
+
} | {
|
|
19
|
+
status: "error";
|
|
20
|
+
error: any;
|
|
21
|
+
};
|
|
22
|
+
export type AsyncResource<T> = {
|
|
23
|
+
read(): T | undefined;
|
|
24
|
+
} & CommonResource<T>;
|
|
25
|
+
export declare function createAsyncResource<T>(fetcher: (signal?: AbortSignal) => Promise<T>, options?: {
|
|
26
|
+
suspense?: boolean;
|
|
27
|
+
priority?: Priority;
|
|
28
|
+
}): AsyncResource<T>;
|
package/build/core/atom.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export type ReadonlyAtom<T> = () => T;
|
|
2
|
+
export declare const atom: <T>(initial: T, options?: import("./createAtomFactory").AtomOptions<T>) => import("./createBaseAtom").Atom<T>;
|
|
3
|
+
export declare const atomMiddleware: <T>(initial: T, middleware?: import("./createAtomFactory").AtomMiddleware<T>) => import("./createBaseAtom").Atom<T>;
|
|
4
|
+
export declare function readonlyAtom<T>(atom: {
|
|
5
|
+
(): T;
|
|
6
|
+
}): ReadonlyAtom<T>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Signal } from "intentx-core-z";
|
|
2
|
+
export type AtomOptions<T> = {
|
|
3
|
+
equals?: (a: T, b: T) => boolean;
|
|
4
|
+
};
|
|
5
|
+
export type AtomMiddleware<T> = (next: T, prev: T) => T;
|
|
6
|
+
export declare function createAtomFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, options?: AtomOptions<T>) => import("./createBaseAtom").Atom<T>;
|
|
7
|
+
export declare function createAtomWithMiddlewareFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, middleware?: AtomMiddleware<T>) => import("./createBaseAtom").Atom<T>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Priority, Signal } from "intentx-core-z";
|
|
2
|
+
export type Atom<T> = Signal<T> & {
|
|
3
|
+
update(fn: (prev: T) => T, priority?: Priority): void;
|
|
4
|
+
};
|
|
5
|
+
export type AtomTransform<T> = (next: T, prev: T) => T;
|
|
6
|
+
export declare function createBaseAtomFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, transform?: AtomTransform<T>) => Atom<T>;
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export type Store<S extends object> = {
|
|
4
|
-
scope: Scope;
|
|
5
|
-
state(): S;
|
|
6
|
-
setState(fn: (s: S) => void): void;
|
|
7
|
-
subscribe(fn: Subscriber): () => void;
|
|
8
|
-
emit(type: string, payload?: any): Promise<void>;
|
|
9
|
-
on(type: string, handler: IntentHandler<S>): () => void;
|
|
10
|
-
};
|
|
1
|
+
import type { Scope } from "intentx-core-z";
|
|
2
|
+
import { Store } from "./types";
|
|
11
3
|
export declare function createStore<S extends object>(initial: S, scope?: Scope): Store<S>;
|
package/build/core/index.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export * from "./atom";
|
|
2
|
+
export * from "./asyncComputed";
|
|
3
|
+
export * from "./createAtomFactory";
|
|
3
4
|
export { asyncAtom } from "./asyncAtom";
|
|
4
|
-
export {
|
|
5
|
-
export { effect } from "
|
|
6
|
-
export
|
|
5
|
+
export { computed } from "intentx-core-z";
|
|
6
|
+
export { effect } from "intentx-core-z";
|
|
7
|
+
export * from "./watch";
|
|
7
8
|
export { createStore } from "./createStore";
|
|
8
|
-
export
|
|
9
|
-
export {
|
|
10
|
-
export type { Scope } from "./scope";
|
|
11
|
-
export { transaction } from "./transaction";
|
|
12
|
-
export { createSelector } from "./selector";
|
|
9
|
+
export * from "./selector";
|
|
10
|
+
export type { Store, Subscriber } from "./types";
|
|
13
11
|
export { factoryAtom } from "./factoryAtom";
|
|
14
|
-
export {
|
|
12
|
+
export { transaction } from "./transaction";
|
package/build/core/selector.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type EqualityFn<T> = (a: T, b: T) => boolean;
|
|
2
|
+
export declare function createSelector<S, R>(select: (state: S) => R, isEqual?: EqualityFn<R>): (state: S) => R;
|
|
3
|
+
export declare function selectAtom<T, R>(atom: () => T, selector: (value: T) => R, onChange: (value: R) => void, options?: {
|
|
4
|
+
isEqual?: (a: R, b: R) => boolean;
|
|
5
|
+
immediate?: boolean;
|
|
6
|
+
}): () => void;
|
|
7
|
+
export declare function watchSelector<S, R>(getState: () => S, subscribe: (fn: () => void) => () => void, selector: (state: S) => R, onChange: (value: R) => void, isEqual?: EqualityFn<R>): () => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntentHandler, Scope } from "intentx-core-z";
|
|
2
|
+
import { EqualityFn } from "./selector";
|
|
3
|
+
export type Subscriber = () => void;
|
|
4
|
+
export type Store<S extends object> = {
|
|
5
|
+
scope: Scope;
|
|
6
|
+
state(): S;
|
|
7
|
+
setState(fn: (s: S) => void): void;
|
|
8
|
+
subscribe(fn: Subscriber): () => void;
|
|
9
|
+
emit(type: string, payload?: any): Promise<void>;
|
|
10
|
+
on(type: string, handler: IntentHandler<S>): () => void;
|
|
11
|
+
watch<R>(selector: (state: S) => R, onChange: (value: R) => void, isEqual?: EqualityFn<R>): () => void;
|
|
12
|
+
};
|
package/build/core/watch.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import type { Priority } from "intentx-core-z";
|
|
2
|
-
export
|
|
2
|
+
export type WatchOptions<T> = {
|
|
3
|
+
immediate?: boolean;
|
|
4
|
+
equals?: (a: T, b: T) => boolean;
|
|
5
|
+
priority?: Priority;
|
|
6
|
+
};
|
|
7
|
+
export declare function watch<T>(getter: () => T, fn: (value: T, prev: T | undefined, onCleanup: (callback: () => void) => void) => void, options?: WatchOptions<T>): () => void;
|
package/build/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("intentx-core-z"),t=require("react");function
|
|
1
|
+
"use strict";var e=require("intentx-core-z"),t=require("react");function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}}),t.default=e,Object.freeze(t)}var n=r(t);function o(e){return function(t,r){const n=e(t),o=n.set;return n.set=(e,t="normal")=>{const s=n(),c=r?r(e,s):e;o(c,t)},n.update=(e,t="normal")=>{n.set(e(n()),t)},n}}function s(e){const t=o(e);return function(e,r){var n;const o=null!==(n=null==r?void 0:r.equals)&&void 0!==n?n:Object.is;return t(e,(e,t)=>o(e,t)?t:e)}}function c(e){const t=o(e);return function(e,r){return t(e,r)}}const u=s(e.signal),a=c(e.signal);function i(t,r){var n,o;const s=null!==(n=null==r?void 0:r.suspense)&&void 0!==n&&n,c=null!==(o=null==r?void 0:r.priority)&&void 0!==o?o:"normal",a=u({status:"idle"});let i=null;const l=()=>{const e=a();if("loading"===e.status)return e.promise;null==i||i.abort(),i=new AbortController;const r=t(i.signal).then(e=>(a.set({status:"success",data:e},c),e)).catch(e=>{if("AbortError"===(null==e?void 0:e.name))return Promise.resolve(void 0);throw a.set({status:"error",error:e}),e});return a.set({status:"loading",promise:r},c),r},f=()=>{null==i||i.abort()};return{read:()=>{const e=a();switch(e.status){case"success":return e.data;case"error":if(s)throw e.error;return;case"loading":if(s)throw e.promise;return;case"idle":const t=l();if(s)throw t;return}},load:l,cancel:f,invalidate:(t=c)=>{f(),a.set({status:"idle"},t),e.schedule(l,t)},status:()=>a().status,error:()=>"error"===a().status?a().error:void 0,setSuccess:(e,t=c)=>{a.set({status:"success",data:e},t)}}}function l(t,r,n){const{immediate:o=!1,equals:s=Object.is,priority:c="normal"}=null!=n?n:{};let u,a,i=!1;const l=e.effect(()=>{const e=t();if(!i)return i=!0,o&&f(e,u),void(u=e);s(e,u)||(f(e,u),u=e)},c);function f(e,t){const n=a;a=void 0,null==n||n(),r(e,t,e=>{a=e})}return()=>{null==a||a(),l()}}function f(e,t=Object.is){let r,n=!1;return o=>{const s=e(o);return n&&t(r,s)?r:(n=!0,r=s,s)}}function d(e,t,r,n,o=Object.is){const s=f(r,o);let c=!1;const u=()=>{c||n(s(e()))};u();const a=t(u);return()=>{c=!0,a()}}const p=e.createScope("default");function m(t){return n.useSyncExternalStore(r=>e.effect(()=>{t(),r()}),t,t)}Object.defineProperty(exports,"computed",{enumerable:!0,get:function(){return e.computed}}),Object.defineProperty(exports,"createScope",{enumerable:!0,get:function(){return e.createScope}}),Object.defineProperty(exports,"effect",{enumerable:!0,get:function(){return e.effect}}),Object.defineProperty(exports,"transaction",{enumerable:!0,get:function(){return e.batch}}),exports.asyncAtom=function(e,t){const r=i(e,t),n=()=>r.read();return n.load=r.load,n.cancel=r.cancel,n.invalidate=r.invalidate,n.status=r.status,n.error=r.error,n.setSuccess=e=>r.setSuccess(e),n},exports.asyncComputed=function(e,t="normal"){const r=i(e,{suspense:!0,priority:t}),n=()=>r.read();return n.invalidate=r.invalidate,n.status=r.status,n.error=r.error,n},exports.atom=u,exports.atomMiddleware=a,exports.createAtomFactory=s,exports.createAtomWithMiddlewareFactory=c,exports.createSelector=f,exports.createStore=function(t,r=p){let n=t;const o=new Set,s=e.createIntentBus((e,t)=>{const r=new AbortController;return{payload:e,scope:t,state:n,signal:r.signal,setState(e){e(n),o.forEach(e=>e())},emit:(e,r)=>s.emit(e,r,t)}});return{scope:r,state:()=>n,setState(e){e(n),o.forEach(e=>e())},subscribe:e=>(o.add(e),()=>o.delete(e)),emit:(e,t)=>s.emit(e,t,r),on:(e,t)=>s.on(e,t,r),watch:(e,t,r)=>d(()=>n,e=>(o.add(e),()=>o.delete(e)),e,t,r)}},exports.factoryAtom=function(e,t){var r;const n=null!==(r=null==t?void 0:t.weak)&&void 0!==r&&r,o=n?new WeakMap:new Map,s=t=>{const r=o.get(t);if(void 0!==r)return r;const n=e(t);return o.set(t,n),n};return s.delete=e=>{n||o.delete(e)},s.clear=()=>{n||o.clear()},s},exports.readonlyAtom=function(e){return()=>e()},exports.scheduleReactJob=function(e,r="normal"){"low"===r?t.startTransition(e):e()},exports.selectAtom=function(t,r,n,o){var s;const c=null!==(s=null==o?void 0:o.isEqual)&&void 0!==s?s:Object.is;let u;return e.effect(()=>{const e=r(t());void 0!==u&&c(u,e)||(u=e,((null==o?void 0:o.immediate)||void 0!==u)&&n(e))})},exports.useAtom=m,exports.useAtomSelector=function(r,n,o=Object.is){const s=t.useRef(f(n,o)),c=()=>s.current(r());return t.useSyncExternalStore(t=>e.effect(()=>{r(),t()}),c,c)},exports.useBatch=function(){return e.batch},exports.useComputed=function(t,r=[]){return m(n.useMemo(()=>e.computed(t),r))},exports.useEffectReact=function(t,r="normal"){const o=n.useRef(t);o.current=t,n.useEffect(()=>{const t=e.effect(()=>{o.current()},r);return()=>t()},[r])},exports.useFactoryAtom=function(e,t){const r=n.useRef(e);r.current=e;const o=n.useRef(null),s=n.useRef(null);return null!==o.current&&s.current===t||(o.current=r.current(t),s.current=t),m(o.current)},exports.useStore=function(e){return t.useSyncExternalStore(e.subscribe,e.state,e.state)},exports.useStoreSelector=function(e,t,r=Object.is){const o=n.useRef(t);o.current=t;const s=n.useRef(f(e=>o.current(e),r)),c=n.useCallback(()=>s.current(e.state()),[e]);return n.useSyncExternalStore(e.subscribe,c,c)},exports.useWatch=function(e,t,r){const o=n.useRef(t);o.current=t;const s=n.useRef(r);s.current=r,n.useEffect(()=>{const t=l(e,e=>{o.current(e)},s.current);return()=>null==t?void 0:t()},[e])},exports.watch=l,exports.watchSelector=d;
|
package/build/index.d.ts
CHANGED
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{signal as t,schedule as e,effect as n,createScope as r,createIntentBus as s,batch as o,computed as u}from"intentx-core-z";export{computed,createScope,effect,batch as transaction}from"intentx-core-z";import*as c from"react";import i,{startTransition as a}from"react";function l(t){return function(e,n){const r=t(e),s=r.set;return r.set=(t,e="normal")=>{const o=r(),u=n?n(t,o):t;s(u,e)},r.update=(t,e="normal")=>{r.set(t(r()),e)},r}}function f(t){const e=l(t);return function(t,n){var r;const s=null!==(r=null==n?void 0:n.equals)&&void 0!==r?r:Object.is;return e(t,(t,e)=>s(t,e)?e:t)}}function d(t){const e=l(t);return function(t,n){return e(t,n)}}const v=f(t),m=d(t);function p(t){return()=>t()}function b(t,n){var r,s;const o=null!==(r=null==n?void 0:n.suspense)&&void 0!==r&&r,u=null!==(s=null==n?void 0:n.priority)&&void 0!==s?s:"normal",c=v({status:"idle"});let i=null;const a=()=>{const e=c();if("loading"===e.status)return e.promise;null==i||i.abort(),i=new AbortController;const n=t(i.signal).then(t=>(c.set({status:"success",data:t},u),t)).catch(t=>{if("AbortError"===(null==t?void 0:t.name))return Promise.resolve(void 0);throw c.set({status:"error",error:t}),t});return c.set({status:"loading",promise:n},u),n},l=()=>{null==i||i.abort()};return{read:()=>{const t=c();switch(t.status){case"success":return t.data;case"error":if(o)throw t.error;return;case"loading":if(o)throw t.promise;return;case"idle":const e=a();if(o)throw e;return}},load:a,cancel:l,invalidate:(t=u)=>{l(),c.set({status:"idle"},t),e(a,t)},status:()=>c().status,error:()=>"error"===c().status?c().error:void 0,setSuccess:(t,e=u)=>{c.set({status:"success",data:t},e)}}}function S(t,e="normal"){const n=b(t,{suspense:!0,priority:e}),r=()=>n.read();return r.invalidate=n.invalidate,r.status=n.status,r.error=n.error,r}function w(t,e){const n=b(t,e),r=()=>n.read();return r.load=n.load,r.cancel=n.cancel,r.invalidate=n.invalidate,r.status=n.status,r.error=n.error,r.setSuccess=t=>n.setSuccess(t),r}function h(t,e,r){const{immediate:s=!1,equals:o=Object.is,priority:u="normal"}=null!=r?r:{};let c,i,a=!1;const l=n(()=>{const e=t();if(!a)return a=!0,s&&f(e,c),void(c=e);o(e,c)||(f(e,c),c=e)},u);function f(t,n){const r=i;i=void 0,null==r||r(),e(t,n,t=>{i=t})}return()=>{null==i||i(),l()}}function E(t,e=Object.is){let n,r=!1;return s=>{const o=t(s);return r&&e(n,o)?n:(r=!0,n=o,o)}}function R(t,e,r,s){var o;const u=null!==(o=null==s?void 0:s.isEqual)&&void 0!==o?o:Object.is;let c;return n(()=>{const n=e(t());void 0!==c&&u(c,n)||(c=n,((null==s?void 0:s.immediate)||void 0!==c)&&r(n))})}function x(t,e,n,r,s=Object.is){const o=E(n,s);let u=!1;const c=()=>{u||r(o(t()))};c();const i=e(c);return()=>{u=!0,i()}}const y=r("default");function g(t,e=y){let n=t;const r=new Set,o=s((t,e)=>{const s=new AbortController;return{payload:t,scope:e,state:n,signal:s.signal,setState(t){t(n),r.forEach(t=>t())},emit:(t,n)=>o.emit(t,n,e)}});return{scope:e,state:()=>n,setState(t){t(n),r.forEach(t=>t())},subscribe:t=>(r.add(t),()=>r.delete(t)),emit:(t,n)=>o.emit(t,n,e),on:(t,n)=>o.on(t,n,e),watch:(t,e,s)=>x(()=>n,t=>(r.add(t),()=>r.delete(t)),t,e,s)}}function j(t,e){var n;const r=null!==(n=null==e?void 0:e.weak)&&void 0!==n&&n,s=r?new WeakMap:new Map,o=e=>{const n=s.get(e);if(void 0!==n)return n;const r=t(e);return s.set(e,r),r};return o.delete=t=>{r||s.delete(t)},o.clear=()=>{r||s.clear()},o}function O(t){return c.useSyncExternalStore(e=>n(()=>{t(),e()}),t,t)}function k(t,e,r=Object.is){const s=i.useRef(E(e,r)),o=()=>s.current(t());return i.useSyncExternalStore(e=>n(()=>{t(),e()}),o,o)}function q(){return o}function A(t,e=[]){return O(c.useMemo(()=>u(t),e))}function C(t,e="normal"){const r=c.useRef(t);r.current=t,c.useEffect(()=>{const t=n(()=>{r.current()},e);return()=>t()},[e])}function M(t,e){const n=c.useRef(t);n.current=t;const r=c.useRef(null),s=c.useRef(null);return null!==r.current&&s.current===e||(r.current=n.current(e),s.current=e),O(r.current)}function z(t){return i.useSyncExternalStore(t.subscribe,t.state,t.state)}function P(t,e,n=Object.is){const r=c.useRef(e);r.current=e;const s=c.useRef(E(t=>r.current(t),n)),o=c.useCallback(()=>s.current(t.state()),[t]);return c.useSyncExternalStore(t.subscribe,o,o)}function W(t,e,n){const r=c.useRef(e);r.current=e;const s=c.useRef(n);s.current=n,c.useEffect(()=>{const e=h(t,t=>{r.current(t)},s.current);return()=>null==e?void 0:e()},[t])}function B(t,e="normal"){"low"===e?a(t):t()}export{w as asyncAtom,S as asyncComputed,v as atom,m as atomMiddleware,f as createAtomFactory,d as createAtomWithMiddlewareFactory,E as createSelector,g as createStore,j as factoryAtom,p as readonlyAtom,B as scheduleReactJob,R as selectAtom,O as useAtom,k as useAtomSelector,q as useBatch,A as useComputed,C as useEffectReact,M as useFactoryAtom,z as useStore,P as useStoreSelector,W as useWatch,h as watch,x as watchSelector};
|
package/build/react/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { useAtom } from './useAtom';
|
|
2
|
+
export { useAtomSelector } from './useAtomSelector';
|
|
3
|
+
export { useBatch } from './useBatch';
|
|
2
4
|
export { useComputed } from './useComputed';
|
|
5
|
+
export { useEffectReact } from './useEffectReact';
|
|
3
6
|
export { useFactoryAtom } from './useFactoryAtom';
|
|
4
7
|
export { useStore } from './useStore';
|
|
5
8
|
export { useStoreSelector } from './useStoreSelector';
|
|
6
9
|
export { useWatch } from './useWatch';
|
|
7
|
-
export { useEffectReact } from './useEffectReact';
|
|
8
|
-
export { useBatch } from './useBatch';
|
|
9
10
|
export { scheduleReactJob } from './schedule';
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export declare function useComputed<T>(fn: () => T, deps?: React.DependencyList): T;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function useStoreSelector<S,
|
|
1
|
+
export declare function useStoreSelector<S, R>(store: {
|
|
2
2
|
state(): S;
|
|
3
3
|
subscribe(fn: () => void): () => void;
|
|
4
|
-
}, selector: (state: S) =>
|
|
4
|
+
}, selector: (state: S) => R, isEqual?: (a: R, b: R) => boolean): R;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { WatchOptions } from "../core/watch";
|
|
2
|
+
export declare function useWatch<T>(getter: () => T, fn: (val: T) => void, options?: WatchOptions<T>): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrono-state-z",
|
|
3
|
-
"version": "2.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "A fine-grained, intent-driven reactive state runtime for building complex React logic outside components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Delpi.Kye",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -9,25 +9,13 @@
|
|
|
9
9
|
"main": "build/index.cjs.js",
|
|
10
10
|
"module": "build/index.esm.js",
|
|
11
11
|
"types": "build/index.d.ts",
|
|
12
|
-
|
|
13
12
|
"exports": {
|
|
14
13
|
".": {
|
|
15
14
|
"types": "./build/index.d.ts",
|
|
16
15
|
"import": "./build/index.esm.js",
|
|
17
16
|
"require": "./build/index.cjs.js"
|
|
18
|
-
},
|
|
19
|
-
"./react": {
|
|
20
|
-
"types": "./build/react/index.d.ts",
|
|
21
|
-
"import": "./build/react/index.esm.js",
|
|
22
|
-
"require": "./build/react/index.cjs.js"
|
|
23
|
-
},
|
|
24
|
-
"./devtools": {
|
|
25
|
-
"types": "./build/devtools/index.d.ts",
|
|
26
|
-
"import": "./build/devtools/index.esm.js",
|
|
27
|
-
"require": "./build/devtools/index.cjs.js"
|
|
28
17
|
}
|
|
29
18
|
},
|
|
30
|
-
|
|
31
19
|
"files": [
|
|
32
20
|
"build"
|
|
33
21
|
],
|
|
@@ -43,35 +31,33 @@
|
|
|
43
31
|
"type": "git",
|
|
44
32
|
"url": "https://github.com/delpikye-v/chrono-state.git"
|
|
45
33
|
},
|
|
46
|
-
|
|
47
34
|
"homepage": "https://github.com/delpikye-v/chrono-state",
|
|
48
|
-
|
|
49
35
|
"bugs": {
|
|
50
36
|
"url": "https://github.com/delpikye-v/chrono-state/issues"
|
|
51
37
|
},
|
|
52
|
-
|
|
53
38
|
"keywords": [
|
|
54
|
-
"react",
|
|
55
39
|
"state-management",
|
|
40
|
+
"react-state",
|
|
56
41
|
"reactive",
|
|
42
|
+
"fine-grained",
|
|
43
|
+
"signals",
|
|
57
44
|
"atom",
|
|
58
45
|
"computed",
|
|
59
46
|
"async-state",
|
|
60
|
-
"
|
|
47
|
+
"scheduler",
|
|
48
|
+
"deterministic",
|
|
61
49
|
"intent",
|
|
62
|
-
"intent-first",
|
|
63
50
|
"logic-first",
|
|
64
51
|
"headless",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"scheduler"
|
|
52
|
+
"react-hooks",
|
|
53
|
+
"react-18"
|
|
68
54
|
],
|
|
69
|
-
|
|
70
55
|
"peerDependencies": {
|
|
71
|
-
"react": "
|
|
72
|
-
|
|
56
|
+
"react": ">=18"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"intentx-core-z": "^2.2.1"
|
|
73
60
|
},
|
|
74
|
-
|
|
75
61
|
"devDependencies": {
|
|
76
62
|
"@rollup/plugin-commonjs": "^25.0.0",
|
|
77
63
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
package/build/core/computed.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function computed<T>(getter: () => T): () => T;
|
package/build/core/effect.d.ts
DELETED
package/build/core/graph.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export type NodeType = 'atom' | 'computed' | 'effect';
|
|
2
|
-
export type GraphNode = {
|
|
3
|
-
id: number;
|
|
4
|
-
name?: string;
|
|
5
|
-
type: NodeType;
|
|
6
|
-
value?: any;
|
|
7
|
-
deps: Set<number>;
|
|
8
|
-
highlighted?: boolean;
|
|
9
|
-
};
|
|
10
|
-
export type GraphSnapshotNode = {
|
|
11
|
-
id: number;
|
|
12
|
-
name?: string;
|
|
13
|
-
type: NodeType;
|
|
14
|
-
value?: any;
|
|
15
|
-
deps: number[];
|
|
16
|
-
highlighted?: boolean;
|
|
17
|
-
};
|
|
18
|
-
export declare function trackNode(type: NodeType, name?: string, value?: any): GraphNode;
|
|
19
|
-
export declare function linkNodes(from: GraphNode, to: GraphNode): void;
|
|
20
|
-
export declare function getGraphSnapshot(): GraphSnapshotNode[];
|
|
21
|
-
export declare function highlightNode(id: number): void;
|
|
22
|
-
export declare function clearHighlights(): void;
|
package/build/core/scope.d.ts
DELETED
package/build/core/store.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { IntentHandler } from "intentx-core-z";
|
|
2
|
-
export type Subscriber = () => void;
|
|
3
|
-
export type Store<S extends object> = {
|
|
4
|
-
state(): S;
|
|
5
|
-
setState(fn: (s: S) => void): void;
|
|
6
|
-
subscribe(fn: Subscriber): () => void;
|
|
7
|
-
emit(intent: string, payload?: any): Promise<void>;
|
|
8
|
-
on(intent: string, handler: IntentHandler<S>): () => void;
|
|
9
|
-
};
|