logic-runtime-react-z 2.0.2 → 3.0.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 +265 -242
- 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 +11 -15
- package/build/index.esm.js +1 -1
- package/build/logic/composeLogic.d.ts +16 -0
- package/build/logic/createBackendRuntime.d.ts +17 -0
- package/build/logic/createLogic.d.ts +28 -0
- package/build/react/useActions.d.ts +5 -0
- package/build/react/useRuntime.d.ts +4 -0
- package/build/react/useSelector.d.ts +2 -0
- package/build/react/withLogic.d.ts +6 -10
- package/package.json +31 -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/signal.d.ts +0 -6
- package/build/state/store.d.ts +0 -6
- /package/build/{state → react}/selector.d.ts +0 -0
|
@@ -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"),s=require("react"),n=require("react/jsx-runtime");function o(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 i=o(s);class r{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 a{constructor(t,s=e.createScope("logic")){this.subs=new Set,this.bus=new r,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=s,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.atom(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(e,s){const n=t.atom(void 0);t.effect(()=>{this.isComputing=!0;const t=s();n.set(t),this.isComputing=!1}),this.atoms[e]=n,n.subscribe(this.markDirty)}}function c(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 u(t){if(t instanceof a)return s.useSyncExternalStore(t.subscribe,t.getSnapshot,t.getSnapshot);const n=t.create(e.createScope("react"));return s.useSyncExternalStore(n.subscribe,n.getSnapshot,n.getSnapshot)}exports.LogicRuntime=a,exports.attachDevtools=c,exports.composeLogic=function(t){return{create(){const e={};for(const s in t){const n=s;e[n]=t[n].create()}return{async emit(t,s){for(const n of Object.values(e))await n.emit(t,s)},subscribe(t){const s=Object.values(e).map(e=>e.subscribe(t));return()=>s.forEach(t=>t())},getSnapshot(){const t={};for(const s in e)t[s]=e[s].getSnapshot();return t}}}}},exports.createBackendRuntime=function(t){var s,n;let o=structuredClone(t);const i=()=>structuredClone(o),r=t=>{o=Object.assign(i(),t)},a=e.createScope("backend");async function u(t,e){await l.emit(t,e,a)}const l=e.createIntentBus(t=>({payload:t,signal:(new AbortController).signal,state:i(),setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}));function h(t,e,s){return{intent:t,payload:e,state:s.state,signal:s.signal,set:r,emit:u}}function f(t){return{state:t.state,signal:t.signal,set:t.set,emit:t.emit}}const d={state:()=>o,reset:()=>{o=structuredClone(t)},emit:u,registerIntents:function(t){for(const e in t){const s=t[e];l.on(e,async(t,n)=>{const o=f(h(e,n,t));await s(o)},a)}},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=c(d);t.wrap(d),d.devtools=t}return d},exports.createLogic=function(t){return{name:t.name,create(e){var s;const n=new a(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}}},exports.createSelector=function(t,e=Object.is){let s,n=null;return o=>{if(null!==n){const i=t(o);return e(s,i)?s:(s=i,n=o,i)}return n=o,s=t(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"actions"in t?t.actions:u(t).actions},exports.useRuntime=u,exports.useSelector=function(t,e){return s.useSyncExternalStore(t.subscribe,()=>e(t.getSnapshot()),()=>e(t.getSnapshot()))},exports.withLogic=function(t,s,o){var r,a;const c=r=>{const a=i.useRef(null);a.current||(a.current=t.create("string"==typeof o?e.createScope(o):o));const c=a.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 n.jsx(s,{...r,...h})};return c.displayName=`withLogic(${null!==(a=null!==(r=s.displayName)&&void 0!==r?r:s.name)&&void 0!==a?a:"View"})`,c};
|
package/build/index.d.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export
|
|
10
|
-
export {
|
|
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 { LogicRuntime } from "./core/runtime";
|
|
2
|
+
export { effect } from "./core/effect";
|
|
3
|
+
export { createLogic } from "./logic/createLogic";
|
|
4
|
+
export type { LogicFactory } from "./logic/createLogic";
|
|
5
|
+
export { composeLogic } from "./logic/composeLogic";
|
|
6
|
+
export { createBackendRuntime } from "./logic/createBackendRuntime";
|
|
7
|
+
export { createSelector } from "./react/selector";
|
|
8
|
+
export { useActions } from "./react/useActions";
|
|
9
|
+
export { useRuntime } from "./react/useRuntime";
|
|
10
|
+
export { useSelector } from "./react/useSelector";
|
|
16
11
|
export { withLogic } from "./react/withLogic";
|
|
12
|
+
export * from "./devtools";
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{atom as t,effect as e}from"chrono-state-z";import{createScope as s,createIntentBus as n}from"intentx-core-z";import*as i from"react";import{useSyncExternalStore as o}from"react";import{jsx as a}from"react/jsx-runtime";class r{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 i=this.handlers[t];i&&i.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 i=null!==(s=this.handlers[t])&&void 0!==s?s:[],o=null!==(n=this.effects[t])&&void 0!==n?n:[],a=(r=this.middlewares,c=async t=>{t.effects=o;for(const e of i)await e(t)},r.reduceRight((t,e)=>e(t),c));var r,c;await a(e)}}class c{constructor(t,e=s("logic")){this.subs=new Set,this.bus=new r,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 i;const o=n.effects;if(!(null==o?void 0:o.length))return s(n);for(const s of o){const o=s.handler.toString();if("takeLatest"===s.strategy){null===(i=t.get(o))||void 0===i||i.abort();const e=new AbortController;t.set(o,e),await s.handler({...n,signal:e.signal})}else"debounce"===s.strategy?(clearTimeout(e.get(o)),e.set(o,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 i=t(void 0);e(()=>{this.isComputing=!0;const t=n();i.set(t),this.isComputing=!1}),this.atoms[s]=i,i.subscribe(this.markDirty)}}function u(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 l(t){return{name:t.name,create(e){var s;const n=new c(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 i={};if(t.actions)for(const e in t.actions)i[e]=t.actions[e]({emit:n.emit,getState:n.getSnapshot});return n.actions=i,n}}}function h(t){return{create(){const e={};for(const s in t){const n=s;e[n]=t[n].create()}return{async emit(t,s){for(const n of Object.values(e))await n.emit(t,s)},subscribe(t){const s=Object.values(e).map(e=>e.subscribe(t));return()=>s.forEach(t=>t())},getSnapshot(){const t={};for(const s in e)t[s]=e[s].getSnapshot();return t}}}}}function f(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:i=1/0,scope:o}=null!=s?s:{},a=e.filter(t=>"emit"===t.type&&t.id>=n&&t.id<=i&&(!o||t.scope===o));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(i,o)=>{e.record({type:"emit:start",intent:i,payload:o,scope:s(),state:t.getSnapshot(),timestamp:Date.now()});try{const t=n(i,o);t instanceof Promise&&await t}finally{e.record({type:"emit:end",intent:i,payload:o,scope:s(),state:t.getSnapshot(),timestamp:Date.now()})}}}}}function d(t){var e,i;let o=structuredClone(t);const a=()=>structuredClone(o),r=t=>{o=Object.assign(a(),t)},c=s("backend");async function u(t,e){await l.emit(t,e,c)}const l=n(t=>({payload:t,signal:(new AbortController).signal,state:a(),setState(){throw new Error("setState is not allowed in backend runtime")},emit:u}));function h(t,e,s){return{intent:t,payload:e,state:s.state,signal:s.signal,set:r,emit:u}}function d(t){return{state:t.state,signal:t.signal,set:t.set,emit:t.emit}}const m={state:()=>o,reset:()=>{o=structuredClone(t)},emit:u,registerIntents:function(t){for(const e in t){const s=t[e];l.on(e,async(t,n)=>{const i=d(h(e,n,t));await s(i)},c)}},onIntent:l.on,effect:l.effect};if("production"!==(null===(i=null===(e=null===globalThis||void 0===globalThis?void 0:globalThis.process)||void 0===e?void 0:e.env)||void 0===i?void 0:i.NODE_ENV)){const t=f(m);t.wrap(m),m.devtools=t}return m}function m(t,e=Object.is){let s,n=null;return i=>{if(null!==n){const o=t(i);return e(s,o)?s:(s=o,n=i,o)}return n=i,s=t(i),s}}function p(t){if(t instanceof c)return o(t.subscribe,t.getSnapshot,t.getSnapshot);const e=t.create(s("react"));return o(e.subscribe,e.getSnapshot,e.getSnapshot)}function g(t){if("actions"in t)return t.actions;return p(t).actions}function b(t,e){return o(t.subscribe,()=>e(t.getSnapshot()),()=>e(t.getSnapshot()))}function y(t,e,n){var o,r;const c=o=>{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 a(e,{...o,...h})};return c.displayName=`withLogic(${null!==(r=null!==(o=e.displayName)&&void 0!==o?o:e.name)&&void 0!==r?r:"View"})`,c}export{c as LogicRuntime,f as attachDevtools,h as composeLogic,d as createBackendRuntime,l as createLogic,m as createSelector,u as effect,g as useActions,p as useRuntime,b as useSelector,y as withLogic};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LogicRuntime } from "../core/runtime";
|
|
2
|
+
type LogicFactory<S extends object> = {
|
|
3
|
+
create(): LogicRuntime<S, any>;
|
|
4
|
+
};
|
|
5
|
+
type LogicMap = Record<string, LogicFactory<any>>;
|
|
6
|
+
type SnapshotOf<M extends LogicMap> = {
|
|
7
|
+
[K in keyof M]: ReturnType<M[K]["create"]> extends LogicRuntime<infer S extends object, any> ? Readonly<S> : never;
|
|
8
|
+
};
|
|
9
|
+
export declare function composeLogic<M extends LogicMap>(logics: M): {
|
|
10
|
+
create(): {
|
|
11
|
+
emit(intent: string, payload?: any): Promise<void>;
|
|
12
|
+
subscribe(fn: () => void): () => void;
|
|
13
|
+
getSnapshot(): SnapshotOf<M>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
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: () => S;
|
|
12
|
+
reset: () => void;
|
|
13
|
+
emit: (intent: string, payload?: any) => Promise<void>;
|
|
14
|
+
registerIntents: (intents: BackendIntents<S>) => void;
|
|
15
|
+
onIntent: (type: string, handler: import("intentx-core-z").IntentHandler<S>, scope?: Scope) => () => void;
|
|
16
|
+
effect: (type: string, fx: import("intentx-core-z/build/intent/effect").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,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.0.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,66 @@
|
|
|
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
|
+
|
|
51
|
+
"headless",
|
|
52
|
+
"backend-friendly",
|
|
53
|
+
"ui-agnostic",
|
|
54
|
+
|
|
55
|
+
"react",
|
|
59
56
|
"react-architecture",
|
|
60
|
-
"
|
|
61
|
-
|
|
57
|
+
"no-hooks",
|
|
58
|
+
"external-store",
|
|
59
|
+
|
|
60
|
+
"computed-state",
|
|
61
|
+
"derived-state",
|
|
62
|
+
"async-effects",
|
|
63
|
+
"takeLatest",
|
|
62
64
|
|
|
65
|
+
"state-management"
|
|
66
|
+
],
|
|
63
67
|
"peerDependencies": {
|
|
64
68
|
"react": ">=18.0.0",
|
|
65
69
|
"react-dom": ">=18.0.0"
|
|
66
70
|
},
|
|
67
|
-
|
|
68
71
|
"devDependencies": {
|
|
69
72
|
"@rollup/plugin-commonjs": "^25.0.0",
|
|
70
73
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
71
74
|
"@rollup/plugin-terser": "^0.4.4",
|
|
75
|
+
"@types/react": "^18.2.43",
|
|
76
|
+
"@types/react-dom": "^18.2.17",
|
|
77
|
+
"react": "^18.2.0",
|
|
78
|
+
"react-dom": "^18.2.0",
|
|
72
79
|
"rimraf": "^5.0.5",
|
|
73
80
|
"rollup": "^4.9.6",
|
|
74
81
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
75
82
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
76
|
-
"typescript": "^5.3.3",
|
|
77
83
|
"tslib": "^2.6.2",
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
"
|
|
84
|
+
"typescript": "^5.3.3"
|
|
85
|
+
},
|
|
86
|
+
"dependencies": {
|
|
87
|
+
"chrono-state-z": "^2.0.1",
|
|
88
|
+
"intentx-core-z": "^1.0.0"
|
|
83
89
|
}
|
|
84
90
|
}
|
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
package/build/runtime/logic.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { LogicRuntime, IntentHandler, Effect } from "../core/types";
|
|
2
|
-
import { LogicPlugin } from "../plugins";
|
|
3
|
-
type ComputedDef<S, C> = {
|
|
4
|
-
[K in keyof C]: (ctx: {
|
|
5
|
-
state: S;
|
|
6
|
-
}) => C[K];
|
|
7
|
-
};
|
|
8
|
-
type LogicDef<S extends object, C extends object = {}> = {
|
|
9
|
-
name?: string;
|
|
10
|
-
state: S;
|
|
11
|
-
computed?: ComputedDef<S, C>;
|
|
12
|
-
intents?: (bus: {
|
|
13
|
-
on(intent: string, handler: IntentHandler<S, S & C>): void;
|
|
14
|
-
effect(intent: string, fx: Effect<S, S & C>): void;
|
|
15
|
-
}) => void;
|
|
16
|
-
plugins?: LogicPlugin<S, C>[];
|
|
17
|
-
};
|
|
18
|
-
export declare function createLogic<S extends object = {}, C extends object = {}>(def: LogicDef<S, C>): {
|
|
19
|
-
create(scope?: string): LogicRuntime<S, C>;
|
|
20
|
-
};
|
|
21
|
-
export {};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type ComputeFn<S, R> = (ctx: {
|
|
2
|
-
state: S;
|
|
3
|
-
}) => R;
|
|
4
|
-
export declare function createComputed<S extends object, C extends Record<string, any>>(): {
|
|
5
|
-
compute: <K extends keyof C>(key: K, fn: ComputeFn<S, C[K]>, state: S) => C[K];
|
|
6
|
-
invalidate: (changedKey: keyof S) => void;
|
|
7
|
-
subscribe: <K extends keyof C>(key: K, fn: () => void) => () => boolean;
|
|
8
|
-
reset: () => void;
|
|
9
|
-
};
|
|
10
|
-
export {};
|
package/build/state/index.d.ts
DELETED