intentx-solid 0.1.0 → 0.2.1-z1

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,7 +6,8 @@
6
6
 
7
7
  ---
8
8
 
9
- `intentx-solid` is an architectural layer for Solid.
9
+ `intentx-solid` enforces a strict architectural boundary between deterministic business logic and reactive UI in Solid.
10
+
10
11
  It enforces a strict separation between:
11
12
  - Business Logic (deterministic runtime)
12
13
  - UI Rendering (fine-grained reactivity)
@@ -27,29 +28,26 @@ Use it when your UI starts to feel like business logic.
27
28
 
28
29
  Avoid it when:
29
30
 
30
- You only need simple `createSignal`
31
- You want reducer-style state
32
- ❌ Your state is purely local UI
31
+ This library introduces an architectural boundary.
32
+ If you don’t need architectural boundaries, don’t use it.
33
33
 
34
34
  ---
35
35
 
36
- ## 🧠 Mental Model
36
+ ## 🧠 Mental Model
37
+
37
38
  ```txt
38
- UI Event
39
-
40
- emit(intent)
41
-
42
- intent handler
43
-
44
- setState
45
-
46
- computed re-evaluates
47
-
48
- Solid store updates
49
-
50
- Fine-grained reactivity updates UI
39
+ UI / HTTP / Queue / Cron
40
+
41
+ intentx-runtime
42
+
43
+ Fine-grained reactivity updates UI
51
44
  ```
52
45
 
46
+ Core principle:
47
+
48
+ > Intent is the only mutation entry point.
49
+ > The [runtime](https://www.npmjs.com/package/intentx-runtime) owns behavior. UI only triggers intent.
50
+
53
51
  ---
54
52
 
55
53
  ## 📦 Installation
@@ -62,8 +60,10 @@ npm install intentx-solid
62
60
 
63
61
  ## 🧩 Core Logic (Framework-Agnostic)
64
62
 
63
+ Even though this is the React package, the runtime is fully usable without React.
64
+
65
65
  ``` ts
66
- import { createLogic } from "intentx-runtime"
66
+ import { createLogic } from "intentx-solid"
67
67
 
68
68
  export const counterLogic = createLogic({
69
69
  name: "counter",
@@ -76,22 +76,20 @@ export const counterLogic = createLogic({
76
76
  double: ({ state }) => state.count * 2
77
77
  },
78
78
 
79
- actions: ({ setState }) => ({
80
- inc() {
81
- setState(d => {
82
- d.count++
83
- })
84
- }
85
- })
86
- })
87
- ```
88
-
89
- ---
90
-
91
- ## 🔌 Solid Adapter
79
+ intents: (bus) => {
80
+ bus.on("inc", ({ setState }) => {
81
+ setState((s) => {
82
+ s.count++;
83
+ });
84
+ });
85
+ },
92
86
 
93
- ``` ts
94
- export { useLogic }
87
+ actions: {
88
+ inc({ emit }) {
89
+ return () => emit("inc");
90
+ },
91
+ },
92
+ })
95
93
  ```
96
94
 
97
95
  ---
@@ -104,11 +102,16 @@ import { counterLogic } from "./counter.logic"
104
102
 
105
103
  export default function Counter() {
106
104
  const counter = useLogic(counterLogic)
105
+ // const { actions, emit, store } = useLogic(counterLogic)
107
106
 
108
107
  return (
109
108
  <>
110
109
  <button onClick={counter.actions.inc}>
111
- {counter.store.count}
110
+ {counter.state.count}
111
+ </button>
112
+
113
+ <button onClick={() => emit("inc")}>
114
+ {counter.state.count}
112
115
  </button>
113
116
 
114
117
  <p>Double: {counter.store.double}</p>
@@ -148,35 +151,91 @@ const counter = useLogic(counterLogic)
148
151
 
149
152
  ---
150
153
 
151
- ## 📡 Scoped Bus
154
+ ## 📡 Multiple Logic Communication (Bus)
152
155
 
153
- ``` ts
156
+ Each `logic` instance is isolated by default.
157
+
158
+ To enable communication between runtimes, you can share an Intent Bus.
159
+
160
+ ---
161
+
162
+ ### 1️⃣ Scoped Shared Bus (Recommended)
163
+
164
+ ```ts
165
+ import { useLogic } from "intentx-solid"
166
+
167
+ // ✅ Same scope → shared bus
168
+ useLogic(logic, {
169
+ scope: "dashboard",
170
+ sharedBus: true
171
+ })
172
+
173
+ // ❌ Different scope → different bus
154
174
  useLogic(logic, {
175
+ scope: "settings",
155
176
  sharedBus: true
156
177
  })
157
178
  ```
158
179
 
159
- Scoped:
180
+ <b>How it works</b>
160
181
 
161
- ``` ts
182
+ When sharedBus: true is enabled:
183
+
184
+ - A singleton bus is created per scope
185
+
186
+ - Same scope → same bus instance
187
+
188
+ - Different scope → different bus
189
+
190
+ - No global leakage
191
+
192
+ If no `scope` is provided:
193
+
194
+ ```ts
162
195
  useLogic(logic, {
163
- scope: "dashboard",
164
196
  sharedBus: true
165
197
  })
166
198
  ```
167
199
 
168
- Custom bus:
200
+ uses a default global scope bus.
169
201
 
170
- ``` ts
171
- import { createIntentBus } from "intentx-runtime"
202
+ ---
203
+
204
+ ### 2️⃣ Custom Bus (Advanced / Cross-Scope)
205
+
206
+ ```ts
207
+ import { createIntentBus } from "intentx-react"
172
208
 
173
209
  const bus = createIntentBus()
174
210
 
175
- useLogic(logic, {
176
- bus
177
- })
211
+ useLogic(logicA, { bus })
212
+ useLogic(logicB, { bus })
213
+
178
214
  ```
179
215
 
216
+ <b>Behavior</b>
217
+
218
+ - Full cross-scope communication
219
+ - Manual orchestration control
220
+ - Suitable for:
221
+ - Microfrontend
222
+ - App-wide coordination
223
+ - Complex workflow systems
224
+
225
+ ### 🔍 Behavior Comparison
226
+
227
+ | Mode | Isolation | Scope-aware | Cross-scope | Recommended |
228
+ | -------------------- | ----------- | ----------- | ------------ | --------------------- |
229
+ | Default (no options) | ✅ Full | ❌ | ❌ | Small/local logic |
230
+ | `sharedBus: true` | ❌ Per scope | ✅ | ❌ | Modular apps |
231
+ | Custom `bus` | ❌ Manual | ❌ | ✅ | Advanced architecture |
232
+
233
+ ### 🎯 Recommendation
234
+
235
+ ✅ Use sharedBus for modular communication.
236
+ ✅ Use custom bus for orchestration layer.
237
+ 🚫 Avoid global single bus without scope in large apps.
238
+
180
239
  ---
181
240
 
182
241
  ## 🧩 Context API
@@ -248,13 +307,13 @@ That is the real split.
248
307
 
249
308
  ## 🔍 Comparison
250
309
 
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
310
 
311
+ | Criteria | Solid primitives | intentx-solid |
312
+ | ----------------------- | ---------------- | ------------- |
313
+ | Local UI | Excellent | Overkill |
314
+ | Async orchestration | Manual | Structured |
315
+ | Cross-environment reuse | No | Yes |
316
+ | Deterministic runtime | No | Yes |
258
317
 
259
318
 
260
319
  - UI consumes state.
@@ -312,19 +371,18 @@ createEffect(async () => {
312
371
  }
313
372
  })
314
373
  ```
315
-
316
374
  And moving it here:
317
375
 
318
376
  ```ts
319
377
  // ✅ Logic outside UI
320
- actions: ({ setState }) => ({
321
- async loadUser(id: string) {
378
+ intents: (bus) => {
379
+ bus.on("loadUser", async ({ setState }) => {
322
380
  const data = await fetchUser(id)
323
381
  setState(d => {
324
382
  d.user = data
325
383
  })
326
- }
327
- })
384
+ });
385
+ }
328
386
  ```
329
387
 
330
388
  Now UI only emits intent.
@@ -341,6 +399,15 @@ intentx-solid ensures they never mix.
341
399
 
342
400
  ---
343
401
 
402
+ ## ❌ What This Is Not
403
+
404
+ - Not a signal replacement
405
+ - Not a store wrapper
406
+ - Not a UI state helper
407
+ - Not a reducer abstraction
408
+
409
+ ---
410
+
344
411
  ## 📜 License
345
412
 
346
413
  MIT
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createIntentBus, LogicActions, LogicFactory, Scope } from 'intentx-runtime';
1
+ import { createIntentBus, LogicActions, InferComputed, Scope, ComputedDef, LogicFactory } from 'intentx-runtime';
2
2
  export { EffectMode, ExtractLogicTypes, IntentContext, LogicActions, LogicFactory, LogicRuntime, createIntentBus, createLogic, effect } from 'intentx-runtime';
3
3
  import * as solid_js from 'solid-js';
4
4
 
@@ -6,13 +6,7 @@ type IntentBus = ReturnType<typeof createIntentBus>;
6
6
  declare function getGlobalBus(): IntentBus;
7
7
  declare function getScopedBus(scope?: string): IntentBus;
8
8
 
9
- type ComputedDef<S> = Record<string, (context: {
10
- state: Readonly<S>;
11
- }) => any>;
12
- type InferComputed<C> = {
13
- [K in keyof C]: C[K] extends (...args: any) => infer R ? R : never;
14
- };
15
- type LogicInstance<S, C, A extends LogicActions> = {
9
+ type LogicApi<S, C, A extends LogicActions> = {
16
10
  runtime: any;
17
11
  store: Readonly<S & InferComputed<C>>;
18
12
  state: Readonly<S & InferComputed<C>>;
@@ -20,19 +14,20 @@ type LogicInstance<S, C, A extends LogicActions> = {
20
14
  emit: (...args: any[]) => Promise<void>;
21
15
  };
22
16
 
23
- declare function useLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>, options?: {
17
+ type LogicOptions = {
24
18
  scope?: Scope | string;
25
19
  sharedBus?: boolean;
26
- bus?: ReturnType<typeof getScopedBus>;
27
- }): LogicInstance<S, C, A>;
20
+ bus?: IntentBus;
21
+ };
22
+ declare function useLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>, options?: LogicOptions): LogicApi<S, C, A>;
28
23
 
29
- declare function setLogicContext<S extends object, C extends ComputedDef<S>, A extends LogicActions>(key: string, logic: LogicFactory<S, C, A>, options?: Parameters<typeof useLogic<S, C, A>>[1]): {
24
+ declare function setLogicContext<S extends object, C extends ComputedDef<S>, A extends LogicActions>(key: string, logic: LogicFactory<S, C, A>, options?: LogicOptions): {
30
25
  Provider: (props: {
31
26
  children: any;
32
27
  }) => solid_js.JSX.Element;
33
- store: LogicInstance<S, C, A>;
28
+ store: LogicApi<S, C, A>;
34
29
  };
35
30
  declare function useLogicContext<T>(key: string): T;
36
31
 
37
32
  export { getGlobalBus, getScopedBus, setLogicContext, useLogic, useLogicContext };
38
- export type { ComputedDef, InferComputed, IntentBus, LogicInstance };
33
+ export type { IntentBus, LogicApi, LogicOptions };
@@ -1,10 +1,9 @@
1
- import type { LogicFactory, LogicActions } from "intentx-runtime";
2
- import { useLogic } from "./useLogic";
3
- import type { ComputedDef } from "./types";
4
- export declare function setLogicContext<S extends object, C extends ComputedDef<S>, A extends LogicActions>(key: string, logic: LogicFactory<S, C, A>, options?: Parameters<typeof useLogic<S, C, A>>[1]): {
1
+ import type { LogicFactory, LogicActions, ComputedDef } from "intentx-runtime";
2
+ import type { LogicOptions } from "./useLogic";
3
+ export declare function setLogicContext<S extends object, C extends ComputedDef<S>, A extends LogicActions>(key: string, logic: LogicFactory<S, C, A>, options?: LogicOptions): {
5
4
  Provider: (props: {
6
5
  children: any;
7
6
  }) => import("solid-js").JSX.Element;
8
- store: import("./types").LogicInstance<S, C, A>;
7
+ store: import("./types").LogicApi<S, C, A>;
9
8
  };
10
9
  export declare function useLogicContext<T>(key: string): T;
@@ -1,11 +1,5 @@
1
- import type { LogicActions } from "intentx-runtime";
2
- export type ComputedDef<S> = Record<string, (context: {
3
- state: Readonly<S>;
4
- }) => any>;
5
- export type InferComputed<C> = {
6
- [K in keyof C]: C[K] extends (...args: any) => infer R ? R : never;
7
- };
8
- export type LogicInstance<S, C, A extends LogicActions> = {
1
+ import type { InferComputed, LogicActions } from "intentx-runtime";
2
+ export type LogicApi<S, C, A extends LogicActions> = {
9
3
  runtime: any;
10
4
  store: Readonly<S & InferComputed<C>>;
11
5
  state: Readonly<S & InferComputed<C>>;
@@ -1,8 +1,9 @@
1
- import type { Scope, LogicFactory, LogicActions } from "intentx-runtime";
2
- import { getScopedBus } from "./bus";
3
- import type { ComputedDef, LogicInstance } from "./types";
4
- export declare function useLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>, options?: {
1
+ import type { Scope, LogicFactory, LogicActions, ComputedDef } from "intentx-runtime";
2
+ import type { IntentBus } from "./bus";
3
+ import type { LogicApi } from "./types";
4
+ export type LogicOptions = {
5
5
  scope?: Scope | string;
6
6
  sharedBus?: boolean;
7
- bus?: ReturnType<typeof getScopedBus>;
8
- }): LogicInstance<S, C, A>;
7
+ bus?: IntentBus;
8
+ };
9
+ export declare function useLogic<S extends object, C extends ComputedDef<S>, A extends LogicActions>(logic: LogicFactory<S, C, A>, options?: LogicOptions): LogicApi<S, C, A>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intentx-solid",
3
- "version": "0.1.0",
3
+ "version": "0.2.1-z1",
4
4
  "description": "Intent-driven logic adapter for SolidJS. Connects intentx-runtime with Solid's fine-grained reactivity.",
5
5
  "license": "MIT",
6
6
  "author": "Delpi.Kye",
@@ -46,29 +46,29 @@
46
46
  "engines": {
47
47
  "node": ">=18"
48
48
  },
49
+ "scripts": {
50
+ "clean": "rimraf build",
51
+ "build": "rollup -c",
52
+ "cb": "npm run clean && npm run build"
53
+ },
49
54
  "peerDependencies": {
50
55
  "solid-js": "^1.8.0"
51
56
  },
52
57
  "dependencies": {
53
- "intentx-runtime": ">=0.2.2"
58
+ "intentx-runtime": "^0.2.4"
54
59
  },
55
60
  "devDependencies": {
56
61
  "@rollup/plugin-commonjs": "^25.0.0",
57
62
  "@rollup/plugin-node-resolve": "^15.2.3",
58
63
  "@rollup/plugin-terser": "^0.4.4",
59
64
  "@rollup/plugin-typescript": "^12.3.0",
65
+ "rimraf": "^5.0.5",
60
66
  "rollup": "^4.9.6",
61
67
  "rollup-plugin-dts": "^6.3.0",
62
68
  "rollup-plugin-peer-deps-external": "^2.2.4",
63
69
  "rollup-plugin-typescript2": "^0.36.0",
64
- "rimraf": "^5.0.5",
65
70
  "tslib": "^2.6.2",
66
71
  "typescript": "^5.3.3",
67
72
  "unplugin-solid": "^1.0.0"
68
- },
69
- "scripts": {
70
- "clean": "rimraf build",
71
- "build": "rollup -c",
72
- "cb": "npm run clean && npm run build"
73
73
  }
74
- }
74
+ }