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 +124 -57
- package/build/index.d.ts +9 -14
- package/build/logic/context.d.ts +4 -5
- package/build/logic/types.d.ts +2 -8
- package/build/logic/useLogic.d.ts +7 -6
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
`intentx-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
|
-
❌
|
|
31
|
-
❌
|
|
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
|
-
## 🧠
|
|
36
|
+
## 🧠 Mental Model
|
|
37
|
+
|
|
37
38
|
```txt
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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-
|
|
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
|
-
|
|
80
|
-
inc() {
|
|
81
|
-
setState(
|
|
82
|
-
|
|
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
|
-
|
|
94
|
-
|
|
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.
|
|
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
|
-
## 📡
|
|
154
|
+
## 📡 Multiple Logic Communication (Bus)
|
|
152
155
|
|
|
153
|
-
|
|
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
|
-
|
|
180
|
+
<b>How it works</b>
|
|
160
181
|
|
|
161
|
-
|
|
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
|
-
|
|
200
|
+
→ uses a default global scope bus.
|
|
169
201
|
|
|
170
|
-
|
|
171
|
-
|
|
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(
|
|
176
|
-
|
|
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
|
-
|
|
321
|
-
async
|
|
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,
|
|
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
|
|
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
|
-
|
|
17
|
+
type LogicOptions = {
|
|
24
18
|
scope?: Scope | string;
|
|
25
19
|
sharedBus?: boolean;
|
|
26
|
-
bus?:
|
|
27
|
-
}
|
|
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?:
|
|
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:
|
|
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 {
|
|
33
|
+
export type { IntentBus, LogicApi, LogicOptions };
|
package/build/logic/context.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { LogicFactory, LogicActions } from "intentx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
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").
|
|
7
|
+
store: import("./types").LogicApi<S, C, A>;
|
|
9
8
|
};
|
|
10
9
|
export declare function useLogicContext<T>(key: string): T;
|
package/build/logic/types.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import type { LogicActions } from "intentx-runtime";
|
|
2
|
-
export type
|
|
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 {
|
|
3
|
-
import type {
|
|
4
|
-
export
|
|
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?:
|
|
8
|
-
}
|
|
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
|
|
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": "
|
|
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
|
+
}
|