@astrale-os/shell-react 0.2.8 → 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 (342) hide show
  1. package/dist/application/apps/app-host.d.ts +7 -15
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +3 -2
  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 +11 -11
  184. package/dist/window/host.d.ts.map +1 -1
  185. package/dist/window/host.js +38 -54
  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 +3 -3
  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/dist/window/stage.d.ts.map +1 -1
  198. package/dist/window/stage.js +1 -0
  199. package/package.json +9 -8
  200. package/src/application/apps/app-host.tsx +17 -18
  201. package/src/application/apps/apps.hook.ts +13 -6
  202. package/src/application/apps/domains.hook.ts +1 -1
  203. package/src/application/apps/open-app.hook.ts +3 -4
  204. package/src/application/index.ts +4 -6
  205. package/src/application/spaces/space.hook.ts +5 -6
  206. package/src/application/spaces/spaces.hook.ts +14 -9
  207. package/src/auth/act-as.context.tsx +37 -91
  208. package/src/auth/auth.hook.ts +2 -30
  209. package/src/auth/can.hook.ts +44 -135
  210. package/src/auth/index.ts +1 -0
  211. package/src/auth/self.hook.ts +2 -9
  212. package/src/auth/session-kernel.ts +6 -16
  213. package/src/components/boundaries.tsx +113 -0
  214. package/src/components/can.tsx +16 -0
  215. package/src/components/index.ts +14 -0
  216. package/src/components/mount-domain-frontend.tsx +158 -0
  217. package/src/components/view-app.tsx +49 -0
  218. package/src/graph/call/call.hook.ts +22 -27
  219. package/src/graph/call/stream.hook.ts +66 -143
  220. package/src/graph/graph.context.ts +6 -11
  221. package/src/graph/guards.error.ts +17 -55
  222. package/src/graph/index.ts +23 -17
  223. package/src/graph/memory/read/envelope.ts +40 -65
  224. package/src/graph/memory/read/idle.ts +5 -18
  225. package/src/graph/query-definition.hook.ts +270 -0
  226. package/src/graph/resource.ts +358 -0
  227. package/src/graph/store.ts +97 -0
  228. package/src/host/actions.hook.ts +165 -0
  229. package/src/host/components.tsx +29 -0
  230. package/src/host/index.ts +17 -0
  231. package/src/index.ts +137 -123
  232. package/src/intents/envelope.ts +7 -23
  233. package/src/intents/send-intent.hook.ts +24 -79
  234. package/src/navigation/adapters/adapter.ts +3 -0
  235. package/src/navigation/adapters/memory.adapter.ts +4 -0
  236. package/src/navigation/adapters/url.adapter.ts +48 -8
  237. package/src/navigation/codec.ts +190 -0
  238. package/src/navigation/history.ts +20 -11
  239. package/src/navigation/hooks/ancestors.hook.ts +10 -60
  240. package/src/navigation/hooks/location.hook.ts +4 -6
  241. package/src/navigation/hooks/scope.hook.ts +4 -6
  242. package/src/navigation/index.ts +18 -2
  243. package/src/navigation/link.tsx +27 -2
  244. package/src/navigation/location.ts +26 -93
  245. package/src/navigation/scope.context.tsx +151 -136
  246. package/src/navigation/snapshot.ts +69 -50
  247. package/src/schema/action.hook.ts +146 -0
  248. package/src/schema/domain.hook.ts +127 -11
  249. package/src/schema/index.ts +9 -30
  250. package/src/schema/kernel.hook.ts +6 -13
  251. package/src/schema/mutation.hook.ts +63 -0
  252. package/src/schema/object.hook.ts +85 -0
  253. package/src/schema/relation.hook.ts +253 -0
  254. package/src/selection/live.ts +75 -125
  255. package/src/selection/scope.context.tsx +4 -4
  256. package/src/session/boot/boot.ts +8 -33
  257. package/src/session/index.ts +1 -0
  258. package/src/session/kernel-instance.hook.ts +2 -11
  259. package/src/session/provider.tsx +34 -103
  260. package/src/session/session.context.ts +6 -0
  261. package/src/window/adopt.ts +0 -1
  262. package/src/window/hooks/target-node.hook.ts +20 -85
  263. package/src/window/hooks/views-for.hook.ts +12 -25
  264. package/src/window/hooks/windows.hook.ts +3 -4
  265. package/src/window/host.tsx +51 -68
  266. package/src/window/hub.ts +33 -0
  267. package/src/window/index.ts +4 -4
  268. package/src/window/lifecycle/mount.ts +15 -160
  269. package/src/window/lifecycle/states.ts +1 -5
  270. package/src/window/stage.tsx +1 -0
  271. package/dist/application/roles.hook.d.ts +0 -7
  272. package/dist/application/roles.hook.d.ts.map +0 -1
  273. package/dist/application/roles.hook.js +0 -23
  274. package/dist/graph/memory/base.d.ts +0 -21
  275. package/dist/graph/memory/base.d.ts.map +0 -1
  276. package/dist/graph/memory/base.js +0 -33
  277. package/dist/graph/memory/read/read.d.ts +0 -9
  278. package/dist/graph/memory/read/read.d.ts.map +0 -1
  279. package/dist/graph/memory/read/read.js +0 -87
  280. package/dist/graph/memory/scope.d.ts +0 -7
  281. package/dist/graph/memory/scope.d.ts.map +0 -1
  282. package/dist/graph/memory/scope.js +0 -25
  283. package/dist/graph/mutate/move.hook.d.ts +0 -7
  284. package/dist/graph/mutate/move.hook.d.ts.map +0 -1
  285. package/dist/graph/mutate/move.hook.js +0 -49
  286. package/dist/graph/mutate/mutate.hook.d.ts +0 -17
  287. package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
  288. package/dist/graph/mutate/mutate.hook.js +0 -45
  289. package/dist/graph/query/children.hook.d.ts +0 -29
  290. package/dist/graph/query/children.hook.d.ts.map +0 -1
  291. package/dist/graph/query/children.hook.js +0 -64
  292. package/dist/graph/query/graph.hook.d.ts +0 -9
  293. package/dist/graph/query/graph.hook.d.ts.map +0 -1
  294. package/dist/graph/query/graph.hook.js +0 -5
  295. package/dist/graph/query/neighbors.hook.d.ts +0 -7
  296. package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
  297. package/dist/graph/query/neighbors.hook.js +0 -104
  298. package/dist/graph/query/node.hook.d.ts +0 -14
  299. package/dist/graph/query/node.hook.d.ts.map +0 -1
  300. package/dist/graph/query/node.hook.js +0 -43
  301. package/dist/graph/query/query.hook.d.ts +0 -14
  302. package/dist/graph/query/query.hook.d.ts.map +0 -1
  303. package/dist/graph/query/query.hook.js +0 -23
  304. package/dist/schema/bind-read.d.ts +0 -37
  305. package/dist/schema/bind-read.d.ts.map +0 -1
  306. package/dist/schema/bind-read.js +0 -205
  307. package/dist/schema/binding.d.ts +0 -21
  308. package/dist/schema/binding.d.ts.map +0 -1
  309. package/dist/schema/binding.js +0 -99
  310. package/dist/schema/function.hook.d.ts +0 -9
  311. package/dist/schema/function.hook.d.ts.map +0 -1
  312. package/dist/schema/function.hook.js +0 -40
  313. package/dist/schema/method.hook.d.ts +0 -14
  314. package/dist/schema/method.hook.d.ts.map +0 -1
  315. package/dist/schema/method.hook.js +0 -49
  316. package/dist/schema/tag.d.ts +0 -11
  317. package/dist/schema/tag.d.ts.map +0 -1
  318. package/dist/schema/tag.js +0 -11
  319. package/dist/schema/types.d.ts +0 -73
  320. package/dist/schema/types.d.ts.map +0 -1
  321. package/dist/schema/types.js +0 -1
  322. package/dist/schema/write.d.ts +0 -16
  323. package/dist/schema/write.d.ts.map +0 -1
  324. package/dist/schema/write.js +0 -56
  325. package/src/application/roles.hook.ts +0 -41
  326. package/src/graph/memory/base.ts +0 -50
  327. package/src/graph/memory/read/read.ts +0 -103
  328. package/src/graph/memory/scope.ts +0 -29
  329. package/src/graph/mutate/move.hook.ts +0 -70
  330. package/src/graph/mutate/mutate.hook.ts +0 -69
  331. package/src/graph/query/children.hook.ts +0 -136
  332. package/src/graph/query/graph.hook.ts +0 -13
  333. package/src/graph/query/neighbors.hook.ts +0 -159
  334. package/src/graph/query/node.hook.ts +0 -83
  335. package/src/graph/query/query.hook.ts +0 -42
  336. package/src/schema/bind-read.ts +0 -319
  337. package/src/schema/binding.ts +0 -146
  338. package/src/schema/function.hook.ts +0 -68
  339. package/src/schema/method.hook.ts +0 -103
  340. package/src/schema/tag.ts +0 -19
  341. package/src/schema/types.ts +0 -150
  342. package/src/schema/write.ts +0 -96
@@ -1,48 +1,21 @@
1
- import type { LiveResult } from '@astrale-os/kernel-client/store';
1
+ import type { Node, NodeId } from '@astrale-os/sdk/graph/node';
2
+ import type { NodePath } from '@astrale-os/sdk/graph/path';
3
+ import type { Key } from '@astrale-os/sdk/schema';
4
+ import type { ReadState } from '../graph/memory/read/envelope.js';
2
5
  import type { SerializedLocation } from './history.js';
3
- /**
4
- * The rich graph `Node`, derived from the memory's read envelope — kernel-client
5
- * does not re-export `Node` at its root yet (API §14 G8), so shell-react reads it
6
- * off `LiveResult` rather than taking a direct kernel-core dependency.
7
- */
8
- export type Node = NonNullable<LiveResult['node']>;
9
- export type NodeId = Node['id'];
10
- /** The live, id-anchored location a scope currently points at (API §8.1). */
6
+ export interface PointResult extends ReadState {
7
+ readonly node: Node | null;
8
+ }
9
+ /** One canonical location and its current caller-visible point projection. */
11
10
  export interface NavLocation {
12
- /** The anchor — survives rename/move. */
13
- readonly id: NodeId;
14
- /** LIVE projection of the node's current path (empty until first resolve). */
15
- readonly path: string;
16
- /** Live memory node — null while cold, or after the anchor stops resolving. */
11
+ readonly target: NodePath | null;
12
+ readonly id: NodeId | null;
17
13
  readonly node: Node | null;
18
- /** View function ref rendering it, when one is open. */
19
- readonly view?: string;
14
+ readonly view?: Key.View;
20
15
  readonly params: Readonly<Record<string, string>>;
21
- /** The anchor no longer resolves (deleted / masked). */
22
16
  readonly missing: boolean;
23
17
  }
24
- /** The idle location a scope with no current entry projects (inert / boot). */
25
18
  export declare const IDLE_LOCATION: NavLocation;
26
- /** Project a serialized entry + its live read into the public {@link NavLocation}. */
27
- export declare function buildLocation(entry: SerializedLocation | null, result: LiveResult | null, settled: boolean): NavLocation;
28
- /**
29
- * Whether a read has definitively settled — data present, a hard error, or a
30
- * completed empty fetch. Guards `missing` (and the missing policy) against the
31
- * one-render false-empty before a cold shape's first fetch is even in flight.
32
- */
33
- export declare function useSettled(result: LiveResult | null, key: string | null): boolean;
34
- /** The raw path of a live node (empty when cold). */
35
- export declare function pathOf(node: Node | null): string;
36
- /** Best-effort anchor id from a stored ref (`@<id>` → id, else the raw ref). */
37
- export declare function idHint(ref: string): string;
38
- /** Best-effort path from a stored ref (a `/…` ref is already a path). */
39
- export declare function pathHint(ref: string): string;
40
- /** The parent absolute path, or null at (or above) root. */
41
- export declare function parentPath(raw: string): string | null;
42
- /**
43
- * The inclusive, root-first path chain for an absolute path — the ancestry the
44
- * kernel tree encodes in the slug path (`/a/b/c` → `/`, `/a`, `/a/b`, `/a/b/c`).
45
- * The node itself is the last element, so breadcrumbs map the chain directly.
46
- */
47
- export declare function chainPaths(raw: string): string[];
19
+ export declare function buildLocation(entry: SerializedLocation | null, result: PointResult | null): NavLocation;
20
+ export type { Node, NodeId };
48
21
  //# sourceMappingURL=location.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/navigation/location.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAWjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEtD;;;;GAIG;AACH,MAAM,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;AAClD,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;AAE/B,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAID,+EAA+E;AAC/E,eAAO,MAAM,aAAa,EAAE,WAM3B,CAAA;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,GAAG,IAAI,EAChC,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,OAAO,EAAE,OAAO,GACf,WAAW,CAWb;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CASjF;AAID,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAEhD;AAED,gFAAgF;AAChF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAUhD"}
1
+ {"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/navigation/location.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAA;AAIjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEtD,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAC3B;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAID,eAAO,MAAM,aAAa,EAAE,WAM1B,CAAA;AAEF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,GAAG,IAAI,EAChC,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,WAAW,CAWb;AAOD,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA"}
@@ -1,88 +1,26 @@
1
- import { rawOf } from '@astrale-os/kernel-client/graph';
2
- /**
3
- * NavLocation projection (API §8.1) — the live, id-anchored location a scope
4
- * points at (live path, missing flag), its `buildLocation` assembly, the
5
- * `useSettled` guard against a one-render false-empty, and the framework-free
6
- * path math (parent/chain) the scope and hooks share.
7
- */
8
- import { useEffect, useRef } from 'react';
1
+ import { Path } from '@astrale-os/sdk/graph/path';
9
2
  const EMPTY_PARAMS = Object.freeze({});
10
- /** The idle location a scope with no current entry projects (inert / boot). */
11
- export const IDLE_LOCATION = {
12
- id: '',
13
- path: '',
3
+ export const IDLE_LOCATION = Object.freeze({
4
+ target: null,
5
+ id: null,
14
6
  node: null,
15
7
  params: EMPTY_PARAMS,
16
8
  missing: false,
17
- };
18
- /** Project a serialized entry + its live read into the public {@link NavLocation}. */
19
- export function buildLocation(entry, result, settled) {
9
+ });
10
+ export function buildLocation(entry, result) {
20
11
  if (entry === null)
21
12
  return IDLE_LOCATION;
22
13
  const node = result?.node ?? null;
23
14
  return {
24
- id: (node?.id ?? idHint(entry.node)),
25
- path: node ? pathOf(node) : pathHint(entry.node),
15
+ target: entry.node,
16
+ id: node?.id ?? idAnchor(entry.node),
26
17
  node,
27
- ...(entry.view !== undefined ? { view: entry.view } : {}),
28
- params: entry.params ?? IDLE_LOCATION.params,
29
- missing: settled && node === null,
18
+ ...(entry.view === undefined ? {} : { view: entry.view }),
19
+ params: entry.params ?? EMPTY_PARAMS,
20
+ missing: result !== null && !result.pending && node === null,
30
21
  };
31
22
  }
32
- /**
33
- * Whether a read has definitively settled — data present, a hard error, or a
34
- * completed empty fetch. Guards `missing` (and the missing policy) against the
35
- * one-render false-empty before a cold shape's first fetch is even in flight.
36
- */
37
- export function useSettled(result, key) {
38
- const sawPending = useRef(new Map());
39
- useEffect(() => {
40
- if (key !== null && result?.pending === true)
41
- sawPending.current.set(key, true);
42
- }, [key, result?.pending]);
43
- if (key === null || result === null)
44
- return false;
45
- if (result.node !== null)
46
- return true;
47
- if (result.error !== undefined)
48
- return true;
49
- return !result.pending && sawPending.current.get(key) === true;
50
- }
51
- // ── path math ──────────────────────────────────────────────────────────────
52
- /** The raw path of a live node (empty when cold). */
53
- export function pathOf(node) {
54
- return node ? rawOf(node.path) : '';
55
- }
56
- /** Best-effort anchor id from a stored ref (`@<id>` → id, else the raw ref). */
57
- export function idHint(ref) {
58
- return ref.startsWith('@') ? ref.slice(1) : ref;
59
- }
60
- /** Best-effort path from a stored ref (a `/…` ref is already a path). */
61
- export function pathHint(ref) {
62
- return ref.startsWith('/') ? ref : '';
63
- }
64
- /** The parent absolute path, or null at (or above) root. */
65
- export function parentPath(raw) {
66
- const norm = raw.replace(/\/+$/, '');
67
- if (norm === '' || norm === '/')
68
- return null;
69
- const idx = norm.lastIndexOf('/');
70
- return idx <= 0 ? '/' : norm.slice(0, idx);
71
- }
72
- /**
73
- * The inclusive, root-first path chain for an absolute path — the ancestry the
74
- * kernel tree encodes in the slug path (`/a/b/c` → `/`, `/a`, `/a/b`, `/a/b/c`).
75
- * The node itself is the last element, so breadcrumbs map the chain directly.
76
- */
77
- export function chainPaths(raw) {
78
- const norm = raw.replace(/\/+$/, '');
79
- if (norm === '' || norm === '/')
80
- return ['/'];
81
- const out = ['/'];
82
- let acc = '';
83
- for (const seg of norm.split('/').filter(Boolean)) {
84
- acc += `/${seg}`;
85
- out.push(acc);
86
- }
87
- return out;
23
+ function idAnchor(target) {
24
+ const path = Path.from(target);
25
+ return path.ast.anchor.kind === 'id' && path.ast.steps.length === 0 ? path.ast.anchor.id : null;
88
26
  }
@@ -1,64 +1,55 @@
1
- import type { GraphMemory, LiveResult, ShapeInput } from '@astrale-os/kernel-client/store';
1
+ import type { GraphStore } from '@astrale-os/kernel-client/store';
2
2
  import type { ReactElement, ReactNode } from 'react';
3
+ import { NodePath } from '@astrale-os/sdk/graph/path';
3
4
  import type { NavAdapter } from './adapters/adapter.js';
4
- import type { NavSnapshot } from './history.js';
5
- import type { NavLocation } from './location.js';
5
+ import type { NavSnapshot, SerializedLocation } from './history.js';
6
+ import type { NavLocation, PointResult } from './location.js';
6
7
  import type { NavTarget } from './snapshot.js';
7
8
  import { NavHistory } from './history.js';
8
- /** The imperative navigation surface (API §8.2). */
9
9
  export interface Navigate {
10
10
  (to: NavTarget, opts?: {
11
11
  replace?: boolean;
12
12
  }): void;
13
13
  back(): void;
14
14
  forward(): void;
15
- /** To the parent via `has_parent`; no-op at root or while the node is cold. */
16
- up(): void;
15
+ /** Unsupported until the caller supplies an explicit parent Edge Class. */
16
+ up(): never;
17
17
  readonly canBack: boolean;
18
18
  readonly canForward: boolean;
19
19
  }
20
- /** A mutable `Navigate` — the scope stamps `canBack`/`canForward` onto it live. */
21
20
  export interface MutableNavigate {
22
21
  (to: Parameters<Navigate>[0], opts?: Parameters<Navigate>[1]): void;
23
22
  back(): void;
24
23
  forward(): void;
25
- up(): void;
24
+ up(): never;
26
25
  canBack: boolean;
27
26
  canForward: boolean;
28
27
  }
29
- /** The nearest scope's shared handle (stable for the scope's lifetime). */
30
28
  export interface NavCtx {
31
29
  readonly history: NavHistory;
32
- readonly memory: GraphMemory;
30
+ readonly store: GraphStore;
33
31
  readonly adapter: NavAdapter;
34
32
  readonly navigate: MutableNavigate;
35
33
  }
36
34
  export declare const NavContext: import("react").Context<NavCtx | null>;
37
- /** The nearest scope, or throw — the door every public nav hook goes through. */
38
35
  export declare function useNavCtx(): NavCtx;
39
- /** The nearest scope or null (for `useAncestors`, usable outside a scope). */
40
36
  export declare function useOptionalNavCtx(): NavCtx | null;
41
- /** Re-render on any history change (no-op subscription when there is no scope). */
42
37
  export declare function useHistoryVersion(history: NavHistory | null): number;
43
- /**
44
- * Subscribe to one memory shape, tear-free. `shape` must be stable per read
45
- * (a string ref, or a builder memoized upstream); a null shape is idle (no I/O).
46
- */
47
- export declare function useMemoryShape(memory: GraphMemory, shape: ShapeInput | null): LiveResult | null;
48
- /** The missing-anchor policy — a fallback strategy or a caller-supplied resolver. */
49
- export type MissingPolicy = 'ancestor' | 'hold' | ((loc: NavLocation) => NavTarget | null);
38
+ /** Caller-scoped canonical point read through the provider's one GraphStore. */
39
+ export declare function useGraphPoint(target: NodePath | null): PointResult | null;
40
+ type MissingResolver = (location: NavLocation) => NavTarget | null;
41
+ export type MissingPolicy = 'hold' | MissingResolver;
50
42
  export interface NavScopeProps {
51
- /** Persistence seam. Default: a fresh {@link memoryAdapter} (captured once). */
52
43
  adapter?: NavAdapter;
53
- /** A saved snapshot — revalidated against the memory; dead entries dropped. */
54
44
  restore?: NavSnapshot;
55
- /** Seed target when neither `adapter.read()` nor `restore` yields one. */
56
45
  initial?: NavTarget;
57
- /** Fires per navigation with the new location + snapshot — persist here. */
58
- onChange?: (loc: NavLocation, snapshot: NavSnapshot) => void;
59
- /** What to do when the current anchor stops resolving. Default `'ancestor'`. */
46
+ onChange?: (location: NavLocation, snapshot: NavSnapshot) => void;
47
+ /** Default `hold`; parent fallback requires an explicit caller relationship. */
60
48
  missing?: MissingPolicy;
49
+ /** Closed codec admission applied before any history or adapter mutation. */
50
+ admit?: (location: SerializedLocation) => SerializedLocation | null;
61
51
  children: ReactNode;
62
52
  }
63
53
  export declare function NavScope(props: NavScopeProps): ReactElement;
54
+ export {};
64
55
  //# sourceMappingURL=scope.context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scope.context.d.ts","sourceRoot":"","sources":["../../src/navigation/scope.context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAqBpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9C,OAAO,EAAE,UAAU,EAAe,MAAM,cAAc,CAAA;AAItD,oDAAoD;AACpD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IACnD,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,+EAA+E;IAC/E,EAAE,IAAI,IAAI,CAAA;IACV,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACnE,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,EAAE,IAAI,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CACnC;AAED,eAAO,MAAM,UAAU,wCAAqC,CAAA;AAG5D,iFAAiF;AACjF,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAID,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,CAOpE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAU/F;AAED,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,SAAS,GAAG,IAAI,CAAC,CAAA;AAE1F,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAA;IAC5D,gFAAgF;IAChF,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CA2H3D"}
1
+ {"version":3,"file":"scope.context.d.ts","sourceRoot":"","sources":["../../src/navigation/scope.context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAsB,MAAM,iCAAiC,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAcrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAO9C,OAAO,EAAE,UAAU,EAAe,MAAM,cAAc,CAAA;AAItD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IACnD,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,2EAA2E;IAC3E,EAAE,IAAI,KAAK,CAAA;IACX,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACnE,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,EAAE,IAAI,KAAK,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CACnC;AAED,eAAO,MAAM,UAAU,wCAAqC,CAAA;AAG5D,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAID,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,CAOpE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CA6BzE;AAED,KAAK,eAAe,GAAG,CAAC,QAAQ,EAAE,WAAW,KAAK,SAAS,GAAG,IAAI,CAAA;AAClE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,eAAe,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAA;IACjE,gFAAgF;IAChF,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,kBAAkB,GAAG,IAAI,CAAA;IACnE,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAsH3D"}
@@ -1,178 +1,210 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * NavScope (API §8.2) — owns one history stack, wires it to an adapter, and seats
4
- * the scope context. Seeds from restore/adapter/initial, revalidates a restored
5
- * stack against the memory, mirrors navigations to/from the adapter, and runs the
6
- * `missing` policy when the current anchor stops resolving. Also the scope's shared
7
- * glue (`NavContext`, the `useSyncExternalStore` reads) and the imperative
8
- * `Navigate` surface. Scopes nest.
9
- */
2
+ import { NodePath } from '@astrale-os/sdk/graph/path';
3
+ import { Query } from '@astrale-os/sdk/query';
4
+ import { Key } from '@astrale-os/sdk/schema';
10
5
  import { createContext, startTransition, useCallback, useContext, useEffect, useMemo, useRef, useSyncExternalStore, } from 'react';
11
- import { useMemory } from '../graph/memory/scope.js';
6
+ import { UnsupportedFeatureError } from '../graph/memory/read/envelope.js';
7
+ import { useStoreResource } from '../graph/resource.js';
8
+ import { useGraphStore } from '../graph/store.js';
9
+ import { useShell } from '../session/shell.hook.js';
12
10
  import { memoryAdapter } from './adapters/memory.adapter.js';
13
11
  import { NavHistory, seedEntries } from './history.js';
14
- import { buildLocation, parentPath, pathHint, pathOf, useSettled } from './location.js';
12
+ import { buildLocation } from './location.js';
15
13
  import { revalidateAndPrune, serializeTarget } from './snapshot.js';
16
14
  export const NavContext = createContext(null);
17
15
  NavContext.displayName = 'AstraleNavContext';
18
- /** The nearest scope, or throw — the door every public nav hook goes through. */
19
16
  export function useNavCtx() {
20
17
  const ctx = useContext(NavContext);
21
18
  if (ctx === null)
22
19
  throw new Error('nav hooks must be used within a <NavScope>');
23
20
  return ctx;
24
21
  }
25
- /** The nearest scope or null (for `useAncestors`, usable outside a scope). */
26
22
  export function useOptionalNavCtx() {
27
23
  return useContext(NavContext);
28
24
  }
29
25
  const NOOP_UNSUB = () => undefined;
30
- /** Re-render on any history change (no-op subscription when there is no scope). */
31
26
  export function useHistoryVersion(history) {
32
- const subscribe = useCallback((cb) => (history !== null ? history.subscribe(cb) : NOOP_UNSUB), [history]);
33
- const getSnapshot = useCallback(() => (history !== null ? history.getVersion() : 0), [history]);
27
+ const subscribe = useCallback((listener) => (history === null ? NOOP_UNSUB : history.subscribe(listener)), [history]);
28
+ const getSnapshot = useCallback(() => (history === null ? 0 : history.getVersion()), [history]);
34
29
  return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
35
30
  }
36
- /**
37
- * Subscribe to one memory shape, tear-free. `shape` must be stable per read
38
- * (a string ref, or a builder memoized upstream); a null shape is idle (no I/O).
39
- */
40
- export function useMemoryShape(memory, shape) {
41
- const subscribe = useCallback((cb) => (shape !== null ? memory.subscribe(shape, cb) : NOOP_UNSUB), [memory, shape]);
42
- const getSnapshot = useCallback(() => (shape !== null ? memory.getSnapshot(shape) : null), [memory, shape]);
43
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
31
+ /** Caller-scoped canonical point read through the provider's one GraphStore. */
32
+ export function useGraphPoint(target) {
33
+ const query = useMemo(() => target === null
34
+ ? null
35
+ : Query.from({ kind: 'node', paths: [target], binding: 'navigation_target' }).select({
36
+ kind: 'graph',
37
+ }), [target]);
38
+ const project = useCallback((response) => {
39
+ const result = response.result;
40
+ if (result.kind !== 'graph' || result.selection.kind !== 'node')
41
+ return null;
42
+ const id = result.selection.ids[0];
43
+ return id === undefined ? null : (result.graph.nodes.find((node) => node.id === id) ?? null);
44
+ }, [query]);
45
+ const resource = useStoreResource(query, 1, project);
46
+ if (target === null)
47
+ return null;
48
+ return {
49
+ node: resource.data ?? null,
50
+ pending: resource.state === 'loading' || resource.state === 'refreshing',
51
+ error: resource.error,
52
+ live: false,
53
+ seq: 0,
54
+ refetch: resource.refresh,
55
+ };
44
56
  }
45
57
  export function NavScope(props) {
46
- const memory = useMemory();
47
- // Adapter + history are captured ONCE — an inline `adapter={memoryAdapter()}`
48
- // (or a re-passed `initial`) must never rebuild the scope's state.
58
+ const store = useGraphStore();
59
+ const shell = useShell();
49
60
  const adapterRef = useRef(null);
50
61
  if (adapterRef.current === null)
51
62
  adapterRef.current = props.adapter ?? memoryAdapter();
52
63
  const adapter = adapterRef.current;
64
+ if (adapter.kind === 'browser' && shell.hostCapabilities.navigation.history !== 'browser') {
65
+ throw new Error('Browser navigation is not granted to this Shell.');
66
+ }
67
+ const admitRef = useRef(props.admit);
68
+ admitRef.current = props.admit;
69
+ const admit = (location) => {
70
+ if (location === null)
71
+ return null;
72
+ const portable = admitLocation(location);
73
+ return admitRef.current?.(portable) ?? portable;
74
+ };
53
75
  const historyRef = useRef(null);
54
76
  if (historyRef.current === null) {
55
- const seed = seedEntries(adapter.read(), props.restore, props.initial !== undefined ? serializeTarget(props.initial) : null);
77
+ const seed = seedEntries(admit(adapter.read()), props.restore === undefined || props.restore.v !== 1
78
+ ? undefined
79
+ : {
80
+ entries: props.restore.entries.flatMap((entry) => {
81
+ const accepted = admit(entry);
82
+ return accepted === null ? [] : [accepted];
83
+ }),
84
+ cursor: props.restore.cursor,
85
+ }, props.initial === undefined ? null : admit(serializeTarget(props.initial)));
56
86
  historyRef.current = new NavHistory(seed.entries, seed.cursor);
57
87
  }
58
88
  const history = historyRef.current;
59
- // Latest-value refs so the stable navigate + effects read current inputs.
60
- const memoryRef = useRef(memory);
61
- memoryRef.current = memory;
62
89
  const onChangeRef = useRef(props.onChange);
63
90
  onChangeRef.current = props.onChange;
64
91
  const missingRef = useRef(props.missing);
65
92
  missingRef.current = props.missing;
93
+ const historyVersion = useHistoryVersion(history);
66
94
  const fireOnChange = useCallback(() => {
67
- const cb = onChangeRef.current;
68
- if (cb === undefined)
69
- return;
70
- const entry = history.current;
71
- const live = entry !== null ? memoryRef.current.peek(entry.node) : null;
72
- cb(buildLocation(entry, live, (live?.node ?? null) !== null), history.snapshot());
95
+ onChangeRef.current?.(buildLocation(history.current, null), history.snapshot());
73
96
  }, [history]);
74
- // The one stable navigate object; hooks re-stamp canBack/canForward onto it.
75
97
  const navigate = useMemo(() => {
76
98
  const commit = (changed, replace) => {
77
99
  if (!changed)
78
100
  return;
79
- const loc = history.current;
80
- if (loc !== null)
81
- adapter.write(loc, { replace });
101
+ const location = history.current;
102
+ if (location !== null)
103
+ adapter.write(location, { replace });
82
104
  fireOnChange();
83
105
  };
84
- const nav = ((to, opts) => {
85
- const loc = serializeTarget(to);
86
- const replace = opts?.replace ?? false;
87
- startTransition(() => commit(history.push(loc, replace), replace));
106
+ const nav = ((to, options) => {
107
+ const replace = options?.replace ?? false;
108
+ const location = admit(serializeTarget(to));
109
+ if (location === null)
110
+ throw new TypeError('Navigation target was rejected by its codec.');
111
+ startTransition(() => commit(history.push(location, replace), replace));
88
112
  });
89
113
  nav.back = () => startTransition(() => commit(history.back(), false));
90
114
  nav.forward = () => startTransition(() => commit(history.forward(), false));
91
115
  nav.up = () => {
92
- const entry = history.current;
93
- if (entry === null)
94
- return;
95
- const live = memoryRef.current.peek(entry.node);
96
- const raw = live?.node ? pathOf(live.node) : pathHint(entry.node);
97
- const parent = raw !== '' ? parentPath(raw) : null;
98
- if (parent !== null)
99
- nav(parent);
116
+ throw new UnsupportedFeatureError('navigation.up requires an explicit parent Edge Class');
100
117
  };
101
118
  nav.canBack = history.canBack;
102
119
  nav.canForward = history.canForward;
103
120
  return nav;
104
- }, [history, adapter, fireOnChange]);
105
- // Re-render the scope on every navigation so the missing watcher tracks the
106
- // current entry (consumers re-render through their own version subscription).
107
- const historyVersion = useHistoryVersion(history);
108
- // Mount: canonicalize a non-adapter seed into the adapter, then relay external
109
- // (browser/URL) changes back into the history.
121
+ }, [history, adapter, fireOnChange, historyVersion]);
110
122
  useEffect(() => {
111
- const seedLoc = history.current;
112
- if (seedLoc !== null && adapter.read() === null)
113
- adapter.write(seedLoc, { replace: true });
123
+ const seed = history.current;
124
+ if (seed !== null && adapter.read() === null)
125
+ adapter.write(seed, { replace: true });
114
126
  return adapter.subscribe(() => {
115
- const loc = adapter.read();
116
- if (loc === null)
127
+ const location = admit(adapter.read());
128
+ if (location === null)
117
129
  return;
118
130
  startTransition(() => {
119
- if (history.syncExternal(loc))
131
+ if (history.syncExternal(location))
120
132
  fireOnChange();
121
133
  });
122
134
  });
123
135
  }, [history, adapter, fireOnChange]);
124
- // Restore revalidation — once, against the shared memory.
125
- const revalidatedRef = useRef(false);
126
136
  useEffect(() => {
127
- if (revalidatedRef.current || props.restore === undefined)
137
+ if (props.restore === undefined)
128
138
  return;
129
- revalidatedRef.current = true;
130
- void revalidateAndPrune(history, memory);
131
- }, [memory, props.restore, history]);
132
- // Missing-anchor watcher: the current entry's live read drives the policy.
133
- const currentShape = history.current?.node ?? null;
134
- const currentResult = useMemoryShape(memory, currentShape);
135
- const settled = useSettled(currentResult, currentShape);
136
- const lastPathRef = useRef(null);
137
- const handledRef = useRef(null);
138
- useEffect(() => {
139
- const resolved = currentResult?.node ?? null;
140
- if (resolved !== null)
141
- lastPathRef.current = pathOf(resolved);
142
- }, [currentResult?.node]);
139
+ let current = true;
140
+ void revalidateAndPrune(history, store, shell).then((changed) => {
141
+ if (!current || !changed)
142
+ return;
143
+ const accepted = history.current;
144
+ if (accepted === null)
145
+ adapter.clear({ replace: true });
146
+ else
147
+ adapter.write(accepted, { replace: true });
148
+ fireOnChange();
149
+ });
150
+ return () => {
151
+ current = false;
152
+ };
153
+ }, [store, shell, history, adapter, props.restore, fireOnChange]);
154
+ const current = history.current;
155
+ const result = useGraphPoint(current?.node ?? null);
156
+ const handled = useRef(null);
143
157
  useEffect(() => {
144
- const entry = history.current;
145
- if (entry === null)
158
+ if (current === null || result === null || result.pending)
146
159
  return;
147
- if ((currentResult?.node ?? null) !== null) {
148
- handledRef.current = null;
160
+ if (result.node !== null) {
161
+ handled.current = null;
149
162
  return;
150
163
  }
151
- if (!settled || handledRef.current === entry.node)
164
+ if (handled.current === current.node)
152
165
  return;
153
- handledRef.current = entry.node;
154
- applyMissingPolicy(entry, missingRef.current ?? 'ancestor', {
155
- lastPath: lastPathRef.current,
156
- result: currentResult,
157
- navigate,
158
- });
159
- // historyVersion re-runs this when the current entry changes.
160
- }, [settled, currentResult, history, navigate, historyVersion]);
161
- const ctx = useMemo(() => ({ history, memory, adapter, navigate }), [history, memory, adapter, navigate]);
166
+ handled.current = current.node;
167
+ const policy = missingRef.current ?? 'hold';
168
+ if (typeof policy === 'function') {
169
+ const target = policy(buildLocation(current, result));
170
+ if (target !== null)
171
+ navigate(target, { replace: true });
172
+ }
173
+ }, [current, result, navigate, historyVersion]);
174
+ const ctx = useMemo(() => ({ history, store, adapter, navigate }), [history, store, adapter, navigate]);
162
175
  return _jsx(NavContext.Provider, { value: ctx, children: props.children });
163
176
  }
164
- function applyMissingPolicy(entry, policy, deps) {
165
- if (policy === 'hold')
166
- return;
167
- if (typeof policy === 'function') {
168
- const target = policy(buildLocation(entry, deps.result, true));
169
- if (target !== null)
170
- deps.navigate(target, { replace: true });
171
- return;
177
+ function admitLocation(location) {
178
+ if (location === null || typeof location !== 'object' || Array.isArray(location)) {
179
+ throw new TypeError('Navigation location is invalid.');
180
+ }
181
+ const node = NodePath(location.node);
182
+ let view;
183
+ if (location.view !== undefined) {
184
+ const key = Key(location.view);
185
+ if (!Key.ref(key).startsWith('view.'))
186
+ throw new TypeError('Navigation View key is invalid.');
187
+ view = key;
188
+ }
189
+ const params = {};
190
+ if (location.params !== undefined) {
191
+ if (location.params === null ||
192
+ typeof location.params !== 'object' ||
193
+ Array.isArray(location.params)) {
194
+ throw new TypeError('Navigation params are invalid.');
195
+ }
196
+ for (const [key, value] of Object.entries(location.params)) {
197
+ if (/token|credential|authorization|secret/i.test(key)) {
198
+ throw new TypeError(`Navigation param '${key}' is sensitive.`);
199
+ }
200
+ if (typeof value !== 'string')
201
+ throw new TypeError(`Navigation param '${key}' is invalid.`);
202
+ params[key] = value;
203
+ }
172
204
  }
173
- // 'ancestor': climb one level toward a resolvable ancestor (repeats per settle).
174
- const raw = deps.lastPath ?? pathHint(entry.node);
175
- const parent = raw !== '' ? parentPath(raw) : null;
176
- if (parent !== null)
177
- deps.navigate(parent, { replace: true });
205
+ return Object.freeze({
206
+ node,
207
+ ...(view === undefined ? {} : { view }),
208
+ ...(Object.keys(params).length === 0 ? {} : { params: Object.freeze(params) }),
209
+ });
178
210
  }
@@ -1,22 +1,17 @@
1
- import type { AnyBoundNode, NodeRefInput } from '@astrale-os/kernel-client';
2
- import type { PathLike } from '@astrale-os/kernel-client/graph';
3
- import type { GraphMemory } from '@astrale-os/kernel-client/store';
4
- import type { NavHistory } from './history.js';
5
- import type { SerializedLocation } from './history.js';
6
- import type { Node, NodeId } from './location.js';
7
- /** Everything `navigate()` / `Link` / `initial` accept (API §8.1). */
8
- export type NavTarget = NodeId | PathLike | Node | AnyBoundNode | {
9
- node: NodeId | PathLike;
10
- view?: NodeRefInput;
11
- params?: Record<string, string>;
1
+ import type { GraphStore } from '@astrale-os/kernel-client/store';
2
+ import type { Node } from '@astrale-os/sdk/graph/node';
3
+ import type { PathLike } from '@astrale-os/sdk/graph/path';
4
+ import type { Key } from '@astrale-os/sdk/schema';
5
+ import type { Shell } from '@astrale-os/shell';
6
+ import type { NavHistory, SerializedLocation } from './history.js';
7
+ /** Canonical navigation inputs; there is no implicit slash-tree or bare-id grammar. */
8
+ export type NavTarget = PathLike | Node | {
9
+ readonly node: PathLike | Node;
10
+ readonly view?: Key.View;
11
+ readonly params?: Record<string, string>;
12
12
  };
13
- /** Normalize any {@link NavTarget} to its stored, id-anchored serialization. */
13
+ /** Normalize every target to canonical astrale-node-path-v1 text. */
14
14
  export declare function serializeTarget(target: NavTarget): SerializedLocation;
15
- /**
16
- * Revalidate a restored stack against the memory and drop dead entries (API §8.2).
17
- * Each entry is point-read one-shot; a null/failed read is a dead anchor. The
18
- * cursor re-lands on the surviving current entry, else the nearest survivor
19
- * before it.
20
- */
21
- export declare function revalidateAndPrune(history: NavHistory, memory: GraphMemory): Promise<void>;
15
+ /** Drop restored entries that no longer resolve under the authenticated Graph capability. */
16
+ export declare function revalidateAndPrune(history: NavHistory, store: GraphStore, shell: Shell): Promise<boolean>;
22
17
  //# sourceMappingURL=snapshot.d.ts.map