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 +99 -16
- package/build/index.cjs +1 -1
- package/build/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
`intentx-solid`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
236
|
-
|
|
|
237
|
-
|
|
|
238
|
-
|
|
|
239
|
-
|
|
|
240
|
-
|
|
|
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
|
-
##
|
|
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
|
-
|
|
330
|
+
Now UI only emits intent.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 🎯 Philosophy
|
|
251
335
|
|
|
252
|
-
|
|
336
|
+
Rendering is reactive.
|
|
253
337
|
|
|
254
|
-
|
|
338
|
+
Business logic should be deterministic.
|
|
255
339
|
|
|
256
|
-
|
|
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
|
|
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"
|