logic-runtime-react-z 2.0.2 → 3.1.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 +294 -241
- package/build/core/applyMiddleware.d.ts +3 -0
- package/build/core/effect.d.ts +30 -6
- package/build/core/effectMiddleware.d.ts +2 -0
- package/build/core/intentBus.d.ts +13 -0
- package/build/core/middleware.d.ts +3 -2
- package/build/core/runtime.d.ts +32 -0
- package/build/core/types.d.ts +6 -35
- package/build/devtools/devtools.d.ts +8 -6
- package/build/devtools/index.d.ts +1 -1
- package/build/index.cjs.js +1 -1
- package/build/index.d.ts +13 -15
- package/build/index.esm.js +1 -1
- package/build/logic/composeLogic.d.ts +18 -0
- package/build/logic/createBackendRuntime.d.ts +17 -0
- package/build/logic/createLogic.d.ts +28 -0
- package/build/react/useActions.d.ts +6 -0
- package/build/react/useLogicSelector.d.ts +2 -0
- package/build/react/useRuntime.d.ts +4 -0
- package/build/react/withLogic.d.ts +6 -10
- package/package.json +27 -25
- package/build/core/index.d.ts +0 -3
- package/build/core/intent.d.ts +0 -11
- package/build/plugins/index.d.ts +0 -5
- package/build/runtime/backend.d.ts +0 -29
- package/build/runtime/compose.d.ts +0 -21
- package/build/runtime/index.d.ts +0 -3
- package/build/runtime/logic.d.ts +0 -21
- package/build/state/computed.d.ts +0 -10
- package/build/state/index.d.ts +0 -4
- package/build/state/selector.d.ts +0 -1
- package/build/state/signal.d.ts +0 -6
- package/build/state/store.d.ts +0 -6
package/build/core/effect.d.ts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export type EffectStrategy = "default" | "takeLatest" | "debounce";
|
|
2
|
+
export type EffectHandler<S = any> = (context: S) => void | Promise<void>;
|
|
3
|
+
export type EffectDef<S = any> = {
|
|
4
|
+
_kind: "effect";
|
|
5
|
+
handler: EffectHandler<S>;
|
|
6
|
+
strategy: EffectStrategy;
|
|
7
|
+
wait: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function effect<S = any>(fn: EffectHandler<S>): {
|
|
10
|
+
takeLatest(): {
|
|
11
|
+
takeLatest(): any;
|
|
12
|
+
debounce(ms: number): any;
|
|
13
|
+
_kind: "effect";
|
|
14
|
+
handler: EffectHandler<S>;
|
|
15
|
+
strategy: EffectStrategy;
|
|
16
|
+
wait: number;
|
|
17
|
+
};
|
|
18
|
+
debounce(ms: number): {
|
|
19
|
+
takeLatest(): any;
|
|
20
|
+
debounce(ms: number): any;
|
|
21
|
+
_kind: "effect";
|
|
22
|
+
handler: EffectHandler<S>;
|
|
23
|
+
strategy: EffectStrategy;
|
|
24
|
+
wait: number;
|
|
25
|
+
};
|
|
26
|
+
_kind: "effect";
|
|
27
|
+
handler: EffectHandler<S>;
|
|
28
|
+
strategy: EffectStrategy;
|
|
29
|
+
wait: number;
|
|
30
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IntentMiddleware } from "./middleware";
|
|
2
|
+
import { RuntimeIntentContext } from "./types";
|
|
3
|
+
import { EffectDef } from "./effect";
|
|
4
|
+
export type IntentHandler<S, P = any> = (context: RuntimeIntentContext<S, P>) => void | Promise<void>;
|
|
5
|
+
export declare class IntentBus<S> {
|
|
6
|
+
private handlers;
|
|
7
|
+
private effects;
|
|
8
|
+
private middlewares;
|
|
9
|
+
use(mw: IntentMiddleware<S>): void;
|
|
10
|
+
effect(type: string, eff: EffectDef): void;
|
|
11
|
+
on<P = any>(type: string, handler: IntentHandler<S, P>): void;
|
|
12
|
+
emit(type: string, context: RuntimeIntentContext<S>): Promise<void>;
|
|
13
|
+
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { RuntimeIntentContext } from "./types";
|
|
2
|
+
export type IntentNext<S> = (context: RuntimeIntentContext<S>) => Promise<void>;
|
|
3
|
+
export type IntentMiddleware<S> = (next: IntentNext<S>) => IntentNext<S>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Atom } from "chrono-state-z/build/core/atom";
|
|
2
|
+
import { Scope } from "intentx-core-z";
|
|
3
|
+
import { EffectDef } from "./effect";
|
|
4
|
+
export type AtomAccessor<T> = Atom<T>;
|
|
5
|
+
export declare class LogicRuntime<S extends object, A extends Record<string, any> = {}> {
|
|
6
|
+
readonly scope: Scope;
|
|
7
|
+
private atoms;
|
|
8
|
+
private subs;
|
|
9
|
+
private bus;
|
|
10
|
+
private snapshotCache;
|
|
11
|
+
private dirty;
|
|
12
|
+
private isComputing;
|
|
13
|
+
actions: A;
|
|
14
|
+
constructor(initial: S, scope?: Scope);
|
|
15
|
+
private createAtoms;
|
|
16
|
+
private buildSnapshot;
|
|
17
|
+
private markDirty;
|
|
18
|
+
getSnapshot: () => Readonly<S>;
|
|
19
|
+
subscribe: (fn: () => void) => () => boolean;
|
|
20
|
+
private setStateInternal;
|
|
21
|
+
onIntent: <P = any>(type: string, handler: (context: {
|
|
22
|
+
payload: P;
|
|
23
|
+
state: () => Readonly<S>;
|
|
24
|
+
scope: Scope;
|
|
25
|
+
signal: AbortSignal;
|
|
26
|
+
setState(fn: (draft: S) => void): void;
|
|
27
|
+
emit<T = any>(type: string, payload?: T): Promise<void>;
|
|
28
|
+
}) => any) => void;
|
|
29
|
+
useEffect(type: string, eff: EffectDef): void;
|
|
30
|
+
emit: <P = any>(type: string, payload?: P) => Promise<void>;
|
|
31
|
+
attachComputed<K extends string, T>(key: K, compute: () => T): void;
|
|
32
|
+
}
|
package/build/core/types.d.ts
CHANGED
|
@@ -1,38 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
export type
|
|
3
|
-
export type EffectCtx<W = any, R = W, P = any> = {
|
|
4
|
-
state: Readonly<R>;
|
|
1
|
+
import { Scope } from "intentx-core-z";
|
|
2
|
+
export type RuntimeIntentContext<S, P = any> = {
|
|
5
3
|
payload: P;
|
|
4
|
+
state: () => Readonly<S>;
|
|
5
|
+
scope: Scope;
|
|
6
6
|
signal: AbortSignal;
|
|
7
|
-
|
|
8
|
-
emit(
|
|
9
|
-
setState: (fn: (s: W) => void) => void;
|
|
10
|
-
};
|
|
11
|
-
export type EmitHookCtx<S = any, C = any, P = any> = {
|
|
12
|
-
intent: string;
|
|
13
|
-
payload: P;
|
|
14
|
-
state: Readonly<S & C>;
|
|
15
|
-
scope: string;
|
|
16
|
-
};
|
|
17
|
-
export type IntentHandler<W = any, R = W, P = any> = (ctx: EffectCtx<W, R, P>) => void | Promise<void>;
|
|
18
|
-
export type Effect<W = any, R = W, P = any> = (next: IntentHandler<W, R, P>) => IntentHandler<W, R, P>;
|
|
19
|
-
export type IntentMiddleware<W = any, R = W, P = any> = (ctx: EffectCtx<W, R, P>, next: () => Promise<void>) => Promise<void>;
|
|
20
|
-
export type LogicRuntime<S extends object, C extends object = {}> = {
|
|
21
|
-
scope: string;
|
|
22
|
-
state(): Readonly<S & C>;
|
|
23
|
-
setState(mutator: (s: S) => void): void;
|
|
24
|
-
reset(): void;
|
|
25
|
-
batch(fn: () => void): void;
|
|
26
|
-
emit(intent: string, payload?: any): Promise<void>;
|
|
27
|
-
effect(intent: string, fx: Effect<S, S & C>): void;
|
|
28
|
-
use(mw: IntentMiddleware<S, S & C>): void;
|
|
29
|
-
subscribe(fn: Listener): () => void;
|
|
30
|
-
onIntent(intent: string, handler: IntentHandler<S, S & C>): void;
|
|
31
|
-
devtools?: {
|
|
32
|
-
timeline: Timeline;
|
|
33
|
-
};
|
|
34
|
-
__internal: {
|
|
35
|
-
onEmitStart(fn: (ctx: EmitHookCtx<S, S & C, any>) => void): void;
|
|
36
|
-
onEmitEnd(fn: (ctx: EmitHookCtx<S, S & C, any>) => void): void;
|
|
37
|
-
};
|
|
7
|
+
setState(fn: (draft: S) => void): void;
|
|
8
|
+
emit<T = any>(type: string, payload?: T): Promise<void>;
|
|
38
9
|
};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Timeline } from "./timeline";
|
|
2
|
-
export type Devtools = {
|
|
3
|
-
timeline: Timeline;
|
|
4
|
-
wrap(runtime: RuntimeLike): void;
|
|
5
|
-
};
|
|
6
2
|
type RuntimeLike = {
|
|
7
|
-
scope:
|
|
8
|
-
|
|
3
|
+
scope: {
|
|
4
|
+
name: string;
|
|
5
|
+
} | string;
|
|
6
|
+
getSnapshot(): any;
|
|
9
7
|
emit(intent: string, payload?: any): Promise<void>;
|
|
10
8
|
};
|
|
9
|
+
export type Devtools = {
|
|
10
|
+
timeline: Timeline;
|
|
11
|
+
wrap(): void;
|
|
12
|
+
};
|
|
11
13
|
export declare function attachDevtools(target: RuntimeLike): Devtools;
|
|
12
14
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { attachDevtools } from "./devtools";
|
|
2
|
-
export
|
|
2
|
+
export type { Timeline, IntentRecord, IntentRecordType, } from "./timeline";
|
package/build/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("react/jsx-runtime");function
|
|
1
|
+
"use strict";var t=require("chrono-state-z"),e=require("intentx-core-z"),n=require("react/jsx-runtime"),s=require("react");function o(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(n){if("default"!==n){var s=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,s.get?s:{enumerable:!0,get:function(){return t[n]}})}}),e.default=t,Object.freeze(e)}var r=o(s);class i{constructor(){this.handlers={},this.effects={},this.middlewares=[]}use(t){this.middlewares.push(t)}effect(t,e){var n,s;(null!==(n=(s=this.effects)[t])&&void 0!==n?n:s[t]=[]).push(e)}on(t,e){var n,s;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!==(n=(s=this.handlers)[t])&&void 0!==n?n:s[t]=[]).push(e)}async emit(t,e){var n,s;const o=null!==(n=this.handlers[t])&&void 0!==n?n:[],r=null!==(s=this.effects[t])&&void 0!==s?s:[],i=(a=this.middlewares,c=async t=>{t.effects=r;for(const e of o)await e(t)},a.reduceRight((t,e)=>e(t),c));var a,c;await i(e)}}class a{constructor(t,n=e.createScope("logic")){this.subs=new Set,this.bus=new i,this.dirty=!0,this.isComputing=!1,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 n=new AbortController;await this.bus.emit(t,{payload:e,scope:this.scope,signal:n.signal,state:this.getSnapshot,setState:t=>this.setStateInternal(t),emit:this.emit})},this.scope=n,this.atoms=this.createAtoms(t);for(const t in this.atoms)this.atoms[t].subscribe(this.markDirty);this.bus.use(function(){const t=new Map,e=new Map;return n=>async s=>{var o;const r=s.effects;if(!(null==r?void 0:r.length))return n(s);for(const n of r){const r=n.handler.toString();if("takeLatest"===n.strategy){null===(o=t.get(r))||void 0===o||o.abort();const e=new AbortController;t.set(r,e),await n.handler({...s,signal:e.signal})}else"debounce"===n.strategy?(clearTimeout(e.get(r)),e.set(r,setTimeout(()=>n.handler(s),n.wait))):await n.handler(s)}await n(s)}}())}createAtoms(e){const n={};for(const s in e)n[s]=t.atom(e[s]);return n}buildSnapshot(){const t={};for(const e in this.atoms)t[e]=this.atoms[e]();return t}setStateInternal(t){this.isComputing&&console.warn("[logic-runtime] Side-effect detected: setState() called inside computed()");const e=this.buildSnapshot();t(e);for(const t in e)e[t]!==this.atoms[t]()&&this.atoms[t].set(e[t])}useEffect(t,e){this.bus.effect(t,e)}attachComputed(e,n){const s=t.atom(void 0);t.effect(()=>{this.isComputing=!0;const t=n();s.set(t),this.isComputing=!1}),this.atoms[e]=s,s.subscribe(this.markDirty)}}function c(t){const e=function(){let t=0,e=[];return{get records(){return e.slice()},record:function(n){e.push({...n,id:++t,state:structuredClone(n.state)})},replay:async function(t,n){const{from:s=0,to:o=1/0,scope:r}=null!=n?n:{},i=e.filter(t=>"emit"===t.type&&t.id>=s&&t.id<=o&&(!r||t.scope===r));for(const e of i){const n=t(e.intent,e.payload);n instanceof Promise&&await n}},clear:function(){e=[],t=0}}}();function n(){return"string"==typeof t.scope?t.scope:t.scope.name}return{timeline:e,wrap:function(){const s=t.emit.bind(t);t.emit=async(o,r)=>{e.record({type:"emit:start",intent:o,payload:r,scope:n(),state:t.getSnapshot(),timestamp:Date.now()});try{const t=s(o,r);t instanceof Promise&&await t}finally{e.record({type:"emit:end",intent:o,payload:r,scope:n(),state:t.getSnapshot(),timestamp:Date.now()})}}}}}function u(t){var n;const o=s.useRef(null),r=null!=t&&"function"==typeof t.subscribe&&"function"==typeof t.getSnapshot?t:null!==(n=o.current)&&void 0!==n?n:o.current=t.create(e.createScope("react"));return s.useSyncExternalStore(r.subscribe,r.getSnapshot,r.getSnapshot)}Object.defineProperty(exports,"createSelector",{enumerable:!0,get:function(){return t.createSelector}}),exports.LogicRuntime=a,exports.attachDevtools=c,exports.composeLogic=function(t){return{create(e){const n={};for(const s in t){const o=s;n[o]=t[o].create(e)}return{async emit(t,e){for(const s of Object.values(n))await s.emit(t,e)},subscribe(t){const e=Object.values(n).map(e=>e.subscribe(t));return()=>e.forEach(t=>t())},getSnapshot(){const t={};for(const e in n)t[e]=n[e].getSnapshot();return t},runtimes:n}}}},exports.createBackendRuntime=function(t){var n,s;let o=structuredClone(t);const r=()=>o,i=t=>{o={...o,...t}},a=e.createScope("backend");async function u(t,e){await l.emit(t,e,a)}const l=e.createIntentBus(t=>{const e=new AbortController;return{scope:a,payload:t,signal:e.signal,get state(){return r()},setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}}),h={state:r,reset:()=>{o=structuredClone(t)},emit:u,registerIntents:function(t){for(const e in t){const n=t[e];l.on(e,async(t,e)=>{var s;const o={get state(){return r()},signal:null!==(s=t.signal)&&void 0!==s?s:(new AbortController).signal,set:i,emit:u};await n(o)},a)}},onIntent:l.on,effect:l.effect};if("production"!==(null===(s=null===(n=null===globalThis||void 0===globalThis?void 0:globalThis.process)||void 0===n?void 0:n.env)||void 0===s?void 0:s.NODE_ENV)){const t=c(h);t.wrap(h),h.devtools=t}return h},exports.createLogic=function(t){return{name:t.name,create(e){var n;const s=new a(structuredClone(t.state),e);if(t.computed)for(const e in t.computed)s.attachComputed(e,()=>t.computed[e]({state:s.getSnapshot()}));null===(n=t.intents)||void 0===n||n.call(t,{on:s.onIntent,effect:s.useEffect.bind(s)});const o={};if(t.actions)for(const e in t.actions)o[e]=t.actions[e]({emit:s.emit,getState:s.getSnapshot});return s.actions=o,s}}},exports.effect=function(t){const e={_kind:"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.useActions=function(t){return(null!=t&&"actions"in t?t:u(t)).actions},exports.useLogicSelector=function(e,n){const o=s.useMemo(()=>t.createSelector(n),[n]);return s.useSyncExternalStore(e.subscribe,()=>o(e.getSnapshot()),()=>o(e.getSnapshot()))},exports.useRuntime=u,exports.withLogic=function(t,s,o){var i,a;const c=i=>{const a=r.useRef(null);a.current||(a.current=t.create("string"==typeof o?e.createScope(o):o));const c=a.current,u=r.useSyncExternalStore(c.subscribe,c.getSnapshot,c.getSnapshot),l=r.useCallback((t,e)=>c.emit(t,e),[c]),h=r.useMemo(()=>({state:u,actions:c.actions,emit:l}),[u,l,c]);return n.jsx(s,{...i,...h})};return c.displayName=`withLogic(${null!==(a=null!==(i=s.displayName)&&void 0!==i?i:s.name)&&void 0!==a?a:"View"})`,c};
|
package/build/index.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export
|
|
10
|
-
export { effect, takeLatest, debounce, retry, composeEffects } from "./core/effect";
|
|
11
|
-
export { createIntentBus } from "./core/intent";
|
|
12
|
-
export { compose as composeMiddleware } from "./core/middleware";
|
|
13
|
-
export type { LogicRuntime, IntentHandler, Effect, EffectCtx, IntentMiddleware, Listener, } from "./core/types";
|
|
14
|
-
export { attachDevtools } from "./devtools/devtools";
|
|
15
|
-
export type { Timeline, IntentRecord, } from "./devtools/timeline";
|
|
1
|
+
export { createSelector } from "chrono-state-z";
|
|
2
|
+
export { LogicRuntime } from "./core/runtime";
|
|
3
|
+
export type { AtomAccessor } from "./core/runtime";
|
|
4
|
+
export { effect } from "./core/effect";
|
|
5
|
+
export type { IntentMiddleware, IntentNext, } from "./core/middleware";
|
|
6
|
+
export { createLogic } from "./logic/createLogic";
|
|
7
|
+
export type { LogicFactory, LogicActions, } from "./logic/createLogic";
|
|
8
|
+
export { composeLogic } from "./logic/composeLogic";
|
|
9
|
+
export { createBackendRuntime } from "./logic/createBackendRuntime";
|
|
16
10
|
export { withLogic } from "./react/withLogic";
|
|
11
|
+
export { useRuntime } from "./react/useRuntime";
|
|
12
|
+
export { useActions } from "./react/useActions";
|
|
13
|
+
export { useLogicSelector } from "./react/useLogicSelector";
|
|
14
|
+
export * from "./devtools";
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{atom as t,effect as e,createSelector as s}from"chrono-state-z";export{createSelector}from"chrono-state-z";import{createScope as n,createIntentBus as o}from"intentx-core-z";import{jsx as i}from"react/jsx-runtime";import*as r from"react";import{useRef as a,useSyncExternalStore as c,useMemo as u}from"react";class l{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 h{constructor(t,e=n("logic")){this.subs=new Set,this.bus=new l,this.dirty=!0,this.isComputing=!1,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.atoms=this.createAtoms(t);for(const t in this.atoms)this.atoms[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.handler.toString();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)}}())}createAtoms(e){const s={};for(const n in e)s[n]=t(e[n]);return s}buildSnapshot(){const t={};for(const e in this.atoms)t[e]=this.atoms[e]();return t}setStateInternal(t){this.isComputing&&console.warn("[logic-runtime] Side-effect detected: setState() called inside computed()");const e=this.buildSnapshot();t(e);for(const t in e)e[t]!==this.atoms[t]()&&this.atoms[t].set(e[t])}useEffect(t,e){this.bus.effect(t,e)}attachComputed(s,n){const o=t(void 0);e(()=>{this.isComputing=!0;const t=n();o.set(t),this.isComputing=!1}),this.atoms[s]=o,o.subscribe(this.markDirty)}}function f(t){const e={_kind:"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 d(t){return{name:t.name,create(e){var s;const n=new h(structuredClone(t.state),e);if(t.computed)for(const e in t.computed)n.attachComputed(e,()=>t.computed[e]({state:n.getSnapshot()}));null===(s=t.intents)||void 0===s||s.call(t,{on:n.onIntent,effect:n.useEffect.bind(n)});const o={};if(t.actions)for(const e in t.actions)o[e]=t.actions[e]({emit:n.emit,getState:n.getSnapshot});return n.actions=o,n}}}function m(t){return{create(e){const s={};for(const n in t){const o=n;s[o]=t[o].create(e)}return{async emit(t,e){for(const n of Object.values(s))await n.emit(t,e)},subscribe(t){const e=Object.values(s).map(e=>e.subscribe(t));return()=>e.forEach(t=>t())},getSnapshot(){const t={};for(const e in s)t[e]=s[e].getSnapshot();return t},runtimes:s}}}}function p(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()})}}}}}function g(t){var e,s;let i=structuredClone(t);const r=()=>i,a=t=>{i={...i,...t}},c=n("backend");async function u(t,e){await l.emit(t,e,c)}const l=o(t=>{const e=new AbortController;return{scope:c,payload:t,signal:e.signal,get state(){return r()},setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}});const h={state:r,reset:()=>{i=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 r()},signal:null!==(n=t.signal)&&void 0!==n?n:(new AbortController).signal,set:a,emit:u};await s(o)},c)}},onIntent:l.on,effect:l.effect};if("production"!==(null===(s=null===(e=null===globalThis||void 0===globalThis?void 0:globalThis.process)||void 0===e?void 0:e.env)||void 0===s?void 0:s.NODE_ENV)){const t=p(h);t.wrap(h),h.devtools=t}return h}function b(t,e,s){var o,a;const c=o=>{const a=r.useRef(null);a.current||(a.current=t.create("string"==typeof s?n(s):s));const c=a.current,u=r.useSyncExternalStore(c.subscribe,c.getSnapshot,c.getSnapshot),l=r.useCallback((t,e)=>c.emit(t,e),[c]),h=r.useMemo(()=>({state:u,actions:c.actions,emit:l}),[u,l,c]);return i(e,{...o,...h})};return c.displayName=`withLogic(${null!==(a=null!==(o=e.displayName)&&void 0!==o?o:e.name)&&void 0!==a?a:"View"})`,c}function y(t){var e;const s=a(null),o=null!=t&&"function"==typeof t.subscribe&&"function"==typeof t.getSnapshot?t:null!==(e=s.current)&&void 0!==e?e:s.current=t.create(n("react"));return c(o.subscribe,o.getSnapshot,o.getSnapshot)}function w(t){return(null!=t&&"actions"in t?t:y(t)).actions}function v(t,e){const n=u(()=>s(e),[e]);return c(t.subscribe,()=>n(t.getSnapshot()),()=>n(t.getSnapshot()))}export{h as LogicRuntime,p as attachDevtools,m as composeLogic,g as createBackendRuntime,d as createLogic,f as effect,w as useActions,v as useLogicSelector,y as useRuntime,b as withLogic};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LogicRuntime } from "../core/runtime";
|
|
2
|
+
import type { LogicFactory } from "../logic/createLogic";
|
|
3
|
+
type LogicMap = Record<string, LogicFactory<any, any>>;
|
|
4
|
+
type RuntimeMap<M extends LogicMap> = {
|
|
5
|
+
[K in keyof M]: ReturnType<M[K]["create"]>;
|
|
6
|
+
};
|
|
7
|
+
type SnapshotOf<M extends LogicMap> = {
|
|
8
|
+
[K in keyof M]: ReturnType<M[K]["create"]> extends LogicRuntime<infer S extends object, any> ? Readonly<S> : never;
|
|
9
|
+
};
|
|
10
|
+
export declare function composeLogic<M extends LogicMap>(logics: M): {
|
|
11
|
+
create(scope?: any): {
|
|
12
|
+
emit(intent: string, payload?: any): Promise<void>;
|
|
13
|
+
subscribe(fn: () => void): () => void;
|
|
14
|
+
getSnapshot(): SnapshotOf<M>;
|
|
15
|
+
runtimes: RuntimeMap<M>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Scope } from "intentx-core-z";
|
|
2
|
+
export type BackendContext<S> = {
|
|
3
|
+
state: Readonly<S>;
|
|
4
|
+
set(patch: Partial<S>): void;
|
|
5
|
+
emit(intent: string, payload?: any): Promise<void>;
|
|
6
|
+
signal: AbortSignal;
|
|
7
|
+
};
|
|
8
|
+
export type BackendIntent<S> = (context: BackendContext<S>) => void | Promise<void>;
|
|
9
|
+
export type BackendIntents<S> = Record<string, BackendIntent<S>>;
|
|
10
|
+
export declare function createBackendRuntime<S extends object>(initial: S): {
|
|
11
|
+
state: () => Readonly<S>;
|
|
12
|
+
reset: () => void;
|
|
13
|
+
emit: (intent: string, payload?: any) => Promise<void>;
|
|
14
|
+
registerIntents: (intents: BackendIntents<S>) => void;
|
|
15
|
+
onIntent: (type: string, h: import("intentx-core-z").IntentHandler<S>, scope?: Scope) => () => void;
|
|
16
|
+
effect: (type: string, fx: import("intentx-core-z/build/intent/types").IntentEffect<S>, scope?: Scope) => () => void;
|
|
17
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Scope } from "intentx-core-z";
|
|
2
|
+
import { LogicRuntime } from "../core/runtime";
|
|
3
|
+
import { EffectDef } from "../core/effect";
|
|
4
|
+
type ComputedFactory<S> = (context: {
|
|
5
|
+
state: Readonly<S>;
|
|
6
|
+
}) => any;
|
|
7
|
+
type ActionFactory<S extends object, Fn extends (...args: any[]) => any> = (context: {
|
|
8
|
+
emit: LogicRuntime<S, any>["emit"];
|
|
9
|
+
getState: () => Readonly<S>;
|
|
10
|
+
}) => Fn;
|
|
11
|
+
export type LogicActions = Record<string, (...args: any[]) => any>;
|
|
12
|
+
export type LogicFactory<S extends object, A extends LogicActions> = {
|
|
13
|
+
name?: string;
|
|
14
|
+
create(scope?: Scope): LogicRuntime<S, A>;
|
|
15
|
+
};
|
|
16
|
+
export declare function createLogic<S extends object, A extends LogicActions>(config: {
|
|
17
|
+
name?: string;
|
|
18
|
+
state: S;
|
|
19
|
+
computed?: Record<string, ComputedFactory<S>>;
|
|
20
|
+
intents?: (bus: {
|
|
21
|
+
on: LogicRuntime<S>["onIntent"];
|
|
22
|
+
effect: (type: string, eff: EffectDef) => void;
|
|
23
|
+
}) => void;
|
|
24
|
+
actions?: {
|
|
25
|
+
[K in keyof A]: ActionFactory<S, A[K]>;
|
|
26
|
+
};
|
|
27
|
+
}): LogicFactory<S, A>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { LogicActions, LogicFactory } from "../logic/createLogic";
|
|
2
|
+
import { LogicRuntime } from "../core/runtime";
|
|
3
|
+
export declare function useActions<A extends object>(runtime: LogicRuntime<any> & {
|
|
4
|
+
actions: A;
|
|
5
|
+
}): A;
|
|
6
|
+
export declare function useActions<S extends object, A extends LogicActions>(logic: LogicFactory<S, A>): A;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { LogicRuntime } from "../core/runtime";
|
|
2
|
+
import { LogicFactory } from "../logic/createLogic";
|
|
3
|
+
export declare function useRuntime<S extends object>(runtime: LogicRuntime<S>): Readonly<S>;
|
|
4
|
+
export declare function useRuntime<S extends object, A extends Record<string, any>>(logic: LogicFactory<S, A>): Readonly<S>;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
subscribe(fn: () => void): () => void;
|
|
6
|
-
};
|
|
7
|
-
type LogicFactory<S> = {
|
|
8
|
-
create(scope?: string): LogicInstance<S>;
|
|
9
|
-
};
|
|
10
|
-
export declare function withLogic<S, P extends object>(logic: LogicFactory<S>, View: React.ComponentType<P & {
|
|
2
|
+
import { Scope } from "intentx-core-z";
|
|
3
|
+
import { LogicActions, LogicFactory } from "../logic/createLogic";
|
|
4
|
+
type InjectedProps<S extends object, A extends LogicActions> = {
|
|
11
5
|
state: Readonly<S>;
|
|
6
|
+
actions: A;
|
|
12
7
|
emit: (intent: string, payload?: any) => Promise<void>;
|
|
13
|
-
}
|
|
8
|
+
};
|
|
9
|
+
export declare function withLogic<S extends object, A extends LogicActions, P extends object>(logic: LogicFactory<S, A>, View: React.ComponentType<P & InjectedProps<S, A>>, scope?: Scope | string): React.FC<Omit<P, keyof InjectedProps<S, A>>>;
|
|
14
10
|
export {};
|
package/package.json
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logic-runtime-react-z",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Intent-first
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "Intent-first business logic runtime. Headless and backend-friendly. Deterministic state, computed graph, and orchestrated async effects. React is just a view layer.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Delpi.Kye",
|
|
7
|
-
|
|
8
7
|
"sideEffects": false,
|
|
9
|
-
|
|
10
8
|
"main": "build/index.cjs.js",
|
|
11
9
|
"module": "build/index.esm.js",
|
|
12
10
|
"types": "build/index.d.ts",
|
|
13
|
-
|
|
14
11
|
"exports": {
|
|
15
12
|
".": {
|
|
16
13
|
"types": "./build/index.d.ts",
|
|
@@ -28,57 +25,62 @@
|
|
|
28
25
|
"require": "./build/devtools/index.cjs.js"
|
|
29
26
|
}
|
|
30
27
|
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
"files": [
|
|
29
|
+
"build"
|
|
30
|
+
],
|
|
34
31
|
"scripts": {
|
|
35
32
|
"clean": "rimraf build",
|
|
36
33
|
"build": "rollup -c",
|
|
37
34
|
"cb": "npm run clean && npm run build",
|
|
38
35
|
"prepublishOnly": "npm run cb"
|
|
39
36
|
},
|
|
40
|
-
|
|
41
37
|
"repository": {
|
|
42
38
|
"type": "git",
|
|
43
39
|
"url": "https://github.com/delpikye-v/logic-runtime-react.git"
|
|
44
40
|
},
|
|
45
|
-
|
|
46
41
|
"homepage": "https://github.com/delpikye-v/logic-runtime-react#readme",
|
|
47
42
|
"bugs": {
|
|
48
43
|
"url": "https://github.com/delpikye-v/logic-runtime-react/issues"
|
|
49
44
|
},
|
|
50
|
-
|
|
51
45
|
"keywords": [
|
|
52
|
-
"
|
|
53
|
-
"react-no-hook",
|
|
54
|
-
"external-store",
|
|
46
|
+
"intent-first",
|
|
55
47
|
"intent-runtime",
|
|
48
|
+
"business-logic",
|
|
56
49
|
"logic-runtime",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
50
|
+
"headless",
|
|
51
|
+
"backend-friendly",
|
|
52
|
+
"ui-agnostic",
|
|
53
|
+
"react",
|
|
59
54
|
"react-architecture",
|
|
60
|
-
"
|
|
55
|
+
"no-hooks",
|
|
56
|
+
"external-store",
|
|
57
|
+
"computed-state",
|
|
58
|
+
"derived-state",
|
|
59
|
+
"async-effects",
|
|
60
|
+
"takeLatest",
|
|
61
|
+
"state-management"
|
|
61
62
|
],
|
|
62
|
-
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"react": ">=18.0.0",
|
|
65
65
|
"react-dom": ">=18.0.0"
|
|
66
66
|
},
|
|
67
|
-
|
|
68
67
|
"devDependencies": {
|
|
69
68
|
"@rollup/plugin-commonjs": "^25.0.0",
|
|
70
69
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
71
70
|
"@rollup/plugin-terser": "^0.4.4",
|
|
71
|
+
"@types/react": "^18.2.43",
|
|
72
|
+
"@types/react-dom": "^18.2.17",
|
|
73
|
+
"react": "^18.2.0",
|
|
74
|
+
"react-dom": "^18.2.0",
|
|
72
75
|
"rimraf": "^5.0.5",
|
|
73
76
|
"rollup": "^4.9.6",
|
|
74
77
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
75
78
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
76
|
-
"typescript": "^5.3.3",
|
|
77
79
|
"tslib": "^2.6.2",
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
"
|
|
80
|
+
"typescript": "^5.3.3"
|
|
81
|
+
},
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"chrono-state-z": "^2.1.0",
|
|
84
|
+
"intentx-core-z": "^2.1.0"
|
|
83
85
|
}
|
|
84
86
|
}
|
package/build/core/index.d.ts
DELETED
package/build/core/intent.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { IntentHandler, Effect, IntentMiddleware } from "./types";
|
|
2
|
-
export declare function createIntentBus<W extends object, R extends object = W, P = any>(scope: string): {
|
|
3
|
-
on: (intent: string, handler: IntentHandler<W, R, P>) => void;
|
|
4
|
-
effect: (intent: string, fx: Effect<W, R, P>) => void;
|
|
5
|
-
use: (mw: IntentMiddleware<W, R, P>) => void;
|
|
6
|
-
emit: (intent: string, payload: P, ctx: {
|
|
7
|
-
getState(): R;
|
|
8
|
-
setState(fn: (s: W) => void): void;
|
|
9
|
-
emit(intent: string, payload?: any): Promise<void>;
|
|
10
|
-
}) => Promise<void>;
|
|
11
|
-
};
|
package/build/plugins/index.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export type SimpleBackendCtx<S> = {
|
|
2
|
-
state: Readonly<S>;
|
|
3
|
-
set: (patch: Partial<S>) => void;
|
|
4
|
-
emit: (intent: string, payload?: any) => Promise<void>;
|
|
5
|
-
signal: AbortSignal;
|
|
6
|
-
};
|
|
7
|
-
export declare function createBackendRuntime<S extends object>(initial: S): {
|
|
8
|
-
state(): S;
|
|
9
|
-
setState: (mutator: (s: S) => void) => void;
|
|
10
|
-
batch: (fn: () => void) => void;
|
|
11
|
-
emit(intent: string, payload?: any): Promise<void>;
|
|
12
|
-
onIntent: (intent: string, handler: import("../core").IntentHandler<S, S, any>) => void;
|
|
13
|
-
effect: (intent: string, fx: import("../core").Effect<S, S, any>) => void;
|
|
14
|
-
use: (mw: import("../core").IntentMiddleware<S, S, any>) => void;
|
|
15
|
-
registerIntents: (intentsObj: Record<string, (ctx: SimpleBackendCtx<S>) => void | Promise<void>>) => void;
|
|
16
|
-
__internal: {
|
|
17
|
-
onEmitStart(fn: (ctx: {
|
|
18
|
-
intent: string;
|
|
19
|
-
payload: any;
|
|
20
|
-
state: S;
|
|
21
|
-
}) => void): void;
|
|
22
|
-
onEmitEnd(fn: (ctx: {
|
|
23
|
-
intent: string;
|
|
24
|
-
payload: any;
|
|
25
|
-
state: S;
|
|
26
|
-
}) => void): void;
|
|
27
|
-
};
|
|
28
|
-
reset: () => void;
|
|
29
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
type LogicInstance = {
|
|
2
|
-
state(): any;
|
|
3
|
-
emit?: (intent: string, payload?: any) => Promise<any> | any;
|
|
4
|
-
subscribe(fn: () => void): () => void;
|
|
5
|
-
};
|
|
6
|
-
type ComposedLogic = {
|
|
7
|
-
create(scope?: string): LogicInstance;
|
|
8
|
-
} | {
|
|
9
|
-
namespace?: string;
|
|
10
|
-
logic: {
|
|
11
|
-
create(scope?: string): LogicInstance;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
export declare function composeLogic(...entries: ComposedLogic[]): {
|
|
15
|
-
create(scope?: string): {
|
|
16
|
-
readonly state: any;
|
|
17
|
-
emit(intent: string, payload?: any): Promise<void>;
|
|
18
|
-
subscribe(fn: () => void): () => void;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
export {};
|
package/build/runtime/index.d.ts
DELETED