intentx-solid 0.0.20 → 0.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 CHANGED
@@ -6,10 +6,10 @@
6
6
 
7
7
  ---
8
8
 
9
- `intentx-solid` connects the headless **LogicRuntime engine** with Solid’s fine-grained reactive system.
10
-
11
- It does not replace Solid’s state primitives.
12
- It orchestrates business logic outside the component tree.
9
+ `intentx-solid` is an architectural layer for Solid.
10
+ It enforces a strict separation between:
11
+ - Business Logic (deterministic runtime)
12
+ - UI Rendering (fine-grained reactivity)
13
13
 
14
14
  > It is a bridge between deterministic logic and Solid’s reactive UI.
15
15
 
@@ -230,14 +230,31 @@ Works with:
230
230
 
231
231
  ---
232
232
 
233
+ ## 🧪 Testability Upgrade
234
+
235
+ Without rendering anything:
236
+
237
+ ```ts
238
+ const runtime = counterLogic.create()
239
+
240
+ runtime.actions.inc()
241
+ expect(runtime.state.count).toBe(1)
242
+
243
+ ```
244
+
245
+ That is the real split.
246
+
247
+ ---
248
+
233
249
  ## 🔍 Comparison
234
250
 
235
- | intentx-solid | Solid |
236
- | ------------------- | ----------------------- |
237
- | Intent-driven logic | Fine-grained reactivity |
238
- | Deterministic state | Reactive DOM updates |
239
- | Computed graph | Dependency tracking |
240
- | Effects & async | Declarative components |
251
+ | Criteria | Solid only | intentx-solid |
252
+ | ---------------------- | ----------- | ------------- |
253
+ | Local UI state | ✅ | Overkill |
254
+ | Async orchestration | ⚠️ Manual | Built-in |
255
+ | Cross-runtime reuse | ❌ | |
256
+ | Deterministic snapshot | ❌ | |
257
+
241
258
 
242
259
 
243
260
  - UI consumes state.
@@ -245,16 +262,82 @@ Works with:
245
262
 
246
263
  ---
247
264
 
248
- ## 🎯 Philosophy
265
+ ## 🔥 What This Library Actually Does
266
+
267
+ <b>It separates business logic from UI completely.</b>
268
+
269
+ Without this split:
270
+
271
+ - Components start holding async workflows
272
+ - Event chains become implicit
273
+ - State transitions become coupled to rendering
274
+ - Testing requires rendering components
275
+
276
+ With intentx-solid:
277
+
278
+ - Logic lives outside the component tree
279
+ - UI becomes a pure consumer
280
+ - Async workflows are deterministic
281
+ - Runtime can be reused in Node, SSR, microfrontends
282
+
283
+ ---
284
+
285
+ ## 🧩 Architectural Boundary
286
+
287
+ <b>Solid owns:</b>
288
+
289
+ - Signals
290
+ - Reactivity
291
+ - DOM updates
292
+ - Rendering lifecycle
293
+
294
+ <b>intentx owns:</b>
295
+
296
+ - State machine
297
+ - Intent routing
298
+ - Async orchestration
299
+ - Computed graph
300
+ - Cross-runtime communication
301
+
302
+ This is not about replacing `createSignal`.
303
+
304
+ It is about preventing this:
305
+
306
+ ```ts
307
+ // ❌ Business logic leaking into UI
308
+ createEffect(async () => {
309
+ if (userId()) {
310
+ const data = await fetchUser(userId())
311
+ setUser(data)
312
+ }
313
+ })
314
+ ```
315
+
316
+ And moving it here:
317
+
318
+ ```ts
319
+ // ✅ Logic outside UI
320
+ actions: ({ setState }) => ({
321
+ async loadUser(id: string) {
322
+ const data = await fetchUser(id)
323
+ setState(d => {
324
+ d.user = data
325
+ })
326
+ }
327
+ })
328
+ ```
249
329
 
250
- Solid handles rendering.
330
+ Now UI only emits intent.
331
+
332
+ ---
333
+
334
+ ## 🎯 Philosophy
251
335
 
252
- intentx handles intent and state orchestration.
336
+ Rendering is reactive.
253
337
 
254
- Together:
338
+ Business logic should be deterministic.
255
339
 
256
- > Predictable business logic
257
- > Ultra-fast fine-grained UI
340
+ intentx-solid ensures they never mix.
258
341
 
259
342
  ---
260
343
 
package/build/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var t=require("solid-js/store"),e=require("solid-js"),s="undefined"!=typeof document?document.currentScript:null;let n=0;function o(t){return Symbol(null!=t?t:"scope-"+ ++n)}const i={activeNode:null,nodes:new Set};let r=0;function c(t){const e={id:++r,type:t,deps:new Set};return i.nodes.add(e),e}function a(t,e){t.deps.add(e)}const d="undefined"==typeof globalThis||void 0===globalThis.__DEV__||globalThis.__DEV__,h={high:new Set,normal:new Set,low:new Set};let u=!1;function l(){u=!0;for(const t of["high","normal","low"])for(const e of h[t])h[t].delete(e),e();u=!1}function f(t,e="normal"){h[e].add(t),u||queueMicrotask(l)}const p=function(){const t={activeEffect:null,activeDeps:null},e=function(t,e){return function(s){let n=s;const o=new Set,r=d?c("signal"):null,h=()=>{var e;const s=t.activeEffect;if(s&&(o.add(s),null===(e=t.activeDeps)||void 0===e||e.add(o)),d&&r){const t=i.activeNode;t&&a(t,r)}return n};return h.set=(s,i="normal")=>{Object.is(s,n)||(n=s,o.forEach(s=>{s!==t.activeEffect&&e(s,i)}))},h.subscribe=t=>(o.add(t),()=>o.delete(t)),h}}(t,f),s=function(t,e){return function(s){let n,o=!0;const r=new Set,h=new Set,u=d?c("computed"):null,l=()=>{o||(o=!0,r.forEach(t=>e(t,"normal")))};return()=>{var e;const c=t.activeEffect;if(c&&(r.add(c),null===(e=t.activeDeps)||void 0===e||e.add(r)),o){for(const t of h)t.delete(l);h.clear();const e=t.activeEffect,r=t.activeDeps,c=d?i.activeNode:null;t.activeEffect=l,t.activeDeps=h,d&&u&&(i.activeNode=u);try{n=s(),o=!1}finally{t.activeEffect=e,t.activeDeps=r,d&&(i.activeNode=c)}}if(d&&u){const t=i.activeNode;t&&a(t,u)}return n}}}(t,f),n=function(t,e){return function(s,n="normal"){let o=!1;const r=new Set,a=d?c("effect"):null,h=()=>{if(o)return;for(const t of r)t.delete(h);r.clear();const e=d?i.activeNode:null;try{t.activeEffect=h,t.activeDeps=r,d&&a&&(i.activeNode=a),s()}finally{t.activeEffect=null,t.activeDeps=null,d&&(i.activeNode=e)}};return e(h,n),()=>{o=!0;for(const t of r)t.delete(h);r.clear()}}}(t,f);return{signal:e,createComputed:s,reactiveEffect:n,context:t}}(),m=p.signal,y=p.reactiveEffect;o("default");const g=function(t){const e=function(t){return function(e,s){const n=t(e),o=n.set;return n.set=(t,e="normal")=>{const i=n(),r=s?s(t,i):t;o(r,e)},n.update=(t,e="normal")=>{n.set(t(n()),e)},n}}(t);return function(t,s){var n;const o=null!==(n=null==s?void 0:s.equals)&&void 0!==n?n:Object.is;return e(t,(t,e)=>o(t,e)?e:t)}}(m);class b{constructor(){this.handlers={},this.effects={},this.middlewares=[],this.effectModes={},this.use=t=>{this.middlewares.push(t)},this.setEffectMode=(t,e)=>{this.effectModes[t]=e},this.effect=(t,e)=>{var s;((s=this.effects)[t]??(s[t]=[])).push(e)},this.on=(t,e)=>{var s;const n=(s=this.handlers)[t]??(s[t]=[]);return n.length>0?()=>{}:(n.push(e),()=>{const s=this.handlers[t];if(!s)return;const n=s.indexOf(e);0>n||s.splice(n,1),0===s.length&&delete this.handlers[t]})},this.emit=async(t,e)=>{const s=this.handlers[t]??[],n={context:e,effects:this.effects[t]??[],effectMode:this.effectModes[t]??"sequential"},o=this.middlewares.reduceRight((t,e)=>e(t),async t=>{for(const e of s)await e(t.context)});await o(n)},this.clear=()=>{this.handlers={},this.effects={},this.middlewares=[],this.effectModes={}}}}function w(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function v(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const e of Object.keys(t)){const s=t[e];s&&"object"==typeof s&&!Object.isFrozen(s)&&v(s)}return t}const S=void("undefined"==typeof document?require("url").pathToFileURL(__filename):s&&"SCRIPT"===s.tagName.toUpperCase()&&s.src||new URL("index.cjs",document.baseURI)),D="undefined"!=typeof globalThis&&void 0!==globalThis.process?globalThis.process?.env?.NODE_ENV:void 0,E=S?.DEV??(!!D&&"production"!==D);class k{constructor(t,e=o("logic"),s){this.computedAtoms={},this.subs=new Set,this.dirty=!0,this.isComputing=!1,this.isBatching=!1,this.destroyed=!1,this.computedKeys=new Set,this.computedDisposers=new Set,this.intentDisposers=new Set,this.errorHandlers=new Set,this.leadingLocks=new Set,this.throttleMap=new Map,this.destroy=()=>{this.destroyed||(this.destroyed=!0,this.subs.clear(),this.computedDisposers.forEach(t=>t()),this.computedDisposers.clear(),this.intentDisposers.forEach(t=>t()),this.intentDisposers.clear(),this.leadingLocks.clear(),this.throttleMap.clear(),this.errorHandlers.clear(),this.computedKeys.clear(),this.dirty=!0)},this.createStateAtoms=t=>{const e={};for(const s in t)e[s]=g(t[s]);return e},this.buildSnapshot=()=>{const t={};for(const e in this.stateAtoms)t[e]=this.stateAtoms[e]();for(const e in this.computedAtoms)t[e]=this.computedAtoms[e]();return E?v(t):t},this.markDirty=()=>{this.destroyed||this.isBatching||(this.dirty=!0,this.subs.forEach(t=>t()))},this.createReactiveState=()=>new Proxy({},{get:(t,e)=>{const s=this.stateAtoms[e];return s?s():void 0}}),this.getSnapshot=()=>this.destroyed?this.snapshotCache??this.buildSnapshot():(this.dirty&&(this.snapshotCache=this.buildSnapshot(),this.dirty=!1),this.snapshotCache),this.subscribe=t=>this.destroyed?()=>{}:(this.subs.add(t),()=>this.subs.delete(t)),this.batch=t=>{if(!this.destroyed){this.isBatching=!0;try{t()}finally{this.isBatching=!1,this.markDirty()}}},this.onError=t=>(this.errorHandlers.add(t),()=>this.errorHandlers.delete(t)),this.getComputedKey=t=>this.computedAtoms[t](),this.getComputed=()=>{const t=this.getSnapshot(),e={};return this.computedKeys.forEach(s=>{e[s]=t[s]}),e},this.setStateInternal=t=>{const e={};for(const t in this.stateAtoms)e[t]=this.stateAtoms[t]();t(e);for(const t in this.stateAtoms)e[t]!==this.stateAtoms[t]()&&this.stateAtoms[t].set(e[t])},this.onIntent=(t,e)=>{const s=this.bus.on(t,e);return this.intentDisposers.add(s),()=>{s(),this.intentDisposers.delete(s)}},this.once=(t,e)=>{const s=this.onIntent(t,async t=>{s(),await e(t)})},this.takeLeading=(t,e)=>{this.onIntent(t,async s=>{if(!this.leadingLocks.has(t)){this.leadingLocks.add(t);try{await e(s)}finally{this.leadingLocks.delete(t)}}})},this.throttle=(t,e,s)=>{this.onIntent(t,async n=>{const o=Date.now();o-(this.throttleMap.get(t)??0)<e||(this.throttleMap.set(t,o),await s(n))})},this.useEffect=(t,e)=>{this.bus.effect(t,e)},this.emit=async(t,e)=>{if(this.destroyed)return;const s=new AbortController;try{await this.bus.emit(t,{payload:e,scope:this.scope,signal:s.signal,state:this.getSnapshot,setState:this.setStateInternal,emit:this.emit})}catch(s){this.errorHandlers.forEach(n=>n(s,{type:t,payload:e}))}},this.attachComputed=(t,e)=>{const s=g(void 0),n=this.createReactiveState();this.computedAtoms[t]=s,this.computedKeys.add(t);const o=()=>{this.destroyed||(this.isComputing=!0,s.set(e({state:n})),this.isComputing=!1)},i=y(o);this.computedDisposers.add(i),o();const r=s.subscribe(this.markDirty);this.computedDisposers.add(r)},this.scope=e,this.stateAtoms=this.createStateAtoms(t);for(const t in this.stateAtoms){const e=this.stateAtoms[t].subscribe(this.markDirty);this.computedDisposers.add(e)}s?this.bus=s:(this.bus=new b,this.bus.use(function(){const t=new Map,e=new Map;return s=>async n=>{await s(n);const{effects:o,effectMode:i,context:r}=n;if(!o.length)return;const c=o.map(s=>()=>(async s=>{const n=s.id;if("takeLatest"===s.strategy){t.get(n)?.abort();const e=new AbortController;return t.set(n,e),s.handler({...r,signal:e.signal})}return"debounce"===s.strategy?(clearTimeout(e.get(n)),new Promise(t=>{e.set(n,setTimeout(async()=>{await s.handler(r),t()},s.wait))})):s.handler(r)})(s));switch(i){case"parallel":await Promise.all(c.map(t=>t()));break;case"race":await Promise.race(c.map(t=>t()));break;case"allSettled":await Promise.allSettled(c.map(t=>t()));break;default:for(const t of c){const e=t();await e}}}}())),E&&(this.__debugId="runtime-"+Math.random().toString(36).slice(2))}get state(){return this.getSnapshot()}get computed(){const t={};return this.computedKeys.forEach(e=>{t[e]=this.computedAtoms[e]()}),t}}const C=()=>new b;let A=null;const x=new Map;function M(){return A||(A=C()),A}function L(t){return t?(x.has(t)||x.set(t,C()),x.get(t)):M()}const _="undefined"!=typeof window;function N(s,n){const i="string"==typeof n?.scope?o(n.scope):n?.scope,r=n?.bus??(n?.sharedBus?L("string"==typeof n?.scope?n.scope:void 0):void 0),c=r?s.create(i,r):s.create(i),[a,d]=t.createStore(c.getSnapshot());let h=()=>{};return _&&(h=c.subscribe(()=>{d(t.reconcile(c.getSnapshot()))}),e.onCleanup(()=>{h(),c.destroy?.()})),{runtime:c,store:a,state:a,actions:c.actions,emit:c.emit.bind(c)}}const j=e.createContext({});exports.createIntentBus=C,exports.createLogic=function(t){return{name:t.name,createShareBus(t,e){return this.create(t,e)},createIsolated(t){return this.create(t,void 0)},create(e,s){const n=new k(w(t.state),e,s);if(E&&!n.devtools){const e=function(t,e){const s=function(){let t=0,e=[];return{get records(){return e.slice()},record:function(s){e.push({...s,id:++t,state:w(s.state)})},replay:async function(t,s){const{from:n=0,to:o=1/0,scope:i}=s??{},r=e.filter(t=>!("emit"!==t.type||n>t.id||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}}}(),n=Symbol("devtools_wrapped");function o(){const s=e||t.scope;return s?"string"==typeof s?s:s.name??"anonymous":"global"}function i(){return"function"==typeof t.getSnapshot?t.getSnapshot():"function"==typeof t.state?t.state():void 0}return{timeline:s,wrap:function(){if(t[n])return;t[n]=!0;const e=t.emit.bind(t);t.emit=async(t,n)=>{s.record({type:"emit:start",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()});try{await Promise.resolve(e(t,n))}catch(e){throw s.record({type:"emit:error",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()}),e}s.record({type:"emit:end",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()})}}}}(n,t.name??"logic");e.wrap(),n.devtools=e}if(t.computed)for(const e in t.computed)n.attachComputed(e,t.computed[e]);t.intents?.({on:n.onIntent,effect:(t,e)=>n.useEffect(t,e)});const o={};if(t.actions){const e=Object.keys(t.actions);for(const s of e)o[s]=(0,t.actions[s])({emit:n.emit,getState:n.getSnapshot})}return n.actions=o,n}}},exports.effect=function(t){const e={_kind:"effect",id:Symbol("effect"),handler:t,strategy:"default"},s=(t={})=>{const n={...e,...t};return Object.assign(n,{takeLatest:()=>s({strategy:"takeLatest"}),debounce:t=>s({strategy:"debounce",wait:t}),blocking:()=>s({blocking:!0})})};return s()},exports.getGlobalBus=M,exports.getScopedBus=L,exports.setLogicContext=function(t,e,s){const n=N(e,s);return{Provider:function(e){return j.Provider({value:{[t]:n},get children(){return e.children}})},store:n}},exports.useLogic=N,exports.useLogicContext=function(t){const s=e.useContext(j);if(!s||!s[t])throw Error(`Logic "${t}" not found in context`);return s[t]};
1
+ "use strict";var e=require("intentx-runtime"),t=require("solid-js/store"),r=require("solid-js");let n=null;const o=new Map;function c(){return n||(n=e.createIntentBus()),n}function s(t){return t?(o.has(t)||o.set(t,e.createIntentBus()),o.get(t)):c()}const i="undefined"!=typeof window;function u(n,o){const c="string"==typeof o?.scope?e.createScope(o.scope):o?.scope,u=o?.bus??(o?.sharedBus?s("string"==typeof o?.scope?o.scope:void 0):void 0),a=u?n.create(c,u):n.create(c),[p,f]=t.createStore(a.getSnapshot());let d=()=>{};return i&&(d=a.subscribe(()=>{f(t.reconcile(a.getSnapshot()))}),r.onCleanup(()=>{d(),a.destroy?.()})),{runtime:a,store:p,state:p,actions:a.actions,emit:a.emit.bind(a)}}const a=r.createContext({});Object.defineProperty(exports,"createIntentBus",{enumerable:!0,get:function(){return e.createIntentBus}}),Object.defineProperty(exports,"createLogic",{enumerable:!0,get:function(){return e.createLogic}}),Object.defineProperty(exports,"effect",{enumerable:!0,get:function(){return e.effect}}),exports.getGlobalBus=c,exports.getScopedBus=s,exports.setLogicContext=function(e,t,r){const n=u(t,r);return{Provider:function(t){return a.Provider({value:{[e]:n},get children(){return t.children}})},store:n}},exports.useLogic=u,exports.useLogicContext=function(e){const t=r.useContext(a);if(!t||!t[e])throw Error(`Logic "${e}" not found in context`);return t[e]};
package/build/index.js CHANGED
@@ -1 +1 @@
1
- import{createStore as t,reconcile as e}from"solid-js/store";import{onCleanup as s,createContext as n,useContext as o}from"solid-js";let i=0;function r(t){return Symbol(null!=t?t:"scope-"+ ++i)}const c={activeNode:null,nodes:new Set};let a=0;function h(t){const e={id:++a,type:t,deps:new Set};return c.nodes.add(e),e}function d(t,e){t.deps.add(e)}const u="undefined"==typeof globalThis||void 0===globalThis.__DEV__||globalThis.__DEV__,l={high:new Set,normal:new Set,low:new Set};let f=!1;function p(){f=!0;for(const t of["high","normal","low"])for(const e of l[t])l[t].delete(e),e();f=!1}function m(t,e="normal"){l[e].add(t),f||queueMicrotask(p)}const y=function(){const t={activeEffect:null,activeDeps:null},e=function(t,e){return function(s){let n=s;const o=new Set,i=u?h("signal"):null,r=()=>{var e;const s=t.activeEffect;if(s&&(o.add(s),null===(e=t.activeDeps)||void 0===e||e.add(o)),u&&i){const t=c.activeNode;t&&d(t,i)}return n};return r.set=(s,i="normal")=>{Object.is(s,n)||(n=s,o.forEach(s=>{s!==t.activeEffect&&e(s,i)}))},r.subscribe=t=>(o.add(t),()=>o.delete(t)),r}}(t,m),s=function(t,e){return function(s){let n,o=!0;const i=new Set,r=new Set,a=u?h("computed"):null,l=()=>{o||(o=!0,i.forEach(t=>e(t,"normal")))};return()=>{var e;const h=t.activeEffect;if(h&&(i.add(h),null===(e=t.activeDeps)||void 0===e||e.add(i)),o){for(const t of r)t.delete(l);r.clear();const e=t.activeEffect,i=t.activeDeps,h=u?c.activeNode:null;t.activeEffect=l,t.activeDeps=r,u&&a&&(c.activeNode=a);try{n=s(),o=!1}finally{t.activeEffect=e,t.activeDeps=i,u&&(c.activeNode=h)}}if(u&&a){const t=c.activeNode;t&&d(t,a)}return n}}}(t,m),n=function(t,e){return function(s,n="normal"){let o=!1;const i=new Set,r=u?h("effect"):null,a=()=>{if(o)return;for(const t of i)t.delete(a);i.clear();const e=u?c.activeNode:null;try{t.activeEffect=a,t.activeDeps=i,u&&r&&(c.activeNode=r),s()}finally{t.activeEffect=null,t.activeDeps=null,u&&(c.activeNode=e)}};return e(a,n),()=>{o=!0;for(const t of i)t.delete(a);i.clear()}}}(t,m);return{signal:e,createComputed:s,reactiveEffect:n,context:t}}(),g=y.signal,w=y.reactiveEffect;r("default");const b=function(t){const e=function(t){return function(e,s){const n=t(e),o=n.set;return n.set=(t,e="normal")=>{const i=n(),r=s?s(t,i):t;o(r,e)},n.update=(t,e="normal")=>{n.set(t(n()),e)},n}}(t);return function(t,s){var n;const o=null!==(n=null==s?void 0:s.equals)&&void 0!==n?n:Object.is;return e(t,(t,e)=>o(t,e)?e:t)}}(g);class v{constructor(){this.handlers={},this.effects={},this.middlewares=[],this.effectModes={},this.use=t=>{this.middlewares.push(t)},this.setEffectMode=(t,e)=>{this.effectModes[t]=e},this.effect=(t,e)=>{var s;((s=this.effects)[t]??(s[t]=[])).push(e)},this.on=(t,e)=>{var s;const n=(s=this.handlers)[t]??(s[t]=[]);return n.length>0?()=>{}:(n.push(e),()=>{const s=this.handlers[t];if(!s)return;const n=s.indexOf(e);0>n||s.splice(n,1),0===s.length&&delete this.handlers[t]})},this.emit=async(t,e)=>{const s=this.handlers[t]??[],n={context:e,effects:this.effects[t]??[],effectMode:this.effectModes[t]??"sequential"},o=this.middlewares.reduceRight((t,e)=>e(t),async t=>{for(const e of s)await e(t.context)});await o(n)},this.clear=()=>{this.handlers={},this.effects={},this.middlewares=[],this.effectModes={}}}}function S(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function D(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const e of Object.keys(t)){const s=t[e];s&&"object"==typeof s&&!Object.isFrozen(s)&&D(s)}return t}const E=void 0!==import.meta?import.meta.env:void 0,k="undefined"!=typeof globalThis&&void 0!==globalThis.process?globalThis.process?.env?.NODE_ENV:void 0,A=E?.DEV??(!!k&&"production"!==k);class M{constructor(t,e=r("logic"),s){this.computedAtoms={},this.subs=new Set,this.dirty=!0,this.isComputing=!1,this.isBatching=!1,this.destroyed=!1,this.computedKeys=new Set,this.computedDisposers=new Set,this.intentDisposers=new Set,this.errorHandlers=new Set,this.leadingLocks=new Set,this.throttleMap=new Map,this.destroy=()=>{this.destroyed||(this.destroyed=!0,this.subs.clear(),this.computedDisposers.forEach(t=>t()),this.computedDisposers.clear(),this.intentDisposers.forEach(t=>t()),this.intentDisposers.clear(),this.leadingLocks.clear(),this.throttleMap.clear(),this.errorHandlers.clear(),this.computedKeys.clear(),this.dirty=!0)},this.createStateAtoms=t=>{const e={};for(const s in t)e[s]=b(t[s]);return e},this.buildSnapshot=()=>{const t={};for(const e in this.stateAtoms)t[e]=this.stateAtoms[e]();for(const e in this.computedAtoms)t[e]=this.computedAtoms[e]();return A?D(t):t},this.markDirty=()=>{this.destroyed||this.isBatching||(this.dirty=!0,this.subs.forEach(t=>t()))},this.createReactiveState=()=>new Proxy({},{get:(t,e)=>{const s=this.stateAtoms[e];return s?s():void 0}}),this.getSnapshot=()=>this.destroyed?this.snapshotCache??this.buildSnapshot():(this.dirty&&(this.snapshotCache=this.buildSnapshot(),this.dirty=!1),this.snapshotCache),this.subscribe=t=>this.destroyed?()=>{}:(this.subs.add(t),()=>this.subs.delete(t)),this.batch=t=>{if(!this.destroyed){this.isBatching=!0;try{t()}finally{this.isBatching=!1,this.markDirty()}}},this.onError=t=>(this.errorHandlers.add(t),()=>this.errorHandlers.delete(t)),this.getComputedKey=t=>this.computedAtoms[t](),this.getComputed=()=>{const t=this.getSnapshot(),e={};return this.computedKeys.forEach(s=>{e[s]=t[s]}),e},this.setStateInternal=t=>{const e={};for(const t in this.stateAtoms)e[t]=this.stateAtoms[t]();t(e);for(const t in this.stateAtoms)e[t]!==this.stateAtoms[t]()&&this.stateAtoms[t].set(e[t])},this.onIntent=(t,e)=>{const s=this.bus.on(t,e);return this.intentDisposers.add(s),()=>{s(),this.intentDisposers.delete(s)}},this.once=(t,e)=>{const s=this.onIntent(t,async t=>{s(),await e(t)})},this.takeLeading=(t,e)=>{this.onIntent(t,async s=>{if(!this.leadingLocks.has(t)){this.leadingLocks.add(t);try{await e(s)}finally{this.leadingLocks.delete(t)}}})},this.throttle=(t,e,s)=>{this.onIntent(t,async n=>{const o=Date.now();o-(this.throttleMap.get(t)??0)<e||(this.throttleMap.set(t,o),await s(n))})},this.useEffect=(t,e)=>{this.bus.effect(t,e)},this.emit=async(t,e)=>{if(this.destroyed)return;const s=new AbortController;try{await this.bus.emit(t,{payload:e,scope:this.scope,signal:s.signal,state:this.getSnapshot,setState:this.setStateInternal,emit:this.emit})}catch(s){this.errorHandlers.forEach(n=>n(s,{type:t,payload:e}))}},this.attachComputed=(t,e)=>{const s=b(void 0),n=this.createReactiveState();this.computedAtoms[t]=s,this.computedKeys.add(t);const o=()=>{this.destroyed||(this.isComputing=!0,s.set(e({state:n})),this.isComputing=!1)},i=w(o);this.computedDisposers.add(i),o();const r=s.subscribe(this.markDirty);this.computedDisposers.add(r)},this.scope=e,this.stateAtoms=this.createStateAtoms(t);for(const t in this.stateAtoms){const e=this.stateAtoms[t].subscribe(this.markDirty);this.computedDisposers.add(e)}s?this.bus=s:(this.bus=new v,this.bus.use(function(){const t=new Map,e=new Map;return s=>async n=>{await s(n);const{effects:o,effectMode:i,context:r}=n;if(!o.length)return;const c=o.map(s=>()=>(async s=>{const n=s.id;if("takeLatest"===s.strategy){t.get(n)?.abort();const e=new AbortController;return t.set(n,e),s.handler({...r,signal:e.signal})}return"debounce"===s.strategy?(clearTimeout(e.get(n)),new Promise(t=>{e.set(n,setTimeout(async()=>{await s.handler(r),t()},s.wait))})):s.handler(r)})(s));switch(i){case"parallel":await Promise.all(c.map(t=>t()));break;case"race":await Promise.race(c.map(t=>t()));break;case"allSettled":await Promise.allSettled(c.map(t=>t()));break;default:for(const t of c){const e=t();await e}}}}())),A&&(this.__debugId="runtime-"+Math.random().toString(36).slice(2))}get state(){return this.getSnapshot()}get computed(){const t={};return this.computedKeys.forEach(e=>{t[e]=this.computedAtoms[e]()}),t}}function C(t){const e={_kind:"effect",id:Symbol("effect"),handler:t,strategy:"default"},s=(t={})=>{const n={...e,...t};return Object.assign(n,{takeLatest:()=>s({strategy:"takeLatest"}),debounce:t=>s({strategy:"debounce",wait:t}),blocking:()=>s({blocking:!0})})};return s()}function N(t){return{name:t.name,createShareBus(t,e){return this.create(t,e)},createIsolated(t){return this.create(t,void 0)},create(e,s){const n=new M(S(t.state),e,s);if(A&&!n.devtools){const e=function(t,e){const s=function(){let t=0,e=[];return{get records(){return e.slice()},record:function(s){e.push({...s,id:++t,state:S(s.state)})},replay:async function(t,s){const{from:n=0,to:o=1/0,scope:i}=s??{},r=e.filter(t=>!("emit"!==t.type||n>t.id||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}}}(),n=Symbol("devtools_wrapped");function o(){const s=e||t.scope;return s?"string"==typeof s?s:s.name??"anonymous":"global"}function i(){return"function"==typeof t.getSnapshot?t.getSnapshot():"function"==typeof t.state?t.state():void 0}return{timeline:s,wrap:function(){if(t[n])return;t[n]=!0;const e=t.emit.bind(t);t.emit=async(t,n)=>{s.record({type:"emit:start",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()});try{await Promise.resolve(e(t,n))}catch(e){throw s.record({type:"emit:error",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()}),e}s.record({type:"emit:end",intent:t,payload:n,scope:o(),state:i(),timestamp:Date.now()})}}}}(n,t.name??"logic");e.wrap(),n.devtools=e}if(t.computed)for(const e in t.computed)n.attachComputed(e,t.computed[e]);t.intents?.({on:n.onIntent,effect:(t,e)=>n.useEffect(t,e)});const o={};if(t.actions){const e=Object.keys(t.actions);for(const s of e)o[s]=(0,t.actions[s])({emit:n.emit,getState:n.getSnapshot})}return n.actions=o,n}}}const _=()=>new v;let j=null;const L=new Map;function O(){return j||(j=_()),j}function I(t){return t?(L.has(t)||L.set(t,_()),L.get(t)):O()}const P="undefined"!=typeof window;function x(n,o){const i="string"==typeof o?.scope?r(o.scope):o?.scope,c=o?.bus??(o?.sharedBus?I("string"==typeof o?.scope?o.scope:void 0):void 0),a=c?n.create(i,c):n.create(i),[h,d]=t(a.getSnapshot());let u=()=>{};return P&&(u=a.subscribe(()=>{d(e(a.getSnapshot()))}),s(()=>{u(),a.destroy?.()})),{runtime:a,store:h,state:h,actions:a.actions,emit:a.emit.bind(a)}}const T=n({});function B(t,e,s){const n=x(e,s);return{Provider:function(e){return T.Provider({value:{[t]:n},get children(){return e.children}})},store:n}}function K(t){const e=o(T);if(!e||!e[t])throw Error(`Logic "${t}" not found in context`);return e[t]}export{_ as createIntentBus,N as createLogic,C as effect,O as getGlobalBus,I as getScopedBus,B as setLogicContext,x as useLogic,K as useLogicContext};
1
+ import{createIntentBus as t,createScope as e}from"intentx-runtime";export{createIntentBus,createLogic,effect}from"intentx-runtime";import{createStore as n,reconcile as o}from"solid-js/store";import{onCleanup as r,createContext as i,useContext as s}from"solid-js";let c=null;const u=new Map;function f(){return c||(c=t()),c}function p(e){return e?(u.has(e)||u.set(e,t()),u.get(e)):f()}const d="undefined"!=typeof window;function a(t,i){const s="string"==typeof i?.scope?e(i.scope):i?.scope,c=i?.bus??(i?.sharedBus?p("string"==typeof i?.scope?i.scope:void 0):void 0),u=c?t.create(s,c):t.create(s),[f,a]=n(u.getSnapshot());let m=()=>{};return d&&(m=u.subscribe(()=>{a(o(u.getSnapshot()))}),r(()=>{m(),u.destroy?.()})),{runtime:u,store:f,state:f,actions:u.actions,emit:u.emit.bind(u)}}const m=i({});function l(t,e,n){const o=a(e,n);return{Provider:function(e){return m.Provider({value:{[t]:o},get children(){return e.children}})},store:o}}function g(t){const e=s(m);if(!e||!e[t])throw Error(`Logic "${t}" not found in context`);return e[t]}export{f as getGlobalBus,p as getScopedBus,l as setLogicContext,a as useLogic,g as useLogicContext};
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "intentx-solid",
3
- "version": "0.0.20",
3
+ "version": "0.1.0",
4
4
  "description": "Intent-driven logic adapter for SolidJS. Connects intentx-runtime with Solid's fine-grained reactivity.",
5
+ "license": "MIT",
6
+ "author": "Delpi.Kye",
5
7
  "type": "module",
6
8
  "main": "build/index.cjs",
7
9
  "module": "build/index.js",
@@ -17,8 +19,6 @@
17
19
  "build"
18
20
  ],
19
21
  "sideEffects": false,
20
- "license": "MIT",
21
- "author": "Delpi.Kye",
22
22
  "repository": {
23
23
  "type": "git",
24
24
  "url": "https://github.com/delpikye-v/intentx-solid.git"