@ersbeth/picoflow 0.2.3 → 1.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.
Files changed (248) hide show
  1. package/.cursor/plans/update-js-e795d61b.plan.md +567 -0
  2. package/.gitlab-ci.yml +24 -0
  3. package/.vscode/settings.json +3 -3
  4. package/CHANGELOG.md +51 -0
  5. package/IMPLEMENTATION_GUIDE.md +1578 -0
  6. package/README.md +62 -25
  7. package/biome.json +32 -32
  8. package/dist/picoflow.js +557 -1099
  9. package/dist/types/advanced/array.d.ts +0 -6
  10. package/dist/types/advanced/array.d.ts.map +1 -1
  11. package/dist/types/advanced/index.d.ts +5 -5
  12. package/dist/types/advanced/index.d.ts.map +1 -1
  13. package/dist/types/advanced/map.d.ts +114 -23
  14. package/dist/types/advanced/map.d.ts.map +1 -1
  15. package/dist/types/advanced/resource.d.ts +51 -12
  16. package/dist/types/advanced/resource.d.ts.map +1 -1
  17. package/dist/types/advanced/resourceAsync.d.ts +28 -13
  18. package/dist/types/advanced/resourceAsync.d.ts.map +1 -1
  19. package/dist/types/advanced/stream.d.ts +74 -16
  20. package/dist/types/advanced/stream.d.ts.map +1 -1
  21. package/dist/types/advanced/streamAsync.d.ts +69 -15
  22. package/dist/types/advanced/streamAsync.d.ts.map +1 -1
  23. package/dist/types/basic/constant.d.ts +44 -16
  24. package/dist/types/basic/constant.d.ts.map +1 -1
  25. package/dist/types/basic/derivation.d.ts +73 -24
  26. package/dist/types/basic/derivation.d.ts.map +1 -1
  27. package/dist/types/basic/disposable.d.ts +65 -6
  28. package/dist/types/basic/disposable.d.ts.map +1 -1
  29. package/dist/types/basic/effect.d.ts +27 -16
  30. package/dist/types/basic/effect.d.ts.map +1 -1
  31. package/dist/types/basic/index.d.ts +7 -8
  32. package/dist/types/basic/index.d.ts.map +1 -1
  33. package/dist/types/basic/observable.d.ts +62 -13
  34. package/dist/types/basic/observable.d.ts.map +1 -1
  35. package/dist/types/basic/signal.d.ts +35 -6
  36. package/dist/types/basic/signal.d.ts.map +1 -1
  37. package/dist/types/basic/state.d.ts +25 -4
  38. package/dist/types/basic/state.d.ts.map +1 -1
  39. package/dist/types/basic/trackingContext.d.ts +33 -0
  40. package/dist/types/basic/trackingContext.d.ts.map +1 -0
  41. package/dist/types/creators.d.ts +271 -26
  42. package/dist/types/creators.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +60 -7
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/solid/converters.d.ts +5 -5
  46. package/dist/types/solid/converters.d.ts.map +1 -1
  47. package/dist/types/solid/index.d.ts +2 -2
  48. package/dist/types/solid/index.d.ts.map +1 -1
  49. package/dist/types/solid/primitives.d.ts +96 -4
  50. package/dist/types/solid/primitives.d.ts.map +1 -1
  51. package/docs/.vitepress/config.mts +110 -0
  52. package/docs/api/classes/FlowArray.md +489 -0
  53. package/docs/api/classes/FlowConstant.md +350 -0
  54. package/docs/api/classes/FlowDerivation.md +334 -0
  55. package/docs/api/classes/FlowEffect.md +100 -0
  56. package/docs/api/classes/FlowMap.md +512 -0
  57. package/docs/api/classes/FlowObservable.md +306 -0
  58. package/docs/api/classes/FlowResource.md +380 -0
  59. package/docs/api/classes/FlowResourceAsync.md +362 -0
  60. package/docs/api/classes/FlowSignal.md +160 -0
  61. package/docs/api/classes/FlowState.md +368 -0
  62. package/docs/api/classes/FlowStream.md +367 -0
  63. package/docs/api/classes/FlowStreamAsync.md +364 -0
  64. package/docs/api/classes/SolidDerivation.md +75 -0
  65. package/docs/api/classes/SolidResource.md +91 -0
  66. package/docs/api/classes/SolidState.md +71 -0
  67. package/docs/api/classes/TrackingContext.md +33 -0
  68. package/docs/api/functions/array.md +58 -0
  69. package/docs/api/functions/constant.md +45 -0
  70. package/docs/api/functions/derivation.md +53 -0
  71. package/docs/api/functions/effect.md +49 -0
  72. package/docs/api/functions/from.md +220 -0
  73. package/docs/api/functions/isDisposable.md +49 -0
  74. package/docs/api/functions/map.md +57 -0
  75. package/docs/api/functions/resource.md +52 -0
  76. package/docs/api/functions/resourceAsync.md +50 -0
  77. package/docs/api/functions/signal.md +36 -0
  78. package/docs/api/functions/state.md +47 -0
  79. package/docs/api/functions/stream.md +53 -0
  80. package/docs/api/functions/streamAsync.md +50 -0
  81. package/docs/api/index.md +118 -0
  82. package/docs/api/interfaces/FlowDisposable.md +65 -0
  83. package/docs/api/interfaces/SolidObservable.md +19 -0
  84. package/docs/api/type-aliases/FlowArrayAction.md +49 -0
  85. package/docs/api/type-aliases/FlowStreamDisposer.md +15 -0
  86. package/docs/api/type-aliases/FlowStreamSetter.md +27 -0
  87. package/docs/api/type-aliases/FlowStreamUpdater.md +32 -0
  88. package/docs/api/type-aliases/NotPromise.md +18 -0
  89. package/docs/api/type-aliases/SolidGetter.md +17 -0
  90. package/docs/api/typedoc-sidebar.json +1 -0
  91. package/docs/examples/examples.md +2313 -0
  92. package/docs/examples/patterns.md +649 -0
  93. package/docs/guide/advanced/disposal.md +426 -0
  94. package/docs/guide/advanced/solidjs.md +221 -0
  95. package/docs/guide/advanced/upgrading.md +464 -0
  96. package/docs/guide/introduction/concepts.md +56 -0
  97. package/docs/guide/introduction/conventions.md +61 -0
  98. package/docs/guide/introduction/getting-started.md +134 -0
  99. package/docs/guide/introduction/lifecycle.md +371 -0
  100. package/docs/guide/primitives/array.md +400 -0
  101. package/docs/guide/primitives/constant.md +380 -0
  102. package/docs/guide/primitives/derivations.md +348 -0
  103. package/docs/guide/primitives/effects.md +458 -0
  104. package/docs/guide/primitives/map.md +387 -0
  105. package/docs/guide/primitives/overview.md +175 -0
  106. package/docs/guide/primitives/resources.md +858 -0
  107. package/docs/guide/primitives/signal.md +259 -0
  108. package/docs/guide/primitives/state.md +368 -0
  109. package/docs/guide/primitives/streams.md +931 -0
  110. package/docs/index.md +47 -0
  111. package/docs/public/logo.svg +1 -0
  112. package/package.json +57 -41
  113. package/src/advanced/array.ts +208 -210
  114. package/src/advanced/index.ts +7 -7
  115. package/src/advanced/map.ts +178 -68
  116. package/src/advanced/resource.ts +87 -43
  117. package/src/advanced/resourceAsync.ts +62 -42
  118. package/src/advanced/stream.ts +113 -50
  119. package/src/advanced/streamAsync.ts +120 -61
  120. package/src/basic/constant.ts +82 -49
  121. package/src/basic/derivation.ts +128 -84
  122. package/src/basic/disposable.ts +74 -15
  123. package/src/basic/effect.ts +85 -77
  124. package/src/basic/index.ts +7 -8
  125. package/src/basic/observable.ts +94 -36
  126. package/src/basic/signal.ts +133 -105
  127. package/src/basic/state.ts +46 -25
  128. package/src/basic/trackingContext.ts +45 -0
  129. package/src/creators.ts +297 -54
  130. package/src/index.ts +96 -43
  131. package/src/solid/converters.ts +186 -67
  132. package/src/solid/index.ts +8 -2
  133. package/src/solid/primitives.ts +167 -65
  134. package/test/array.test.ts +592 -612
  135. package/test/constant.test.ts +31 -33
  136. package/test/derivation.test.ts +531 -536
  137. package/test/effect.test.ts +21 -21
  138. package/test/map.test.ts +233 -137
  139. package/test/resource.test.ts +119 -121
  140. package/test/resourceAsync.test.ts +98 -100
  141. package/test/signal.test.ts +51 -55
  142. package/test/state.test.ts +186 -168
  143. package/test/stream.test.ts +189 -189
  144. package/test/streamAsync.test.ts +186 -186
  145. package/tsconfig.json +19 -18
  146. package/typedoc.json +37 -0
  147. package/vite.config.ts +23 -20
  148. package/vitest.config.ts +7 -7
  149. package/api/doc/index.md +0 -31
  150. package/api/doc/picoflow.array.md +0 -55
  151. package/api/doc/picoflow.constant.md +0 -55
  152. package/api/doc/picoflow.derivation.md +0 -55
  153. package/api/doc/picoflow.effect.md +0 -55
  154. package/api/doc/picoflow.flowarray._constructor_.md +0 -49
  155. package/api/doc/picoflow.flowarray._lastaction.md +0 -13
  156. package/api/doc/picoflow.flowarray.clear.md +0 -17
  157. package/api/doc/picoflow.flowarray.dispose.md +0 -55
  158. package/api/doc/picoflow.flowarray.get.md +0 -19
  159. package/api/doc/picoflow.flowarray.length.md +0 -13
  160. package/api/doc/picoflow.flowarray.md +0 -273
  161. package/api/doc/picoflow.flowarray.pop.md +0 -17
  162. package/api/doc/picoflow.flowarray.push.md +0 -53
  163. package/api/doc/picoflow.flowarray.set.md +0 -53
  164. package/api/doc/picoflow.flowarray.setitem.md +0 -69
  165. package/api/doc/picoflow.flowarray.shift.md +0 -17
  166. package/api/doc/picoflow.flowarray.splice.md +0 -85
  167. package/api/doc/picoflow.flowarray.unshift.md +0 -53
  168. package/api/doc/picoflow.flowarrayaction.md +0 -37
  169. package/api/doc/picoflow.flowconstant._constructor_.md +0 -49
  170. package/api/doc/picoflow.flowconstant.get.md +0 -25
  171. package/api/doc/picoflow.flowconstant.md +0 -88
  172. package/api/doc/picoflow.flowderivation._constructor_.md +0 -49
  173. package/api/doc/picoflow.flowderivation.get.md +0 -23
  174. package/api/doc/picoflow.flowderivation.md +0 -86
  175. package/api/doc/picoflow.flowdisposable.dispose.md +0 -55
  176. package/api/doc/picoflow.flowdisposable.md +0 -43
  177. package/api/doc/picoflow.floweffect._constructor_.md +0 -54
  178. package/api/doc/picoflow.floweffect.dispose.md +0 -21
  179. package/api/doc/picoflow.floweffect.disposed.md +0 -13
  180. package/api/doc/picoflow.floweffect.md +0 -131
  181. package/api/doc/picoflow.flowgetter.md +0 -15
  182. package/api/doc/picoflow.flowmap._lastdeleted.md +0 -21
  183. package/api/doc/picoflow.flowmap._lastset.md +0 -21
  184. package/api/doc/picoflow.flowmap.delete.md +0 -61
  185. package/api/doc/picoflow.flowmap.md +0 -133
  186. package/api/doc/picoflow.flowmap.setat.md +0 -77
  187. package/api/doc/picoflow.flowobservable.get.md +0 -19
  188. package/api/doc/picoflow.flowobservable.md +0 -68
  189. package/api/doc/picoflow.flowobservable.subscribe.md +0 -55
  190. package/api/doc/picoflow.flowresource._constructor_.md +0 -49
  191. package/api/doc/picoflow.flowresource.fetch.md +0 -27
  192. package/api/doc/picoflow.flowresource.get.md +0 -23
  193. package/api/doc/picoflow.flowresource.md +0 -100
  194. package/api/doc/picoflow.flowresourceasync._constructor_.md +0 -49
  195. package/api/doc/picoflow.flowresourceasync.fetch.md +0 -27
  196. package/api/doc/picoflow.flowresourceasync.get.md +0 -23
  197. package/api/doc/picoflow.flowresourceasync.md +0 -100
  198. package/api/doc/picoflow.flowsignal.dispose.md +0 -59
  199. package/api/doc/picoflow.flowsignal.disposed.md +0 -18
  200. package/api/doc/picoflow.flowsignal.md +0 -112
  201. package/api/doc/picoflow.flowsignal.trigger.md +0 -21
  202. package/api/doc/picoflow.flowstate.md +0 -52
  203. package/api/doc/picoflow.flowstate.set.md +0 -61
  204. package/api/doc/picoflow.flowstream._constructor_.md +0 -49
  205. package/api/doc/picoflow.flowstream.dispose.md +0 -21
  206. package/api/doc/picoflow.flowstream.get.md +0 -23
  207. package/api/doc/picoflow.flowstream.md +0 -100
  208. package/api/doc/picoflow.flowstreamasync._constructor_.md +0 -54
  209. package/api/doc/picoflow.flowstreamasync.dispose.md +0 -21
  210. package/api/doc/picoflow.flowstreamasync.get.md +0 -23
  211. package/api/doc/picoflow.flowstreamasync.md +0 -100
  212. package/api/doc/picoflow.flowstreamdisposer.md +0 -13
  213. package/api/doc/picoflow.flowstreamsetter.md +0 -13
  214. package/api/doc/picoflow.flowstreamupdater.md +0 -19
  215. package/api/doc/picoflow.flowwatcher.md +0 -15
  216. package/api/doc/picoflow.from.md +0 -55
  217. package/api/doc/picoflow.from_1.md +0 -55
  218. package/api/doc/picoflow.from_2.md +0 -55
  219. package/api/doc/picoflow.from_3.md +0 -55
  220. package/api/doc/picoflow.from_4.md +0 -55
  221. package/api/doc/picoflow.from_5.md +0 -55
  222. package/api/doc/picoflow.isdisposable.md +0 -55
  223. package/api/doc/picoflow.map.md +0 -59
  224. package/api/doc/picoflow.md +0 -544
  225. package/api/doc/picoflow.resource.md +0 -55
  226. package/api/doc/picoflow.resourceasync.md +0 -55
  227. package/api/doc/picoflow.signal.md +0 -19
  228. package/api/doc/picoflow.solidderivation._constructor_.md +0 -49
  229. package/api/doc/picoflow.solidderivation.get.md +0 -13
  230. package/api/doc/picoflow.solidderivation.md +0 -94
  231. package/api/doc/picoflow.solidgetter.md +0 -13
  232. package/api/doc/picoflow.solidobservable.get.md +0 -13
  233. package/api/doc/picoflow.solidobservable.md +0 -57
  234. package/api/doc/picoflow.solidresource._constructor_.md +0 -49
  235. package/api/doc/picoflow.solidresource.get.md +0 -13
  236. package/api/doc/picoflow.solidresource.latest.md +0 -13
  237. package/api/doc/picoflow.solidresource.md +0 -157
  238. package/api/doc/picoflow.solidresource.refetch.md +0 -13
  239. package/api/doc/picoflow.solidresource.state.md +0 -13
  240. package/api/doc/picoflow.solidstate._constructor_.md +0 -49
  241. package/api/doc/picoflow.solidstate.get.md +0 -13
  242. package/api/doc/picoflow.solidstate.md +0 -115
  243. package/api/doc/picoflow.solidstate.set.md +0 -13
  244. package/api/doc/picoflow.state.md +0 -55
  245. package/api/doc/picoflow.stream.md +0 -55
  246. package/api/doc/picoflow.streamasync.md +0 -55
  247. package/api/picoflow.public.api.md +0 -244
  248. package/api-extractor.json +0 -61
@@ -1,73 +1,143 @@
1
- import { FlowDerivation, FlowEffect, FlowObservable, type FlowGetter } from '@ersbeth/picoflow';
2
- import { onCleanup, onMount } from 'solid-js';
3
- import { SolidResource, SolidState, type SolidDerivation } from './primitives';
4
-
1
+ import { onCleanup, onMount } from "solid-js";
2
+ import {
3
+ FlowDerivation,
4
+ FlowEffect,
5
+ FlowObservable,
6
+ type TrackingContext,
7
+ } from "../basic";
8
+ import { type SolidDerivation, SolidResource, SolidState } from "./primitives";
5
9
 
10
+ /**
11
+ * Converts a synchronous FlowObservable into a SolidJS signal.
12
+ *
13
+ * @param state - The FlowObservable to convert.
14
+ * @returns A SolidDerivation that mirrors the FlowObservable's value.
15
+ *
16
+ * @remarks
17
+ * This internal helper bridges PicoFlow's reactive system with SolidJS by:
18
+ * 1. Reading the initial value without tracking (using `pick()`)
19
+ * 2. Creating a FlowEffect that tracks the observable and updates the Solid signal
20
+ * 3. Properly disposing the effect when the Solid component unmounts
21
+ *
22
+ * @internal
23
+ */
6
24
  function fromSync<T>(state: FlowObservable<T>): SolidDerivation<T> {
25
+ const solidState = new SolidState<T>(state.pick());
7
26
 
8
- const solidState = new SolidState<T>(state.get());
27
+ let fx: FlowEffect;
9
28
 
10
- let fx: FlowEffect;
29
+ onMount(() => {
30
+ fx = new FlowEffect((t) => {
31
+ const value = state.get(t);
32
+ solidState.set(() => value);
33
+ });
34
+ });
11
35
 
12
- onMount(() => {
13
- fx = new FlowEffect((get) => {
14
- const value = get(state);
15
- solidState.set(() => value);
16
- });
17
- });
36
+ onCleanup(() => fx.dispose());
18
37
 
19
- onCleanup(() => fx.dispose());
20
-
21
- return solidState
38
+ return solidState;
22
39
  }
23
40
 
24
- function fromAsync<T>(derivation: FlowObservable<Promise<T>>): SolidResource<T> {
25
-
26
- const solidResource = new SolidResource<T>(async () => {
27
- const value = await derivation.get();
28
- return value;
29
- });
41
+ /**
42
+ * Converts an asynchronous FlowObservable (Promise-based) into a SolidJS resource.
43
+ *
44
+ * @param derivation - The FlowObservable that resolves to a Promise.
45
+ * @returns A SolidResource that mirrors the FlowObservable's async value.
46
+ *
47
+ * @remarks
48
+ * This internal helper bridges PicoFlow's async reactive system with SolidJS by:
49
+ * 1. Creating a SolidResource with an initial fetch using `pick()` (untracked)
50
+ * 2. Setting up a FlowEffect that tracks the Promise observable
51
+ * 3. Refetching the SolidResource whenever the Promise observable changes
52
+ * 4. Properly disposing the effect when the Solid component unmounts
53
+ *
54
+ * @internal
55
+ */
56
+ function fromAsync<T>(
57
+ derivation: FlowObservable<Promise<T>>,
58
+ ): SolidResource<T> {
59
+ const solidResource = new SolidResource<T>(async () => {
60
+ const value = await derivation.pick();
61
+ return value;
62
+ });
30
63
 
31
- let fx: FlowEffect;
64
+ let fx: FlowEffect;
32
65
 
33
- onMount(() => {
34
- fx = new FlowEffect(async (get) => {
35
- await get(derivation);
36
- solidResource.refetch();
37
- });
38
- });
66
+ onMount(() => {
67
+ fx = new FlowEffect(async (t) => {
68
+ await derivation.get(t);
69
+ solidResource.refetch();
70
+ });
71
+ });
39
72
 
40
- onCleanup(() => fx.dispose());
73
+ onCleanup(() => fx.dispose());
41
74
 
42
- return solidResource;
75
+ return solidResource;
43
76
  }
44
77
 
78
+ /**
79
+ * Converts a FlowObservable directly into a Solid primitive (signal or resource).
80
+ *
81
+ * @param flow - The FlowObservable to convert (can be sync or async).
82
+ * @returns A SolidDerivation for sync values or SolidResource for async values.
83
+ *
84
+ * @remarks
85
+ * This internal helper performs "shallow" conversion, meaning it converts the
86
+ * observable itself without creating an intermediate FlowDerivation. It inspects
87
+ * the initial value to determine if it's a Promise, then delegates to the
88
+ * appropriate converter (fromSync or fromAsync).
89
+ *
90
+ * @internal
91
+ */
45
92
  function shallowFrom<T>(flow: FlowObservable<Promise<T>>): SolidResource<T>;
46
93
  function shallowFrom<T>(flow: FlowObservable<T>): SolidDerivation<T>;
47
- function shallowFrom<T>(flow: FlowObservable<Promise<T>> | FlowObservable<T>): SolidDerivation<T> | SolidResource<T> {
48
- const initialValue = flow.get();
49
- const isAsync = initialValue instanceof Promise;
50
- if (isAsync) {
51
- return fromAsync(flow as FlowObservable<Promise<T>>);
52
- }
53
- return fromSync(flow as FlowObservable<T>);
94
+ function shallowFrom<T>(
95
+ flow: FlowObservable<Promise<T>> | FlowObservable<T>,
96
+ ): SolidDerivation<T> | SolidResource<T> {
97
+ const initialValue = flow.pick();
98
+ const isAsync = initialValue instanceof Promise;
99
+ if (isAsync) {
100
+ return fromAsync(flow as FlowObservable<Promise<T>>);
101
+ }
102
+ return fromSync(flow as FlowObservable<T>);
54
103
  }
55
104
 
56
- function deepFrom<T>(getter: (get: FlowGetter) => T): SolidDerivation<T>;
57
- function deepFrom<T>(getter: (get: FlowGetter) => Promise<T>): SolidResource<T>;
58
- function deepFrom<T>(getter: (get: FlowGetter) => T | Promise<T>): SolidDerivation<T> | SolidResource<T> {
59
- const derivation = new FlowDerivation((get) => {
60
- return getter(get);
61
- });
105
+ /**
106
+ * Converts a getter function with TrackingContext into a Solid primitive (signal or resource).
107
+ *
108
+ * @param getter - A function that computes a value using a TrackingContext.
109
+ * @returns A SolidDerivation for sync values or SolidResource for async values.
110
+ *
111
+ * @remarks
112
+ * This internal helper performs "deep" conversion by:
113
+ * 1. Creating a FlowDerivation from the getter function
114
+ * 2. Inspecting the initial computed value to determine if it's a Promise
115
+ * 3. Delegating to the appropriate converter (fromSync or fromAsync)
116
+ *
117
+ * This allows users to pass computation functions directly to `from()` without
118
+ * manually creating a FlowDerivation first.
119
+ *
120
+ * @internal
121
+ */
122
+ function deepFrom<T>(getter: (t: TrackingContext) => T): SolidDerivation<T>;
123
+ function deepFrom<T>(
124
+ getter: (t: TrackingContext) => Promise<T>,
125
+ ): SolidResource<T>;
126
+ function deepFrom<T>(
127
+ getter: (t: TrackingContext) => T | Promise<T>,
128
+ ): SolidDerivation<T> | SolidResource<T> {
129
+ const derivation = new FlowDerivation((t) => {
130
+ return getter(t);
131
+ });
62
132
 
63
- const initialValue = derivation.get();
64
- const isAsync = initialValue instanceof Promise;
133
+ const initialValue = derivation.pick();
134
+ const isAsync = initialValue instanceof Promise;
65
135
 
66
- if (isAsync) {
67
- return fromAsync(derivation as FlowObservable<Promise<T>>);
68
- }
136
+ if (isAsync) {
137
+ return fromAsync(derivation as FlowObservable<Promise<T>>);
138
+ }
69
139
 
70
- return fromSync(derivation as FlowObservable<T>);
140
+ return fromSync(derivation as FlowObservable<T>);
71
141
  }
72
142
 
73
143
  /**
@@ -86,7 +156,9 @@ export type NotPromise<T> = T extends Promise<unknown> ? never : T;
86
156
  *
87
157
  * @public
88
158
  */
89
- export function from<T>(flow: FlowObservable<Promise<NotPromise<T>>>): SolidResource<NotPromise<T>>;
159
+ export function from<T>(
160
+ flow: FlowObservable<Promise<NotPromise<T>>>,
161
+ ): SolidResource<NotPromise<T>>;
90
162
  /**
91
163
  * Converts a FlowObservable of a non-Promise value into a SolidDerivation.
92
164
  *
@@ -95,7 +167,9 @@ export function from<T>(flow: FlowObservable<Promise<NotPromise<T>>>): SolidReso
95
167
  *
96
168
  * @public
97
169
  */
98
- export function from<T>(flow: FlowObservable<NotPromise<T>>): SolidDerivation<NotPromise<T>>;
170
+ export function from<T>(
171
+ flow: FlowObservable<NotPromise<T>>,
172
+ ): SolidDerivation<NotPromise<T>>;
99
173
  /**
100
174
  * Converts a FlowObservable into a Solid derivation or resource, depending on whether the value is synchronous or asynchronous.
101
175
  *
@@ -105,7 +179,7 @@ export function from<T>(flow: FlowObservable<NotPromise<T>>): SolidDerivation<No
105
179
  * @public
106
180
  */
107
181
  export function from<T>(
108
- flow: FlowObservable<Promise<NotPromise<T>>> | FlowObservable<NotPromise<T>>,
182
+ flow: FlowObservable<Promise<NotPromise<T>>> | FlowObservable<NotPromise<T>>,
109
183
  ): SolidDerivation<NotPromise<T>> | SolidResource<NotPromise<T>>;
110
184
  /**
111
185
  * Converts a getter function returning a non-Promise value into a SolidDerivation.
@@ -115,7 +189,9 @@ export function from<T>(
115
189
  *
116
190
  * @public
117
191
  */
118
- export function from<T>(flow: (get: FlowGetter) => NotPromise<T>): SolidDerivation<NotPromise<T>>;
192
+ export function from<T>(
193
+ flow: (t: TrackingContext) => NotPromise<T>,
194
+ ): SolidDerivation<NotPromise<T>>;
119
195
  /**
120
196
  * Converts a getter function returning a Promise into a SolidResource.
121
197
  *
@@ -124,7 +200,9 @@ export function from<T>(flow: (get: FlowGetter) => NotPromise<T>): SolidDerivati
124
200
  *
125
201
  * @public
126
202
  */
127
- export function from<T>(flow: (get: FlowGetter) => Promise<NotPromise<T>>): SolidResource<NotPromise<T>>;
203
+ export function from<T>(
204
+ flow: (t: TrackingContext) => Promise<NotPromise<T>>,
205
+ ): SolidResource<NotPromise<T>>;
128
206
  /**
129
207
  * Converts a getter function into a Solid derivation or resource, depending on whether the returned value is synchronous or asynchronous.
130
208
  *
@@ -134,26 +212,67 @@ export function from<T>(flow: (get: FlowGetter) => Promise<NotPromise<T>>): Soli
134
212
  * @public
135
213
  */
136
214
  export function from<T>(
137
- flow: ((get: FlowGetter) => NotPromise<T>) | ((get: FlowGetter) => Promise<NotPromise<T>>),
215
+ flow:
216
+ | ((t: TrackingContext) => NotPromise<T>)
217
+ | ((t: TrackingContext) => Promise<NotPromise<T>>),
138
218
  ): SolidDerivation<T> | SolidResource<T>;
139
219
  /**
140
220
  * Converts a FlowObservable or getter function into a Solid derivation or resource, depending on whether the value is synchronous or asynchronous.
141
221
  *
142
- * - If passed a FlowObservable of a non-Promise value, returns a SolidDerivation.
143
- * - If passed a FlowObservable of a Promise, returns a SolidResource.
144
- * - If passed a getter function returning a non-Promise value, returns a SolidDerivation.
145
- * - If passed a getter function returning a Promise, returns a SolidResource.
146
- *
147
222
  * @param flow - The FlowObservable or getter function to convert.
148
- * @returns A SolidDerivation or SolidResource, depending on the input type.
223
+ * @returns A SolidDerivation or SolidResource, depending on the input type.
224
+ *
225
+ * @remarks
226
+ * This function bridges PicoFlow's reactive system with SolidJS, allowing you to use
227
+ * PicoFlow observables within Solid components. The conversion is automatic based on
228
+ * whether the value is a Promise or not:
229
+ *
230
+ * - **FlowObservable of non-Promise value** → SolidDerivation (reactive signal)
231
+ * - **FlowObservable of Promise** → SolidResource (async resource)
232
+ * - **Getter function returning non-Promise** → SolidDerivation (computed signal)
233
+ * - **Getter function returning Promise** → SolidResource (async computed resource)
234
+ *
235
+ * The created Solid primitives automatically subscribe to the PicoFlow observables and
236
+ * update when changes occur. The subscription is properly cleaned up when the Solid
237
+ * component unmounts.
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * import { from } from 'picoflow/solid';
242
+ * import { state } from 'picoflow';
243
+ *
244
+ * // Convert a PicoFlow state to a Solid signal
245
+ * const $count = state(0);
246
+ * const solidCount = from($count);
247
+ *
248
+ * // Use in a Solid component
249
+ * function Counter() {
250
+ * const count = solidCount.get(); // Solid's reactive get
251
+ * return <div>Count: {count}</div>;
252
+ * }
253
+ *
254
+ * // Or convert a computation function
255
+ * const solidDerived = from((t) => {
256
+ * return $count.get(t) * 2;
257
+ * });
258
+ * ```
259
+ *
149
260
  * @public
150
261
  */
151
262
  export function from<T>(
152
- flow: FlowObservable<Promise<T>> | FlowObservable<T> | ((get: FlowGetter) => T) | ((get: FlowGetter) => Promise<T>),
263
+ flow:
264
+ | FlowObservable<Promise<T>>
265
+ | FlowObservable<T>
266
+ | ((t: TrackingContext) => T)
267
+ | ((t: TrackingContext) => Promise<T>),
153
268
  ): SolidDerivation<T> | SolidResource<T> {
154
- if (flow instanceof FlowObservable) {
155
- return shallowFrom(flow as FlowObservable<T | Promise<T>>) as SolidDerivation<T> | SolidResource<T>;
156
- }
269
+ if (flow instanceof FlowObservable) {
270
+ return shallowFrom(flow as FlowObservable<T | Promise<T>>) as
271
+ | SolidDerivation<T>
272
+ | SolidResource<T>;
273
+ }
157
274
 
158
- return deepFrom(flow as (get: FlowGetter) => T | Promise<T>) as SolidDerivation<T> | SolidResource<T>;
159
- }
275
+ return deepFrom(flow as (t: TrackingContext) => T | Promise<T>) as
276
+ | SolidDerivation<T>
277
+ | SolidResource<T>;
278
+ }
@@ -1,2 +1,8 @@
1
- export { from } from './converters';
2
- export { SolidState, SolidResource, SolidDerivation, type SolidObservable, type SolidGetter } from './primitives';
1
+ export { from, type NotPromise } from "./converters";
2
+ export {
3
+ SolidDerivation,
4
+ type SolidGetter,
5
+ type SolidObservable,
6
+ SolidResource,
7
+ SolidState,
8
+ } from "./primitives";
@@ -1,4 +1,9 @@
1
- import { createMemo, createResource, createSignal, type ResourceFetcher, } from "solid-js";
1
+ import {
2
+ createMemo,
3
+ createResource,
4
+ createSignal,
5
+ type ResourceFetcher,
6
+ } from "solid-js";
2
7
 
3
8
  /**
4
9
  * A getter function or value for Solid state/derivation.
@@ -15,95 +20,192 @@ export type SolidGetter<T> = ((previous: T) => T) | T;
15
20
  * @public
16
21
  */
17
22
  export interface SolidObservable<T> {
18
- /**
19
- * Returns the current value.
20
- */
21
- get: () => T;
23
+ /**
24
+ * Returns the current value.
25
+ */
26
+ get: () => T;
22
27
  }
23
28
 
24
29
  /**
25
- * Solid-style state container, similar to a writable signal.
30
+ * Solid-style state container wrapping SolidJS's createSignal, providing a writable reactive signal.
31
+ *
32
+ * @remarks
33
+ * SolidState is a thin wrapper around SolidJS's `createSignal` that provides a class-based
34
+ * interface consistent with PicoFlow's API style. It's used internally by PicoFlow's Solid
35
+ * integration but can also be used directly in Solid components.
36
+ *
37
+ * Unlike PicoFlow's {@link FlowState} which uses explicit tracking context, SolidState
38
+ * relies on SolidJS's automatic dependency tracking within reactive contexts like
39
+ * `createEffect` or component render functions.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const count = new SolidState(0);
44
+ *
45
+ * // In a Solid component
46
+ * function Counter() {
47
+ * return <div>{count.get()}</div>; // Automatically reactive
48
+ * }
49
+ *
50
+ * // Update the value
51
+ * count.set(1);
52
+ * count.set(prev => prev + 1);
53
+ * ```
26
54
  *
27
55
  * @typeParam T - The value type.
28
56
  * @public
29
57
  */
30
58
  export class SolidState<T> implements SolidObservable<T> {
31
- /**
32
- * Returns the current value.
33
- */
34
- readonly get: () => T;
35
- /**
36
- * Sets the value or updates it using a getter function.
37
- */
38
- readonly set: (param: SolidGetter<T>) => void;
59
+ /**
60
+ * Returns the current value.
61
+ */
62
+ readonly get: () => T;
63
+ /**
64
+ * Sets the value or updates it using a getter function.
65
+ */
66
+ readonly set: (param: SolidGetter<T>) => void;
39
67
 
40
- /**
41
- * Creates a new SolidState with the given initial value.
42
- * @param initialValue - The initial value.
43
- */
44
- constructor(initialValue: T) {
45
- const [get, set] = createSignal<T>(initialValue);
46
- this.get = get;
47
- this.set = set;
48
- }
68
+ /**
69
+ * Creates a new SolidState with the given initial value.
70
+ * @param initialValue - The initial value.
71
+ */
72
+ constructor(initialValue: T) {
73
+ const [get, set] = createSignal<T>(initialValue);
74
+ this.get = get;
75
+ this.set = set;
76
+ }
49
77
  }
50
78
 
51
79
  type EffectFunction<Prev, Next extends Prev = Prev> = (v: Prev) => Next;
52
80
  /**
53
- * Solid-style derivation, similar to a computed/memoized value.
81
+ * Solid-style derivation wrapping SolidJS's createMemo, providing a computed reactive value.
82
+ *
83
+ * @remarks
84
+ * SolidDerivation is a thin wrapper around SolidJS's `createMemo` that provides a class-based
85
+ * interface consistent with PicoFlow's API style. It creates a memoized computation that
86
+ * automatically tracks its dependencies and recomputes only when they change.
87
+ *
88
+ * Unlike PicoFlow's {@link FlowDerivation} which uses explicit tracking context, SolidDerivation
89
+ * relies on SolidJS's automatic dependency tracking. The computation function runs within
90
+ * SolidJS's reactive scope and automatically subscribes to any signals accessed during execution.
91
+ *
92
+ * **Memoization:**
93
+ * The computed value is cached and only recomputed when tracked dependencies change,
94
+ * providing efficient derived state management.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const firstName = new SolidState('John');
99
+ * const lastName = new SolidState('Doe');
100
+ *
101
+ * const fullName = new SolidDerivation(() => {
102
+ * return `${firstName.get()} ${lastName.get()}`;
103
+ * });
104
+ *
105
+ * // In a Solid component
106
+ * function Display() {
107
+ * return <div>{fullName.get()}</div>; // Automatically updates
108
+ * }
109
+ * ```
54
110
  *
55
111
  * @typeParam T - The value type.
56
112
  * @public
57
113
  */
58
114
  export class SolidDerivation<T> implements SolidObservable<T> {
59
- /**
60
- * Returns the current derived value.
61
- */
62
- readonly get: () => T;
115
+ /**
116
+ * Returns the current derived value.
117
+ */
118
+ readonly get: () => T;
63
119
 
64
- /**
65
- * Creates a new SolidDerivation from a getter function or value.
66
- * @param calculator - The getter function or value.
67
- */
68
- constructor(calculator: SolidGetter<T>) {
69
- const get = createMemo<T>(calculator as EffectFunction<T | undefined, T>);
70
- this.get = get;
71
- }
120
+ /**
121
+ * Creates a new SolidDerivation from a getter function or value.
122
+ * @param calculator - The getter function or value.
123
+ */
124
+ constructor(calculator: SolidGetter<T>) {
125
+ const get = createMemo<T>(calculator as EffectFunction<T | undefined, T>);
126
+ this.get = get;
127
+ }
72
128
  }
73
129
 
74
130
  /**
75
- * Solid-style resource, similar to an async resource or data loader.
131
+ * Solid-style resource wrapping SolidJS's createResource, providing async data loading with reactive state.
132
+ *
133
+ * @remarks
134
+ * SolidResource is a thin wrapper around SolidJS's `createResource` that provides a class-based
135
+ * interface consistent with PicoFlow's API style. It manages asynchronous data fetching with
136
+ * built-in loading states, error handling, and automatic reactivity.
137
+ *
138
+ * Unlike PicoFlow's {@link FlowResource} or {@link FlowResourceAsync}, SolidResource integrates
139
+ * directly with SolidJS's Suspense and ErrorBoundary mechanisms, providing a first-class async
140
+ * data loading experience in Solid applications.
141
+ *
142
+ * **Resource States:**
143
+ * - `unresolved`: Initial state before first fetch
144
+ * - `pending`: Fetch is in progress
145
+ * - `ready`: Data has been successfully loaded
146
+ * - `refreshing`: Refetching while previous data is still available
147
+ * - `errored`: Fetch failed with an error
148
+ *
149
+ * **Properties:**
150
+ * - `get()`: Returns the current value (or undefined if not ready)
151
+ * - `state()`: Returns the current loading state
152
+ * - `latest()`: Returns the most recent successfully loaded value
153
+ * - `refetch()`: Triggers a new fetch operation
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const user = new SolidResource(async () => {
158
+ * const res = await fetch('/api/user');
159
+ * return res.json();
160
+ * });
161
+ *
162
+ * // In a Solid component
163
+ * function UserProfile() {
164
+ * return (
165
+ * <div>
166
+ * {user.state() === 'pending' && <p>Loading...</p>}
167
+ * {user.state() === 'ready' && <p>Name: {user.get()?.name}</p>}
168
+ * <button onClick={() => user.refetch()}>Refresh</button>
169
+ * </div>
170
+ * );
171
+ * }
172
+ * ```
76
173
  *
77
174
  * @typeParam T - The value type.
78
175
  * @public
79
176
  */
80
177
  export class SolidResource<T> implements SolidObservable<T | undefined> {
81
- /**
82
- * Returns the current value (or undefined if not yet loaded).
83
- */
84
- readonly get: () => T | undefined;
85
- /**
86
- * Returns the current resource state.
87
- */
88
- readonly state: () => 'unresolved' | 'pending' | 'errored' | 'ready' | 'refreshing';
89
- /**
90
- * Returns the latest successfully loaded value (or undefined).
91
- */
92
- readonly latest: () => T | undefined;
93
- /**
94
- * Triggers a refetch of the resource.
95
- */
96
- readonly refetch: () => void;
178
+ /**
179
+ * Returns the current value (or undefined if not yet loaded).
180
+ */
181
+ readonly get: () => T | undefined;
182
+ /**
183
+ * Returns the current resource state.
184
+ */
185
+ readonly state: () =>
186
+ | "unresolved"
187
+ | "pending"
188
+ | "errored"
189
+ | "ready"
190
+ | "refreshing";
191
+ /**
192
+ * Returns the latest successfully loaded value (or undefined).
193
+ */
194
+ readonly latest: () => T | undefined;
195
+ /**
196
+ * Triggers a refetch of the resource.
197
+ */
198
+ readonly refetch: () => void;
97
199
 
98
- /**
99
- * Creates a new SolidResource from a fetcher function.
100
- * @param fetcher - The async fetcher function.
101
- */
102
- constructor(fetcher: ResourceFetcher<true, T, unknown>) {
103
- const [get, set] = createResource<T>(fetcher);
104
- this.get = get;
105
- this.state = () => get.state;
106
- this.latest = () => get.latest;
107
- this.refetch = () => set.refetch();
108
- }
109
- }
200
+ /**
201
+ * Creates a new SolidResource from a fetcher function.
202
+ * @param fetcher - The async fetcher function.
203
+ */
204
+ constructor(fetcher: ResourceFetcher<true, T, unknown>) {
205
+ const [get, set] = createResource<T>(fetcher);
206
+ this.get = get;
207
+ this.state = () => get.state;
208
+ this.latest = () => get.latest;
209
+ this.refetch = () => set.refetch();
210
+ }
211
+ }