@astrale-os/shell-react 0.2.9 → 0.2.10-beta.2

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 (339) hide show
  1. package/dist/application/apps/app-host.d.ts +4 -15
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +1 -1
  4. package/dist/application/apps/apps.hook.d.ts +7 -4
  5. package/dist/application/apps/apps.hook.d.ts.map +1 -1
  6. package/dist/application/apps/apps.hook.js +10 -2
  7. package/dist/application/apps/domains.hook.d.ts +1 -1
  8. package/dist/application/apps/domains.hook.d.ts.map +1 -1
  9. package/dist/application/apps/domains.hook.js +1 -1
  10. package/dist/application/apps/open-app.hook.d.ts +2 -3
  11. package/dist/application/apps/open-app.hook.d.ts.map +1 -1
  12. package/dist/application/index.d.ts +2 -4
  13. package/dist/application/index.d.ts.map +1 -1
  14. package/dist/application/index.js +2 -3
  15. package/dist/application/spaces/space.hook.d.ts +2 -2
  16. package/dist/application/spaces/space.hook.d.ts.map +1 -1
  17. package/dist/application/spaces/space.hook.js +2 -2
  18. package/dist/application/spaces/spaces.hook.d.ts +2 -3
  19. package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
  20. package/dist/application/spaces/spaces.hook.js +10 -3
  21. package/dist/auth/act-as.context.d.ts +15 -32
  22. package/dist/auth/act-as.context.d.ts.map +1 -1
  23. package/dist/auth/act-as.context.js +22 -66
  24. package/dist/auth/auth.hook.d.ts +1 -0
  25. package/dist/auth/auth.hook.d.ts.map +1 -1
  26. package/dist/auth/auth.hook.js +2 -22
  27. package/dist/auth/can.hook.d.ts +10 -38
  28. package/dist/auth/can.hook.d.ts.map +1 -1
  29. package/dist/auth/can.hook.js +35 -110
  30. package/dist/auth/index.d.ts +1 -0
  31. package/dist/auth/index.d.ts.map +1 -1
  32. package/dist/auth/self.hook.d.ts +2 -2
  33. package/dist/auth/self.hook.d.ts.map +1 -1
  34. package/dist/auth/self.hook.js +0 -7
  35. package/dist/auth/session-kernel.d.ts +2 -3
  36. package/dist/auth/session-kernel.d.ts.map +1 -1
  37. package/dist/auth/session-kernel.js +4 -13
  38. package/dist/components/boundaries.d.ts +47 -0
  39. package/dist/components/boundaries.d.ts.map +1 -0
  40. package/dist/components/boundaries.js +55 -0
  41. package/dist/components/can.d.ts +11 -0
  42. package/dist/components/can.d.ts.map +1 -0
  43. package/dist/components/can.js +5 -0
  44. package/dist/components/index.d.ts +7 -0
  45. package/dist/components/index.d.ts.map +1 -0
  46. package/dist/components/index.js +4 -0
  47. package/dist/components/mount-domain-frontend.d.ts +22 -0
  48. package/dist/components/mount-domain-frontend.d.ts.map +1 -0
  49. package/dist/components/mount-domain-frontend.js +85 -0
  50. package/dist/components/view-app.d.ts +16 -0
  51. package/dist/components/view-app.d.ts.map +1 -0
  52. package/dist/components/view-app.js +16 -0
  53. package/dist/graph/call/call.hook.d.ts +8 -18
  54. package/dist/graph/call/call.hook.d.ts.map +1 -1
  55. package/dist/graph/call/call.hook.js +7 -13
  56. package/dist/graph/call/stream.hook.d.ts +12 -20
  57. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  58. package/dist/graph/call/stream.hook.js +55 -111
  59. package/dist/graph/graph.context.d.ts +4 -3
  60. package/dist/graph/graph.context.d.ts.map +1 -1
  61. package/dist/graph/graph.context.js +2 -8
  62. package/dist/graph/guards.error.d.ts +7 -8
  63. package/dist/graph/guards.error.d.ts.map +1 -1
  64. package/dist/graph/guards.error.js +11 -7
  65. package/dist/graph/index.d.ts +8 -16
  66. package/dist/graph/index.d.ts.map +1 -1
  67. package/dist/graph/index.js +3 -7
  68. package/dist/graph/memory/read/envelope.d.ts +22 -54
  69. package/dist/graph/memory/read/envelope.d.ts.map +1 -1
  70. package/dist/graph/memory/read/envelope.js +26 -20
  71. package/dist/graph/memory/read/idle.d.ts +1 -15
  72. package/dist/graph/memory/read/idle.d.ts.map +1 -1
  73. package/dist/graph/memory/read/idle.js +4 -13
  74. package/dist/graph/query-definition.hook.d.ts +11 -0
  75. package/dist/graph/query-definition.hook.d.ts.map +1 -0
  76. package/dist/graph/query-definition.hook.js +205 -0
  77. package/dist/graph/resource.d.ts +34 -0
  78. package/dist/graph/resource.d.ts.map +1 -0
  79. package/dist/graph/resource.js +244 -0
  80. package/dist/graph/store.d.ts +25 -0
  81. package/dist/graph/store.d.ts.map +1 -0
  82. package/dist/graph/store.js +69 -0
  83. package/dist/host/actions.hook.d.ts +34 -0
  84. package/dist/host/actions.hook.d.ts.map +1 -0
  85. package/dist/host/actions.hook.js +125 -0
  86. package/dist/host/components.d.ts +15 -0
  87. package/dist/host/components.d.ts.map +1 -0
  88. package/dist/host/components.js +14 -0
  89. package/dist/host/index.d.ts +5 -0
  90. package/dist/host/index.d.ts.map +1 -0
  91. package/dist/host/index.js +3 -0
  92. package/dist/index.d.ts +26 -37
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +20 -31
  95. package/dist/intents/envelope.d.ts +7 -19
  96. package/dist/intents/envelope.d.ts.map +1 -1
  97. package/dist/intents/envelope.js +2 -3
  98. package/dist/intents/send-intent.hook.d.ts +5 -7
  99. package/dist/intents/send-intent.hook.d.ts.map +1 -1
  100. package/dist/intents/send-intent.hook.js +17 -75
  101. package/dist/navigation/adapters/adapter.d.ts +5 -0
  102. package/dist/navigation/adapters/adapter.d.ts.map +1 -1
  103. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
  104. package/dist/navigation/adapters/memory.adapter.js +4 -0
  105. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  106. package/dist/navigation/adapters/url.adapter.js +57 -10
  107. package/dist/navigation/codec.d.ts +60 -0
  108. package/dist/navigation/codec.d.ts.map +1 -0
  109. package/dist/navigation/codec.js +121 -0
  110. package/dist/navigation/history.d.ts +11 -9
  111. package/dist/navigation/history.d.ts.map +1 -1
  112. package/dist/navigation/history.js +6 -8
  113. package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
  114. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
  115. package/dist/navigation/hooks/ancestors.hook.js +7 -51
  116. package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
  117. package/dist/navigation/hooks/location.hook.js +4 -6
  118. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
  119. package/dist/navigation/hooks/scope.hook.js +4 -6
  120. package/dist/navigation/index.d.ts +4 -2
  121. package/dist/navigation/index.d.ts.map +1 -1
  122. package/dist/navigation/index.js +2 -1
  123. package/dist/navigation/link.d.ts +12 -0
  124. package/dist/navigation/link.d.ts.map +1 -1
  125. package/dist/navigation/link.js +13 -2
  126. package/dist/navigation/location.d.ts +13 -40
  127. package/dist/navigation/location.d.ts.map +1 -1
  128. package/dist/navigation/location.js +14 -76
  129. package/dist/navigation/scope.context.d.ts +17 -26
  130. package/dist/navigation/scope.context.d.ts.map +1 -1
  131. package/dist/navigation/scope.context.js +140 -108
  132. package/dist/navigation/snapshot.d.ts +14 -19
  133. package/dist/navigation/snapshot.d.ts.map +1 -1
  134. package/dist/navigation/snapshot.js +48 -44
  135. package/dist/schema/action.hook.d.ts +44 -0
  136. package/dist/schema/action.hook.d.ts.map +1 -0
  137. package/dist/schema/action.hook.js +72 -0
  138. package/dist/schema/domain.hook.d.ts +12 -7
  139. package/dist/schema/domain.hook.d.ts.map +1 -1
  140. package/dist/schema/domain.hook.js +101 -4
  141. package/dist/schema/index.d.ts +9 -8
  142. package/dist/schema/index.d.ts.map +1 -1
  143. package/dist/schema/index.js +5 -7
  144. package/dist/schema/kernel.hook.d.ts +4 -9
  145. package/dist/schema/kernel.hook.d.ts.map +1 -1
  146. package/dist/schema/kernel.hook.js +4 -6
  147. package/dist/schema/mutation.hook.d.ts +9 -0
  148. package/dist/schema/mutation.hook.d.ts.map +1 -0
  149. package/dist/schema/mutation.hook.js +41 -0
  150. package/dist/schema/object.hook.d.ts +16 -0
  151. package/dist/schema/object.hook.d.ts.map +1 -0
  152. package/dist/schema/object.hook.js +46 -0
  153. package/dist/schema/relation.hook.d.ts +46 -0
  154. package/dist/schema/relation.hook.d.ts.map +1 -0
  155. package/dist/schema/relation.hook.js +136 -0
  156. package/dist/selection/live.d.ts +9 -17
  157. package/dist/selection/live.d.ts.map +1 -1
  158. package/dist/selection/live.js +65 -112
  159. package/dist/selection/scope.context.js +5 -4
  160. package/dist/session/boot/boot.d.ts +1 -13
  161. package/dist/session/boot/boot.d.ts.map +1 -1
  162. package/dist/session/boot/boot.js +9 -27
  163. package/dist/session/index.d.ts +1 -0
  164. package/dist/session/index.d.ts.map +1 -1
  165. package/dist/session/kernel-instance.hook.d.ts +1 -4
  166. package/dist/session/kernel-instance.hook.d.ts.map +1 -1
  167. package/dist/session/kernel-instance.hook.js +1 -5
  168. package/dist/session/provider.d.ts +9 -23
  169. package/dist/session/provider.d.ts.map +1 -1
  170. package/dist/session/provider.js +29 -75
  171. package/dist/session/session.context.d.ts +5 -0
  172. package/dist/session/session.context.d.ts.map +1 -1
  173. package/dist/window/adopt.d.ts +0 -1
  174. package/dist/window/adopt.d.ts.map +1 -1
  175. package/dist/window/hooks/target-node.hook.d.ts +10 -6
  176. package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
  177. package/dist/window/hooks/target-node.hook.js +14 -72
  178. package/dist/window/hooks/views-for.hook.d.ts +4 -3
  179. package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
  180. package/dist/window/hooks/views-for.hook.js +6 -22
  181. package/dist/window/hooks/windows.hook.d.ts.map +1 -1
  182. package/dist/window/hooks/windows.hook.js +3 -4
  183. package/dist/window/host.d.ts +9 -11
  184. package/dist/window/host.d.ts.map +1 -1
  185. package/dist/window/host.js +26 -62
  186. package/dist/window/hub.d.ts +2 -0
  187. package/dist/window/hub.d.ts.map +1 -1
  188. package/dist/window/hub.js +33 -0
  189. package/dist/window/index.d.ts +2 -2
  190. package/dist/window/index.d.ts.map +1 -1
  191. package/dist/window/index.js +2 -2
  192. package/dist/window/lifecycle/mount.d.ts +5 -44
  193. package/dist/window/lifecycle/mount.d.ts.map +1 -1
  194. package/dist/window/lifecycle/mount.js +14 -120
  195. package/dist/window/lifecycle/states.d.ts +0 -5
  196. package/dist/window/lifecycle/states.d.ts.map +1 -1
  197. package/package.json +9 -8
  198. package/src/application/apps/app-host.tsx +11 -15
  199. package/src/application/apps/apps.hook.ts +13 -6
  200. package/src/application/apps/domains.hook.ts +1 -1
  201. package/src/application/apps/open-app.hook.ts +3 -4
  202. package/src/application/index.ts +4 -6
  203. package/src/application/spaces/space.hook.ts +5 -6
  204. package/src/application/spaces/spaces.hook.ts +14 -9
  205. package/src/auth/act-as.context.tsx +37 -91
  206. package/src/auth/auth.hook.ts +2 -30
  207. package/src/auth/can.hook.ts +44 -135
  208. package/src/auth/index.ts +1 -0
  209. package/src/auth/self.hook.ts +2 -9
  210. package/src/auth/session-kernel.ts +6 -16
  211. package/src/components/boundaries.tsx +113 -0
  212. package/src/components/can.tsx +16 -0
  213. package/src/components/index.ts +14 -0
  214. package/src/components/mount-domain-frontend.tsx +158 -0
  215. package/src/components/view-app.tsx +49 -0
  216. package/src/graph/call/call.hook.ts +22 -27
  217. package/src/graph/call/stream.hook.ts +66 -143
  218. package/src/graph/graph.context.ts +6 -11
  219. package/src/graph/guards.error.ts +17 -55
  220. package/src/graph/index.ts +23 -17
  221. package/src/graph/memory/read/envelope.ts +40 -65
  222. package/src/graph/memory/read/idle.ts +5 -18
  223. package/src/graph/query-definition.hook.ts +270 -0
  224. package/src/graph/resource.ts +358 -0
  225. package/src/graph/store.ts +97 -0
  226. package/src/host/actions.hook.ts +165 -0
  227. package/src/host/components.tsx +29 -0
  228. package/src/host/index.ts +17 -0
  229. package/src/index.ts +136 -124
  230. package/src/intents/envelope.ts +7 -23
  231. package/src/intents/send-intent.hook.ts +24 -79
  232. package/src/navigation/adapters/adapter.ts +3 -0
  233. package/src/navigation/adapters/memory.adapter.ts +4 -0
  234. package/src/navigation/adapters/url.adapter.ts +48 -8
  235. package/src/navigation/codec.ts +190 -0
  236. package/src/navigation/history.ts +20 -11
  237. package/src/navigation/hooks/ancestors.hook.ts +10 -60
  238. package/src/navigation/hooks/location.hook.ts +4 -6
  239. package/src/navigation/hooks/scope.hook.ts +4 -6
  240. package/src/navigation/index.ts +18 -2
  241. package/src/navigation/link.tsx +27 -2
  242. package/src/navigation/location.ts +26 -93
  243. package/src/navigation/scope.context.tsx +151 -136
  244. package/src/navigation/snapshot.ts +69 -50
  245. package/src/schema/action.hook.ts +146 -0
  246. package/src/schema/domain.hook.ts +127 -11
  247. package/src/schema/index.ts +9 -30
  248. package/src/schema/kernel.hook.ts +6 -13
  249. package/src/schema/mutation.hook.ts +63 -0
  250. package/src/schema/object.hook.ts +85 -0
  251. package/src/schema/relation.hook.ts +253 -0
  252. package/src/selection/live.ts +75 -125
  253. package/src/selection/scope.context.tsx +4 -4
  254. package/src/session/boot/boot.ts +8 -33
  255. package/src/session/index.ts +1 -0
  256. package/src/session/kernel-instance.hook.ts +2 -11
  257. package/src/session/provider.tsx +34 -103
  258. package/src/session/session.context.ts +6 -0
  259. package/src/window/adopt.ts +0 -1
  260. package/src/window/hooks/target-node.hook.ts +20 -85
  261. package/src/window/hooks/views-for.hook.ts +12 -25
  262. package/src/window/hooks/windows.hook.ts +3 -4
  263. package/src/window/host.tsx +35 -77
  264. package/src/window/hub.ts +33 -0
  265. package/src/window/index.ts +3 -3
  266. package/src/window/lifecycle/mount.ts +15 -160
  267. package/src/window/lifecycle/states.ts +1 -5
  268. package/dist/application/roles.hook.d.ts +0 -7
  269. package/dist/application/roles.hook.d.ts.map +0 -1
  270. package/dist/application/roles.hook.js +0 -23
  271. package/dist/graph/memory/base.d.ts +0 -21
  272. package/dist/graph/memory/base.d.ts.map +0 -1
  273. package/dist/graph/memory/base.js +0 -33
  274. package/dist/graph/memory/read/read.d.ts +0 -9
  275. package/dist/graph/memory/read/read.d.ts.map +0 -1
  276. package/dist/graph/memory/read/read.js +0 -87
  277. package/dist/graph/memory/scope.d.ts +0 -7
  278. package/dist/graph/memory/scope.d.ts.map +0 -1
  279. package/dist/graph/memory/scope.js +0 -25
  280. package/dist/graph/mutate/move.hook.d.ts +0 -7
  281. package/dist/graph/mutate/move.hook.d.ts.map +0 -1
  282. package/dist/graph/mutate/move.hook.js +0 -49
  283. package/dist/graph/mutate/mutate.hook.d.ts +0 -17
  284. package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
  285. package/dist/graph/mutate/mutate.hook.js +0 -45
  286. package/dist/graph/query/children.hook.d.ts +0 -29
  287. package/dist/graph/query/children.hook.d.ts.map +0 -1
  288. package/dist/graph/query/children.hook.js +0 -64
  289. package/dist/graph/query/graph.hook.d.ts +0 -9
  290. package/dist/graph/query/graph.hook.d.ts.map +0 -1
  291. package/dist/graph/query/graph.hook.js +0 -5
  292. package/dist/graph/query/neighbors.hook.d.ts +0 -7
  293. package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
  294. package/dist/graph/query/neighbors.hook.js +0 -104
  295. package/dist/graph/query/node.hook.d.ts +0 -14
  296. package/dist/graph/query/node.hook.d.ts.map +0 -1
  297. package/dist/graph/query/node.hook.js +0 -43
  298. package/dist/graph/query/query.hook.d.ts +0 -14
  299. package/dist/graph/query/query.hook.d.ts.map +0 -1
  300. package/dist/graph/query/query.hook.js +0 -23
  301. package/dist/schema/bind-read.d.ts +0 -37
  302. package/dist/schema/bind-read.d.ts.map +0 -1
  303. package/dist/schema/bind-read.js +0 -205
  304. package/dist/schema/binding.d.ts +0 -21
  305. package/dist/schema/binding.d.ts.map +0 -1
  306. package/dist/schema/binding.js +0 -99
  307. package/dist/schema/function.hook.d.ts +0 -9
  308. package/dist/schema/function.hook.d.ts.map +0 -1
  309. package/dist/schema/function.hook.js +0 -40
  310. package/dist/schema/method.hook.d.ts +0 -14
  311. package/dist/schema/method.hook.d.ts.map +0 -1
  312. package/dist/schema/method.hook.js +0 -49
  313. package/dist/schema/tag.d.ts +0 -11
  314. package/dist/schema/tag.d.ts.map +0 -1
  315. package/dist/schema/tag.js +0 -11
  316. package/dist/schema/types.d.ts +0 -73
  317. package/dist/schema/types.d.ts.map +0 -1
  318. package/dist/schema/types.js +0 -1
  319. package/dist/schema/write.d.ts +0 -16
  320. package/dist/schema/write.d.ts.map +0 -1
  321. package/dist/schema/write.js +0 -56
  322. package/src/application/roles.hook.ts +0 -41
  323. package/src/graph/memory/base.ts +0 -50
  324. package/src/graph/memory/read/read.ts +0 -103
  325. package/src/graph/memory/scope.ts +0 -29
  326. package/src/graph/mutate/move.hook.ts +0 -70
  327. package/src/graph/mutate/mutate.hook.ts +0 -69
  328. package/src/graph/query/children.hook.ts +0 -136
  329. package/src/graph/query/graph.hook.ts +0 -13
  330. package/src/graph/query/neighbors.hook.ts +0 -159
  331. package/src/graph/query/node.hook.ts +0 -83
  332. package/src/graph/query/query.hook.ts +0 -42
  333. package/src/schema/bind-read.ts +0 -319
  334. package/src/schema/binding.ts +0 -146
  335. package/src/schema/function.hook.ts +0 -68
  336. package/src/schema/method.hook.ts +0 -103
  337. package/src/schema/tag.ts +0 -19
  338. package/src/schema/types.ts +0 -150
  339. package/src/schema/write.ts +0 -96
@@ -1,159 +0,0 @@
1
- import type { AnyBoundNode, EdgeNames } from '@astrale-os/kernel-client'
2
- import type { Schema } from '@astrale-os/kernel-dsl'
3
-
4
- /**
5
- * useOut / useIn (API §6) — the public typed traversal read hooks. Resolve
6
- * endpoints one-shot through `BoundNode.links.out/in` (`live: false`); become live with
7
- * no surface change once edge-endpoint ids land. Deviations tracked in API §6/G6.
8
- */
9
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
10
-
11
- import type { EndpointResult } from '../../schema/types.js'
12
- import type { ReadState, ReadOptions } from '../memory/read/envelope.js'
13
-
14
- import { schemaOf, tagSchema } from '../../schema/tag.js'
15
- import { isIdleInput } from '../memory/read/idle.js'
16
-
17
- export function useOut<S extends Schema, E extends EdgeNames<S>>(
18
- node: AnyBoundNode<S> | null | undefined,
19
- edge: E,
20
- opts?: ReadOptions,
21
- ): EndpointResult<S, E, 'to'> {
22
- return useEndpoint(node, edge, 'out', opts) as unknown as EndpointResult<S, E, 'to'>
23
- }
24
-
25
- export function useIn<S extends Schema, E extends EdgeNames<S>>(
26
- node: AnyBoundNode<S> | null | undefined,
27
- edge: E,
28
- opts?: ReadOptions,
29
- ): EndpointResult<S, E, 'from'> {
30
- return useEndpoint(node, edge, 'in', opts) as unknown as EndpointResult<S, E, 'from'>
31
- }
32
-
33
- type EndpointEnvelope<S extends Schema> = ReadState & {
34
- readonly node?: AnyBoundNode<S> | null
35
- readonly nodes?: readonly AnyBoundNode<S>[]
36
- }
37
-
38
- function useEndpoint<S extends Schema>(
39
- node: AnyBoundNode<S> | null | undefined,
40
- edge: EdgeNames<S>,
41
- side: 'out' | 'in',
42
- opts?: ReadOptions,
43
- ): EndpointEnvelope<S> {
44
- const schema = isIdleInput(node) ? undefined : schemaOf(node)
45
- const single = schema !== undefined && isSingleEndpoint(schema, edge, side)
46
- const key = `${node?.id ?? ''}\u0000${edge}\u0000${side}`
47
- const run = useCallback(async (): Promise<unknown> => {
48
- if (isIdleInput(node)) return null
49
- const result = await (side === 'out' ? node.links.out(edge) : node.links.in(edge))
50
- if (schema !== undefined) tagEndpoints(result, schema)
51
- return result
52
- // eslint-disable-next-line react-hooks/exhaustive-deps
53
- }, [node?.id, edge, side])
54
-
55
- const { data, pending, error, refetch } = useAsyncRead(
56
- isIdleInput(node) ? null : run,
57
- key,
58
- opts?.keepPrevious === true,
59
- )
60
-
61
- return useMemo<EndpointEnvelope<S>>(() => {
62
- const live: ReadState = { pending, error, live: false, seq: 0, refetch }
63
- if (isIdleInput(node)) return { ...live, node: null, nodes: EMPTY }
64
- if (single) {
65
- const value = Array.isArray(data) ? data[0] : data
66
- return { ...live, node: (value ?? null) as AnyBoundNode<S> | null }
67
- }
68
- const values = Array.isArray(data) ? data : data === null || data === undefined ? EMPTY : [data]
69
- return { ...live, nodes: values as readonly AnyBoundNode<S>[] }
70
- }, [node, data, pending, error, refetch, single])
71
- }
72
-
73
- // ── helpers ──────────────────────────────────────────────────────────────────
74
-
75
- const EMPTY: readonly never[] = Object.freeze([])
76
-
77
- function isSingleEndpoint(schema: Schema, edge: string, side: 'out' | 'in'): boolean {
78
- const definition = schema.classes[edge] as
79
- | {
80
- readonly from?: { readonly cardinality?: string }
81
- readonly to?: { readonly cardinality?: string }
82
- }
83
- | undefined
84
- const cardinality = (side === 'out' ? definition?.to : definition?.from)?.cardinality
85
- return cardinality === '1' || cardinality === '0..1'
86
- }
87
-
88
- function tagEndpoints(result: unknown, schema: Schema): void {
89
- if (Array.isArray(result)) for (const r of result) tagSchema(r, schema)
90
- else if (result !== null && result !== undefined) tagSchema(result, schema)
91
- }
92
-
93
- interface AsyncState<T> {
94
- data?: T
95
- pending: boolean
96
- error: unknown
97
- key: string | null
98
- }
99
-
100
- /** One-shot async read with pending/error/refetch and stale-response guarding. */
101
- function useAsyncRead<T>(
102
- run: (() => Promise<T>) | null,
103
- key: string,
104
- keepPrevious: boolean,
105
- ): AsyncState<T> & { refetch(): Promise<void> } {
106
- const [state, setState] = useState<AsyncState<T>>({
107
- pending: run !== null,
108
- error: undefined,
109
- key: run === null ? null : key,
110
- })
111
- const runRef = useRef(run)
112
- runRef.current = run
113
- const keyRef = useRef(key)
114
- keyRef.current = key
115
- const keepPreviousRef = useRef(keepPrevious)
116
- keepPreviousRef.current = keepPrevious
117
- const seq = useRef(0)
118
-
119
- const refetch = useCallback((): Promise<void> => {
120
- const current = runRef.current
121
- const currentKey = keyRef.current
122
- if (current === null) {
123
- setState({ pending: false, error: undefined, data: undefined, key: null })
124
- return Promise.resolve()
125
- }
126
- const my = ++seq.current
127
- setState((s) => ({
128
- data: s.key === currentKey || keepPreviousRef.current === true ? s.data : undefined,
129
- pending: true,
130
- error: undefined,
131
- key: currentKey,
132
- }))
133
- return current().then(
134
- (data) => {
135
- if (my === seq.current) {
136
- setState({ data, pending: false, error: undefined, key: currentKey })
137
- }
138
- },
139
- (error: unknown) => {
140
- if (my === seq.current) {
141
- setState((s) => ({ data: s.data, pending: false, error, key: currentKey }))
142
- }
143
- },
144
- )
145
- }, [])
146
-
147
- useEffect(() => {
148
- void refetch()
149
- }, [key, refetch])
150
-
151
- const current = state.key === key
152
- return {
153
- data: current || keepPrevious ? state.data : undefined,
154
- pending: run !== null && (!current || state.pending),
155
- error: current ? state.error : undefined,
156
- key: current ? state.key : null,
157
- refetch,
158
- }
159
- }
@@ -1,83 +0,0 @@
1
- import type { NodeRefInput, TypeNames } from '@astrale-os/kernel-client'
2
- import type { PathLike } from '@astrale-os/kernel-client/graph'
3
- import type { Schema } from '@astrale-os/kernel-dsl'
4
-
5
- /**
6
- * useNode (API §5 + §6) — ONE public symbol, overloaded: pass a `Schema` (+ type)
7
- * for the typed `BoundNode` result, or a bare ref for the untyped `Node` result.
8
- * Both forms ride the SAME memory shape — a typed read and its untyped twin are
9
- * one cache entry, one liveness, one overlay. The runtime dispatches on the first
10
- * argument; a given call site is always one form, so hook order is stable.
11
- */
12
- import { useMemo } from 'react'
13
-
14
- import type { TypedNodeResult } from '../../schema/types.js'
15
- import type { ReadState, Node, ReadOptions } from '../memory/read/envelope.js'
16
-
17
- import { useNode as useNodeTyped } from '../../schema/bind-read.js'
18
- import { useRead } from '../memory/read/read.js'
19
-
20
- export interface NodeResult extends ReadState {
21
- /** The node, or `null` when missing ≡ masked (never throws NOT_FOUND). */
22
- readonly node: Node | null
23
- }
24
-
25
- /**
26
- * A `Schema` (from `defineSchema`) — its shape (`domain`/`classes`/`interfaces`)
27
- * is disjoint from a `PathLike` (`string | Path`), so this cleanly routes the
28
- * typed vs untyped overload at runtime.
29
- */
30
- function isSchema(value: unknown): value is Schema {
31
- return (
32
- typeof value === 'object' &&
33
- value !== null &&
34
- 'domain' in value &&
35
- 'classes' in value &&
36
- 'interfaces' in value
37
- )
38
- }
39
-
40
- /** One node by path — live, suspense-first; `null` ref is idle (§1.3). */
41
- function useNodeUntyped(ref: PathLike | null | undefined, opts?: ReadOptions): NodeResult {
42
- const r = useRead(ref, opts)
43
- return useMemo(
44
- () => ({
45
- pending: r.pending,
46
- error: r.error,
47
- live: r.live,
48
- seq: r.seq,
49
- refetch: r.refetch,
50
- node: r.first,
51
- }),
52
- [r],
53
- )
54
- }
55
-
56
- /** Typed: one node bound under `schema` as `type`. */
57
- export function useNode<S extends Schema, T extends TypeNames<S>>(
58
- schema: S,
59
- type: T,
60
- ref: NodeRefInput | null | undefined,
61
- opts?: ReadOptions,
62
- ): TypedNodeResult<S, T>
63
- /** Untyped: one node by ref — `null` ref is idle (§1.3). */
64
- export function useNode(ref: PathLike | null | undefined, opts?: ReadOptions): NodeResult
65
- // The implementation signature returns an erased supertype of both result
66
- // shapes — every overload above is assignable to it regardless of `BoundNode`
67
- // variance; callers only ever see the precise overload return types.
68
- export function useNode(
69
- a: unknown,
70
- b?: unknown,
71
- c?: unknown,
72
- d?: unknown,
73
- ): ReadState & { readonly node: unknown } {
74
- if (isSchema(a)) {
75
- return useNodeTyped(
76
- a,
77
- b as string,
78
- c as NodeRefInput | null | undefined,
79
- d as ReadOptions | undefined,
80
- )
81
- }
82
- return useNodeUntyped(a as PathLike | null | undefined, b as ReadOptions | undefined)
83
- }
@@ -1,42 +0,0 @@
1
- import type { GatherBuilder, QueryASTInput, QuerySource } from '@astrale-os/kernel-client/graph'
2
-
3
- /**
4
- * useQuery (API §5) — a structured read: a builder callback or an AST value;
5
- * `null` is idle (§1.3). Rides the §1 envelope over the shared memory, projecting
6
- * roots/first/nodes and the gathered-alias arms.
7
- */
8
- import { useMemo } from 'react'
9
-
10
- import type { ReadState, Node, ReadOptions, Windowed } from '../memory/read/envelope.js'
11
-
12
- import { useRead } from '../memory/read/read.js'
13
-
14
- export interface QueryResult extends ReadState, Windowed {
15
- readonly nodes: readonly Node[]
16
- readonly roots: readonly Node[]
17
- readonly first: Node | null
18
- gathered(alias: string): { readonly nodes: readonly Node[]; readonly first: Node | null }
19
- }
20
-
21
- /** A structured read — builder callback or AST value; `null` is idle (§1.3). */
22
- export function useQuery(
23
- build: ((q: QuerySource) => GatherBuilder) | QueryASTInput | null | undefined,
24
- opts?: ReadOptions,
25
- ): QueryResult {
26
- const r = useRead(build ?? null, opts)
27
- return useMemo(
28
- () => ({
29
- pending: r.pending,
30
- error: r.error,
31
- live: r.live,
32
- seq: r.seq,
33
- refetch: r.refetch,
34
- nodes: r.nodes,
35
- roots: r.roots,
36
- first: r.first,
37
- gathered: r.gathered,
38
- more: r.more,
39
- }),
40
- [r],
41
- )
42
- }
@@ -1,319 +0,0 @@
1
- import type { GatherBuilder, OrderInput, QuerySource } from '@astrale-os/kernel-client/graph'
2
- import type {
3
- LiveResult,
4
- ReadOptions as StoreReadOptions,
5
- ShapeInput,
6
- } from '@astrale-os/kernel-client/store'
7
- import type { Node } from '@astrale-os/kernel-core'
8
- import type { Schema } from '@astrale-os/kernel-dsl'
9
-
10
- import {
11
- BindTypeMismatchError,
12
- normalizeRef,
13
- type AnyBoundNode,
14
- type BoundNode,
15
- type DefOf,
16
- type NodeRefInput,
17
- type SchemaBoundView,
18
- type TypeNames,
19
- } from '@astrale-os/kernel-client'
20
- import { shapeInputToAST, stableStringify, stripCursors } from '@astrale-os/kernel-client/store'
21
- import { compileDomain } from '@astrale-os/kernel-core/domain'
22
- /**
23
- * Binder-over-memory composition (API §6, §1.7) — consumed by the `graph/query/`
24
- * overloads. Binds wire `Node`s from the shared memory to stable `BoundNode`s
25
- * (an unchanged wire node re-binds to the SAME instance), and composes those
26
- * binders with a `useSyncExternalStore` read substrate (`useShape`) into the typed
27
- * `useNode`/`useChildren` reads. A typed read and its untyped twin ride the SAME
28
- * memory shape, so they are one cache entry, one liveness, one overlay.
29
- */
30
- import { useCallback, useMemo, useRef, useSyncExternalStore } from 'react'
31
-
32
- import type { ReadState, ReadOptions } from '../graph/memory/read/envelope.js'
33
- import type { TypedChildrenResult, TypedNodeResult } from './types.js'
34
-
35
- import { useSessionKernel } from '../auth/session-kernel.js'
36
- import { idleReadState, isIdleInput } from '../graph/memory/read/idle.js'
37
- import { useMemory } from '../graph/memory/scope.js'
38
- import { bindingFor } from './binding.js'
39
- import { schemaOf, tagSchema } from './tag.js'
40
-
41
- // ── binder hooks ────────────────────────────────────────────────────────────────
42
-
43
- interface OneCache<S extends Schema> {
44
- wire: Node | null
45
- binding: SchemaBoundView<S>
46
- type: string
47
- bound: BoundNode<unknown, S> | null
48
- }
49
-
50
- /** Bind one wire node as `type`; stable while the wire node, binding, and type hold. */
51
- export function useBoundNode<S extends Schema, T extends TypeNames<S>>(
52
- binding: SchemaBoundView<S>,
53
- type: T,
54
- wire: Node | null | undefined,
55
- ): BoundNode<DefOf<S, T>, S> | null {
56
- const ref = useRef<OneCache<S> | null>(null)
57
- const node = wire ?? null
58
- let entry = ref.current
59
- if (entry === null || entry.wire !== node || entry.binding !== binding || entry.type !== type) {
60
- entry = {
61
- wire: node,
62
- binding,
63
- type,
64
- bound: node === null ? null : (binding.bind(type, node) as BoundNode<unknown, S>),
65
- }
66
- ref.current = entry
67
- }
68
- return entry.bound as BoundNode<DefOf<S, T>, S> | null
69
- }
70
-
71
- interface ManyCache<S extends Schema> {
72
- binding: SchemaBoundView<S>
73
- type: string
74
- perNode: WeakMap<Node, BoundNode<unknown, S>>
75
- last: readonly BoundNode<unknown, S>[]
76
- }
77
-
78
- /**
79
- * Bind many wire nodes as `type`; per-node identity + a stable array on no
80
- * change. `skipMismatch` drops nodes whose class is not `type` (a mixed-class
81
- * child set) instead of throwing.
82
- */
83
- export function useBoundNodes<S extends Schema, T extends TypeNames<S>>(
84
- binding: SchemaBoundView<S>,
85
- type: T,
86
- wires: readonly Node[],
87
- skipMismatch = false,
88
- ): readonly BoundNode<DefOf<S, T>, S>[] {
89
- const ref = useRef<ManyCache<S> | null>(null)
90
- if (ref.current === null || ref.current.binding !== binding || ref.current.type !== type) {
91
- ref.current = { binding, type, perNode: new WeakMap(), last: [] }
92
- }
93
- const cache = ref.current
94
- const next: BoundNode<unknown, S>[] = []
95
- for (const w of wires) {
96
- let b = cache.perNode.get(w)
97
- if (b === undefined) {
98
- try {
99
- b = binding.bind(type, w) as BoundNode<unknown, S>
100
- } catch (error) {
101
- if (skipMismatch && error instanceof BindTypeMismatchError) continue
102
- throw error
103
- }
104
- cache.perNode.set(w, b)
105
- }
106
- next.push(b)
107
- }
108
- if (sameArray(cache.last, next)) return cache.last as readonly BoundNode<DefOf<S, T>, S>[]
109
- cache.last = next
110
- return next as readonly BoundNode<DefOf<S, T>, S>[]
111
- }
112
-
113
- interface EndpointCache<S extends Schema> {
114
- binding: SchemaBoundView<S>
115
- perNode: WeakMap<Node, AnyBoundNode<S>>
116
- last: readonly AnyBoundNode<S>[]
117
- }
118
-
119
- /** Bind many wire nodes classlessly (traversal endpoints); per-node + stable array. */
120
- export function useBoundEndpoints<S extends Schema>(
121
- binding: SchemaBoundView<S>,
122
- wires: readonly Node[],
123
- ): readonly AnyBoundNode<S>[] {
124
- const ref = useRef<EndpointCache<S> | null>(null)
125
- if (ref.current === null || ref.current.binding !== binding) {
126
- ref.current = { binding, perNode: new WeakMap(), last: [] }
127
- }
128
- const cache = ref.current
129
- const next = wires.map((w) => {
130
- let b = cache.perNode.get(w)
131
- if (b === undefined) {
132
- b = binding.bindAny(w)
133
- cache.perNode.set(w, b)
134
- }
135
- return b
136
- })
137
- if (sameArray(cache.last, next)) return cache.last
138
- cache.last = next
139
- return next
140
- }
141
-
142
- function sameArray<A>(a: readonly A[], b: readonly A[]): boolean {
143
- return a.length === b.length && a.every((x, i) => x === b[i])
144
- }
145
-
146
- // ── read substrate ────────────────────────────────────────────────────────────
147
-
148
- /** Base read options plus the window growth mode (a `useChildren`-specific extra). */
149
- export type ShapeOptions = ReadOptions & { window?: 'append' | 'paged' }
150
-
151
- /** Store-facing options — render-time concerns (`suspend`/`keepPrevious`) stay here. */
152
- function toStoreOptions(opts?: ShapeOptions): StoreReadOptions | undefined {
153
- if (opts === undefined) return undefined
154
- const out: StoreReadOptions = {}
155
- if (opts.live !== undefined) out.live = opts.live
156
- if (opts.window !== undefined) out.window = opts.window
157
- if (opts.with !== undefined) out.with = opts.with as unknown as StoreReadOptions['with']
158
- return out
159
- }
160
-
161
- /** A stable string identity for a (shape, options) pair — the subscription key. */
162
- function keyOf(shape: ShapeInput, opts?: ShapeOptions): string {
163
- const ast = stripCursors(shapeInputToAST(shape))
164
- return `${stableStringify(ast)}|${opts?.live === false ? '0' : '1'}|${opts?.window ?? ''}|${opts?.with ?? ''}`
165
- }
166
-
167
- /**
168
- * Subscribe to a memory shape. `null` shape → idle (`null`, no I/O). A cold
169
- * shape suspends unless `suspend: false`. The returned `LiveResult` is the
170
- * unified read envelope — callers project `node`/`children`/`nodes`.
171
- */
172
- export function useShape(
173
- shape: ShapeInput | null | undefined,
174
- opts?: ShapeOptions,
175
- ): LiveResult | null {
176
- const memory = useMemory()
177
- const storeOpts = toStoreOptions(opts)
178
- const key = isIdleInput(shape) ? null : keyOf(shape, opts)
179
-
180
- const subscribe = useCallback(
181
- (onChange: () => void): (() => void) => {
182
- if (isIdleInput(shape)) return () => {}
183
- return memory.subscribe(shape, onChange, storeOpts)
184
- },
185
- // The shape's canonical identity is `key`; the captured `shape` is equivalent.
186
- // eslint-disable-next-line react-hooks/exhaustive-deps
187
- [memory, key],
188
- )
189
- const getSnapshot = useCallback(
190
- (): LiveResult | null => (isIdleInput(shape) ? null : memory.getSnapshot(shape, storeOpts)),
191
- // eslint-disable-next-line react-hooks/exhaustive-deps
192
- [memory, key],
193
- )
194
-
195
- const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
196
-
197
- if (!isIdleInput(shape) && opts?.suspend !== false && memory.peek(shape, storeOpts) === null) {
198
- // Cold FAILURE (§1.4): a rejected fetch with no data throws to the boundary;
199
- // re-throwing the promise would re-arm a fetch each retry (infinite loop).
200
- if (snapshot !== null && snapshot.error !== undefined) throw snapshot.error
201
- throw memory.promise(shape, storeOpts)
202
- }
203
- return snapshot
204
- }
205
-
206
- // ── typed reads (schema-first useNode, BoundNode-first useChildren) ──────────────
207
-
208
- export function useNode<S extends Schema, T extends TypeNames<S>>(
209
- schema: S,
210
- type: T,
211
- ref: NodeRefInput | null | undefined,
212
- opts?: ReadOptions,
213
- ): TypedNodeResult<S, T> {
214
- const binding = bindingFor(useSessionKernel(), schema, useMemory())
215
- const shape = isIdleInput(ref) ? null : normalizeRef(ref)
216
- const snap = useShape(shape, opts)
217
- const wire = snap?.node ?? null
218
- const bound = useBoundNode(binding, type, wire)
219
- if (bound !== null) tagSchema(bound, schema)
220
- const live = snap === null ? idleReadState() : readStateOf(snap)
221
- return useMemo(
222
- () => ({ ...live, node: bound }),
223
- [bound, live.pending, live.error, live.live, live.seq],
224
- )
225
- }
226
-
227
- export function useChildren<S extends Schema, T extends TypeNames<S>>(
228
- parent: AnyBoundNode<S> | null | undefined,
229
- opts: ReadOptions & {
230
- type: T
231
- order?: OrderInput
232
- limit?: number
233
- window?: 'append' | 'paged'
234
- },
235
- ): TypedChildrenResult<S, T> {
236
- const kernel = useSessionKernel()
237
- const memory = useMemory()
238
- const schema = isIdleInput(parent) ? null : requireSchema(parent)
239
- const binding = schema === null ? null : bindingFor(kernel, schema, memory)
240
-
241
- const parentRef = isIdleInput(parent) ? null : `@${parent.id}`
242
- const classRef = schema === null ? undefined : classRefFor(schema, opts.type)
243
- const shape =
244
- parentRef === null
245
- ? null
246
- : (q: QuerySource): GatherBuilder =>
247
- q.from(parentRef).children({
248
- ...(classRef !== undefined ? { classes: [classRef] } : {}),
249
- ...(opts.order !== undefined ? { order: opts.order } : {}),
250
- ...(opts.limit !== undefined ? { limit: opts.limit } : {}),
251
- })
252
-
253
- const snap = useShape(shape, opts)
254
- const wires = snap?.children ?? EMPTY
255
- const bound = useBoundNodes(
256
- (binding ?? UNBOUND) as unknown as SchemaBoundView<S>,
257
- opts.type,
258
- binding === null ? EMPTY : wires,
259
- true,
260
- )
261
- if (schema !== null) for (const b of bound) tagSchema(b, schema)
262
-
263
- const live = snap === null ? idleReadState() : readStateOf(snap)
264
- const more = snap?.more ?? IDLE_MORE
265
- return useMemo(
266
- () => ({ ...live, more, children: bound }),
267
- [bound, more, live.pending, live.error, live.live, live.seq],
268
- )
269
- }
270
-
271
- // ── helpers ──────────────────────────────────────────────────────────────────
272
-
273
- const EMPTY: readonly never[] = Object.freeze([])
274
- const IDLE_MORE = { has: false, load: () => Promise.resolve(), pending: false } as const
275
- const UNBOUND = {} as never
276
-
277
- function readStateOf(snap: {
278
- pending: boolean
279
- error: unknown
280
- live: boolean
281
- seq: number
282
- refetch(): Promise<void>
283
- }): ReadState {
284
- return {
285
- pending: snap.pending,
286
- error: snap.error,
287
- live: snap.live,
288
- seq: snap.seq,
289
- refetch: snap.refetch,
290
- }
291
- }
292
-
293
- /** Recover the schema a BoundNode was bound under; a clear error if it is untagged. */
294
- export function requireSchema(node: object): Schema {
295
- const schema = schemaOf(node)
296
- if (schema === undefined) {
297
- throw new Error(
298
- 'useChildren: the parent was not produced by a shell-react typed binding — ' +
299
- 'obtain it from useNode / useDomain(schema).bind() so its schema is known.',
300
- )
301
- }
302
- return schema
303
- }
304
-
305
- const compiledCache = new WeakMap<Schema, ReturnType<typeof compileDomain>>()
306
-
307
- /** The descent class ref for a type name (class or interface), or undefined. */
308
- function classRefFor(schema: Schema, type: string): string | undefined {
309
- let compiled = compiledCache.get(schema)
310
- if (compiled === undefined) {
311
- compiled = compileDomain(schema)
312
- compiledCache.set(schema, compiled)
313
- }
314
- const accessor = compiled.$ as unknown as {
315
- c(name: string): { path?: { class?: { raw: string } } } | undefined
316
- i(name: string): { path?: { class?: { raw: string } } } | undefined
317
- }
318
- return accessor.c(type)?.path?.class?.raw ?? accessor.i(type)?.path?.class?.raw
319
- }