@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
@@ -0,0 +1,46 @@
1
+ import type { BoundInstanceOf, Definition, EdgeEndpointAcceptedDefinitionsOf } from '@astrale-os/sdk/domain';
2
+ import type { LinkedCountOf } from '@astrale-os/sdk/query';
3
+ import type { GraphResource } from '../graph/resource.js';
4
+ type DefinitionCoordinates = Pick<Definition<'class' | 'interface'>, 'kind' | 'origin' | 'name' | 'key' | 'schemaRef' | 'definition'>;
5
+ type NodeDefinition = DefinitionCoordinates & {
6
+ readonly family: 'node';
7
+ };
8
+ type EdgeDefinition = DefinitionCoordinates & {
9
+ readonly family: 'edge';
10
+ };
11
+ type EndpointRole = 'source' | 'target';
12
+ type Opposite<Role extends EndpointRole> = Role extends 'source' ? 'target' : 'source';
13
+ type Accepted<Definition extends EdgeDefinition, Role extends EndpointRole> = EdgeEndpointAcceptedDefinitionsOf<Definition, Opposite<Role>>;
14
+ type StartingDefinition<Relation extends EdgeDefinition, Role extends EndpointRole> = EdgeEndpointAcceptedDefinitionsOf<Relation, Role> & NodeDefinition;
15
+ type RelatedDefinition<Relation extends EdgeDefinition, Role extends EndpointRole> = Accepted<Relation, Role> & NodeDefinition;
16
+ type EffectiveCardinality<Relation extends EdgeDefinition, Role extends EndpointRole, To extends RelatedDefinition<Relation, Role>> = LinkedCountOf<Relation, Role, To>;
17
+ export interface RelationUnavailable {
18
+ readonly kind: 'required-hidden-or-invalid';
19
+ readonly cardinality: '1' | '1..*';
20
+ }
21
+ export declare class RelationUnavailableError extends Error {
22
+ readonly unavailable: RelationUnavailable;
23
+ readonly code: 'SHELL_REACT_RELATION_UNAVAILABLE';
24
+ constructor(unavailable: RelationUnavailable);
25
+ }
26
+ export type RelationResource<T, C extends string> = C extends '1' | '0..1' ? GraphResource<T | null> & {
27
+ readonly cardinality: C;
28
+ readonly unavailable?: RelationUnavailable;
29
+ require(): T;
30
+ } : GraphResource<readonly T[]> & {
31
+ readonly cardinality: C;
32
+ readonly unavailable?: RelationUnavailable;
33
+ require(): readonly T[];
34
+ };
35
+ export interface RelationOptions<Role extends EndpointRole, To> {
36
+ readonly from: Role;
37
+ /** Exact rich opposite-endpoint definition used to admit and brand returned nodes. */
38
+ readonly to: To;
39
+ readonly page?: {
40
+ readonly size: number;
41
+ };
42
+ }
43
+ /** Traverse one exact rich Edge definition with endpoint and cardinality inference. */
44
+ export declare function useRelation<Definition extends EdgeDefinition, Role extends EndpointRole, To extends RelatedDefinition<Definition, Role>>(definition: Definition, source: BoundInstanceOf<StartingDefinition<Definition, Role>> | null | undefined, options: RelationOptions<Role, To>): RelationResource<BoundInstanceOf<To>, EffectiveCardinality<Definition, Role, To>>;
45
+ export {};
46
+ //# sourceMappingURL=relation.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation.hook.d.ts","sourceRoot":"","sources":["../../src/schema/relation.hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { NodeId } from '@astrale-os/sdk/graph/node';
2
+ import { Path } from '@astrale-os/sdk/graph/path';
3
+ import { Query } from '@astrale-os/sdk/query';
4
+ import { useCallback, useMemo } from 'react';
5
+ import { useStoreResource } from '../graph/resource.js';
6
+ import { bindingFor } from './domain.hook.js';
7
+ export class RelationUnavailableError extends Error {
8
+ unavailable;
9
+ code = 'SHELL_REACT_RELATION_UNAVAILABLE';
10
+ constructor(unavailable) {
11
+ super(`Required relation (${unavailable.cardinality}) is hidden or violates the installed schema.`);
12
+ this.unavailable = unavailable;
13
+ this.name = 'RelationUnavailableError';
14
+ }
15
+ }
16
+ /** Traverse one exact rich Edge definition with endpoint and cardinality inference. */
17
+ export function useRelation(definition, source, options) {
18
+ const binding = bindingFor(definition);
19
+ if (source !== null && source !== undefined) {
20
+ admitSource(binding, definition, options.from, source);
21
+ }
22
+ admitRelatedDefinition(binding, definition, options.from, options.to);
23
+ const path = source === null || source === undefined ? null : Path.id(NodeId(source.id));
24
+ const query = useMemo(() => {
25
+ if (path === null)
26
+ return null;
27
+ const root = Query.from({ kind: 'node', paths: [path], binding: 'relation_source' });
28
+ const admitted = root.filter({ satisfies: source.$.definition.schemaRef });
29
+ const expanded = admitted.expand({
30
+ via: [definition.schemaRef],
31
+ direction: options.from === 'source' ? 'outgoing' : 'incoming',
32
+ });
33
+ return expanded
34
+ .filter({ satisfies: options.to.schemaRef })
35
+ .select({ kind: 'graph', binding: expanded.node });
36
+ }, [definition, options.from, options.to, path?.raw, source]);
37
+ const cardinality = effectiveCardinality(binding, definition, options.from, options.to);
38
+ const project = useCallback((response) => {
39
+ const result = response.result;
40
+ if (result.kind !== 'graph' || result.selection.kind !== 'node') {
41
+ return cardinality === '0..1'
42
+ ? null
43
+ : cardinality === '0..*'
44
+ ? Object.freeze([])
45
+ : undefined;
46
+ }
47
+ const byId = new Map(result.graph.nodes.map((node) => [node.id, node]));
48
+ const values = result.selection.ids.flatMap((id) => {
49
+ const node = byId.get(id);
50
+ if (node === undefined)
51
+ return [];
52
+ const bind = binding.$.bind;
53
+ return [bind(options.to, node)];
54
+ });
55
+ if (cardinality === '0..1')
56
+ return values[0] ?? null;
57
+ if (cardinality === '1')
58
+ return values[0];
59
+ if (cardinality === '1..*' && values.length === 0)
60
+ return undefined;
61
+ return Object.freeze(values);
62
+ }, [binding, cardinality, options.to, query]);
63
+ const resource = useStoreResource(query, options.page?.size ?? 50, project);
64
+ const unavailable = (cardinality === '1' &&
65
+ resource.data === undefined &&
66
+ resource.state !== 'idle' &&
67
+ resource.state !== 'loading') ||
68
+ (cardinality === '1..*' &&
69
+ resource.data === undefined &&
70
+ resource.state !== 'idle' &&
71
+ resource.state !== 'loading')
72
+ ? Object.freeze({ kind: 'required-hidden-or-invalid', cardinality })
73
+ : undefined;
74
+ const require = () => {
75
+ if (unavailable !== undefined)
76
+ throw new RelationUnavailableError(unavailable);
77
+ if (resource.data === undefined || resource.data === null) {
78
+ throw new Error('Relation resource is not settled with an available value.');
79
+ }
80
+ return resource.data;
81
+ };
82
+ return Object.freeze({
83
+ ...resource,
84
+ cardinality,
85
+ ...(unavailable === undefined ? {} : { unavailable }),
86
+ require,
87
+ });
88
+ }
89
+ function admitSource(binding, relation, from, source) {
90
+ const accepted = edgeEndpoints(relation)[from].accepts;
91
+ const matches = accepted.some((ref) => {
92
+ const candidate = binding.$.inspect(ref);
93
+ return source.$.definition.satisfies(candidate);
94
+ });
95
+ if (!matches)
96
+ throw new TypeError('Relation source does not satisfy the selected endpoint.');
97
+ }
98
+ function endpointCardinality(definition, side) {
99
+ const endpoint = edgeEndpoints(definition)[side];
100
+ const cardinality = side === 'source' ? endpoint.outgoing : endpoint.incoming;
101
+ if (cardinality === undefined) {
102
+ throw new TypeError(`Relation ${side} endpoint does not expose its traversal cardinality.`);
103
+ }
104
+ return cardinality;
105
+ }
106
+ function effectiveCardinality(binding, relation, from, to) {
107
+ const base = endpointCardinality(relation, from);
108
+ if (base !== '1' && base !== '1..*') {
109
+ return base;
110
+ }
111
+ const opposite = from === 'source' ? 'target' : 'source';
112
+ const coversEndpoint = edgeEndpoints(relation)[opposite].accepts.every((ref) => {
113
+ const candidate = binding.$.inspect(ref);
114
+ return candidate.satisfies(to);
115
+ });
116
+ return (coversEndpoint ? base : base === '1' ? '0..1' : '0..*');
117
+ }
118
+ function admitRelatedDefinition(binding, relation, from, to) {
119
+ const opposite = from === 'source' ? 'target' : 'source';
120
+ const accepted = edgeEndpoints(relation)[opposite].accepts;
121
+ const matches = accepted.some((ref) => {
122
+ const candidate = binding.$.inspect(ref);
123
+ return to.satisfies(candidate);
124
+ });
125
+ if (!matches)
126
+ throw new TypeError('Relation target definition is not admitted by the opposite endpoint.');
127
+ }
128
+ function edgeEndpoints(relation) {
129
+ const declaration = relation.definition;
130
+ const source = declaration.endpoints?.source;
131
+ const target = declaration.endpoints?.target;
132
+ if (declaration.family !== 'edge' || source === undefined || target === undefined) {
133
+ throw new TypeError('Relation definition does not expose admitted Edge endpoints.');
134
+ }
135
+ return Object.freeze({ source, target });
136
+ }
@@ -1,21 +1,13 @@
1
- import type { GraphMemory } from '@astrale-os/kernel-client/store';
2
- /** A live memory node — the non-null projection of a point read. */
3
- export type SelectionNode = NonNullable<ReturnType<GraphMemory['getSnapshot']>['node']>;
4
- export type NodeId = SelectionNode['id'];
5
- /**
6
- * The in-scope graph memory, structurally narrowed. Reads the base memory the
7
- * provider seats in `GraphContext`, defensively so selection also works under a
8
- * bare/fake context (tests) or before one is mounted.
9
- */
10
- export declare function useMemory(): GraphMemory | null;
11
- export interface LiveSnapshot {
1
+ import type { Node, NodeId } from '@astrale-os/sdk/graph/node';
2
+ export type SelectionNode = Node;
3
+ export type { NodeId };
4
+ export interface ResolvedSelection {
12
5
  readonly aliveIds: readonly NodeId[];
13
6
  readonly nodes: readonly SelectionNode[];
7
+ readonly pending: boolean;
8
+ readonly error: unknown;
9
+ refetch(): Promise<void>;
14
10
  }
15
- /**
16
- * Subscribe to each id's node shape and project the surviving nodes. The result
17
- * keeps a stable reference across renders when membership and node identities
18
- * are unchanged (useSyncExternalStore contract).
19
- */
20
- export declare function useLiveNodes(orderedIds: readonly NodeId[], memory: GraphMemory | null): LiveSnapshot;
11
+ /** Resolve selected identities through the authenticated GraphApi; no fake live subscription. */
12
+ export declare function useResolvedNodes(orderedIds: readonly NodeId[]): ResolvedSelection;
21
13
  //# sourceMappingURL=live.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/selection/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA2B,MAAM,iCAAiC,CAAA;AAc3F,oEAAoE;AACpE,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AACvF,MAAM,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;AAyBxC;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,WAAW,GAAG,IAAI,CAO9C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;CACzC;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,YAAY,CA4Dd"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/selection/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAO9D,MAAM,MAAM,aAAa,GAAG,IAAI,CAAA;AAChC,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAUD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAgEjF"}
@@ -1,116 +1,69 @@
1
- /**
2
- * Selection liveness (API §9) — resolve the scope's ids to LIVE memory nodes, and
3
- * the node types the selection speaks. Each id is subscribed as an independent
4
- * point-read shape; an id drops ONLY once its shape has SETTLED to absence (the
5
- * fixed latch) — a cold shape whose point-read has not landed is kept alive with
6
- * no node, so a selection made from a children row is never self-cleared before
7
- * its fetch resolves. Degrades to no nodes (ids kept) when no memory is in scope.
8
- */
9
- import { useCallback, useContext, useRef, useSyncExternalStore } from 'react';
10
- import { GraphContext } from '../graph/graph.context.js';
11
- const LIVE_OPTS = { live: true };
12
- const EMPTY_NODES = [];
13
- const NOOP = () => { };
14
- /** Point-read shape addressing a node by its graph id. */
15
- function nodeShape(id) {
16
- return `@${id}`;
17
- }
18
- /**
19
- * A null-node id is a CONFIRMED absence (drop it) only when the shape settled
20
- * there: it was seen warm and is now gone (deletion), or a live subscription has
21
- * finished fetching and found nothing (mask/never-existed). A never-warm, not-
22
- * yet-fetched (cold/pending) shape is NOT absence — the id stays alive, no node.
23
- */
24
- function isConfirmedAbsent(snap, id, everWarm) {
25
- if (everWarm.has(id))
26
- return true;
27
- return snap.live === true && snap.pending === false;
28
- }
29
- /**
30
- * The in-scope graph memory, structurally narrowed. Reads the base memory the
31
- * provider seats in `GraphContext`, defensively so selection also works under a
32
- * bare/fake context (tests) or before one is mounted.
33
- */
34
- export function useMemory() {
35
- const ctx = useContext(GraphContext);
36
- return ctx !== null &&
37
- typeof ctx.subscribe === 'function' &&
38
- typeof ctx.getSnapshot === 'function'
39
- ? ctx
40
- : null;
41
- }
42
- function unchanged(prev, aliveIds, nodes) {
43
- // `aliveIds` and `nodes` can differ in length (a cold id is alive with no node
44
- // yet), so compare the two lists independently.
45
- if (prev.aliveIds.length !== aliveIds.length || prev.nodes.length !== nodes.length)
46
- return false;
47
- for (let i = 0; i < aliveIds.length; i += 1)
48
- if (prev.aliveIds[i] !== aliveIds[i])
49
- return false;
50
- for (let i = 0; i < nodes.length; i += 1)
51
- if (prev.nodes[i] !== nodes[i])
52
- return false;
53
- return true;
54
- }
55
- /**
56
- * Subscribe to each id's node shape and project the surviving nodes. The result
57
- * keeps a stable reference across renders when membership and node identities
58
- * are unchanged (useSyncExternalStore contract).
59
- */
60
- export function useLiveNodes(orderedIds, memory) {
61
- // Stands in for `orderedIds` in the callback deps (a fresh array each render).
62
- const idsKey = orderedIds.join(' ');
63
- const cache = useRef(null);
64
- // Ids whose shape has been seen warm at least once — a later null is a deletion
65
- // (confirmed absence), whereas a never-warm null is merely cold. Monotonic, so
66
- // re-reading getSnapshot within a render is idempotent (useSyncExternalStore-safe).
67
- const everWarm = useRef(new Set());
68
- const getSnapshot = useCallback(() => {
69
- let aliveIds;
70
- let nodes;
71
- if (memory === null) {
72
- // No liveness source: keep the ids, resolve no nodes.
73
- aliveIds = orderedIds;
74
- nodes = EMPTY_NODES;
75
- }
76
- else {
77
- const seen = everWarm.current;
78
- const a = [];
79
- const n = [];
80
- for (const id of orderedIds) {
81
- const snap = memory.getSnapshot(nodeShape(id), LIVE_OPTS);
82
- const node = snap.node;
83
- if (node !== null) {
84
- seen.add(id);
85
- a.push(id);
86
- n.push(node);
87
- }
88
- else if (!isConfirmedAbsent(snap, id, seen)) {
89
- // Cold / not-yet-fetched: keep the id alive, no node yet — never a
90
- // premature drop (the critical self-clear this guards against).
91
- a.push(id);
92
- }
93
- // else: settled absence (deleted/masked) → drops from ids and nodes.
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { useSessionKernel } from '../auth/session-kernel.js';
4
+ /** Resolve selected identities through the authenticated GraphApi; no fake live subscription. */
5
+ export function useResolvedNodes(orderedIds) {
6
+ const graph = useSessionKernel().graph;
7
+ const key = orderedIds.join('\u0000');
8
+ const idsRef = useRef(orderedIds);
9
+ idsRef.current = orderedIds;
10
+ const generation = useRef(0);
11
+ const alive = useRef(true);
12
+ const [state, setState] = useState({
13
+ key,
14
+ aliveIds: orderedIds,
15
+ nodes: [],
16
+ pending: orderedIds.length > 0,
17
+ error: undefined,
18
+ });
19
+ useEffect(() => {
20
+ alive.current = true;
21
+ return () => {
22
+ alive.current = false;
23
+ };
24
+ }, []);
25
+ const load = useCallback(async () => {
26
+ const ids = idsRef.current;
27
+ const currentKey = ids.join('\u0000');
28
+ const id = ++generation.current;
29
+ if (ids.length === 0) {
30
+ if (alive.current) {
31
+ setState({ key: currentKey, aliveIds: [], nodes: [], pending: false, error: undefined });
94
32
  }
95
- aliveIds = a;
96
- nodes = n;
33
+ return;
97
34
  }
98
- const prev = cache.current;
99
- if (prev !== null && prev.memory === memory && unchanged(prev.snap, aliveIds, nodes)) {
100
- return prev.snap;
35
+ setState({ key: currentKey, aliveIds: ids, nodes: [], pending: true, error: undefined });
36
+ try {
37
+ const values = await Promise.all(ids.map((nodeId) => graph.get(Path.id(nodeId))));
38
+ if (!alive.current || id !== generation.current)
39
+ return;
40
+ const aliveIds = [];
41
+ const nodes = [];
42
+ values.forEach((node, index) => {
43
+ if (node === null)
44
+ return;
45
+ aliveIds.push(ids[index]);
46
+ nodes.push(node);
47
+ });
48
+ setState({
49
+ key: currentKey,
50
+ aliveIds: Object.freeze(aliveIds),
51
+ nodes: Object.freeze(nodes),
52
+ pending: false,
53
+ error: undefined,
54
+ });
101
55
  }
102
- const snap = { aliveIds, nodes };
103
- cache.current = { memory, snap };
104
- return snap;
105
- }, [memory, idsKey]);
106
- const subscribe = useCallback((onStoreChange) => {
107
- if (memory === null || orderedIds.length === 0)
108
- return NOOP;
109
- const unsubs = orderedIds.map((id) => memory.subscribe(nodeShape(id), onStoreChange, LIVE_OPTS));
110
- return () => {
111
- for (const unsub of unsubs)
112
- unsub();
113
- };
114
- }, [memory, idsKey]);
115
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
56
+ catch (error) {
57
+ if (alive.current && id === generation.current) {
58
+ setState({ key: currentKey, aliveIds: ids, nodes: [], pending: false, error });
59
+ }
60
+ }
61
+ }, [graph]);
62
+ useEffect(() => {
63
+ void load();
64
+ }, [key, load]);
65
+ if (state.key !== key) {
66
+ return { aliveIds: orderedIds, nodes: [], pending: true, error: undefined, refetch: load };
67
+ }
68
+ return { ...state, refetch: load };
116
69
  }
@@ -6,7 +6,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
6
6
  * math stays caller-side (read `anchor`). Seats the selection context.
7
7
  */
8
8
  import { createContext, useCallback, useEffect, useMemo, useReducer, useRef } from 'react';
9
- import { useLiveNodes, useMemory } from './live.js';
9
+ import { useResolvedNodes } from './live.js';
10
10
  export const SelectionContext = createContext(null);
11
11
  SelectionContext.displayName = 'AstraleSelectionContext';
12
12
  function dedupe(ids) {
@@ -67,14 +67,15 @@ function initState(initial) {
67
67
  export function SelectionScope(props) {
68
68
  const { initial, onChange, children } = props;
69
69
  const [state, dispatch] = useReducer(reducer, initial, initState);
70
- const memory = useMemory();
71
- const { aliveIds, nodes } = useLiveNodes(state.ids, memory);
70
+ const { aliveIds, nodes, pending, error } = useResolvedNodes(state.ids);
72
71
  // Re-canonicalize stored state when liveness drops a node (or its anchor).
73
72
  useEffect(() => {
74
73
  const anchorDead = state.anchor !== null && !aliveIds.includes(state.anchor);
74
+ if (pending || error !== undefined)
75
+ return;
75
76
  if (!sameIds(state.ids, aliveIds) || anchorDead)
76
77
  dispatch({ t: 'prune', alive: aliveIds });
77
- }, [aliveIds, state.ids, state.anchor]);
78
+ }, [aliveIds, pending, error, state.ids, state.anchor]);
78
79
  // Report changes (explicit ops AND liveness drops), skipping the initial mount.
79
80
  const onChangeRef = useRef(onChange);
80
81
  onChangeRef.current = onChange;
@@ -1,19 +1,7 @@
1
- /**
2
- * The boot machine inputs (API §2): config identity (what triggers a reboot) and
3
- * whoami resolution (`createShell → init → whoami → OS-user preresolve`). Kept
4
- * pure of React so the provider's boot effect composes them.
5
- */
6
1
  import type { Shell, ShellConfig } from '@astrale-os/shell';
7
2
  import type { SelfNode } from '../session.context.js';
8
3
  export declare function isShellConfig(config: ShellConfig | Shell): config is ShellConfig;
9
- /**
10
- * Identity of a config — primitive fields only, so re-passing an inline `fetch`,
11
- * `adapter`, `getCredential`, or `parentWindow` each render does not reboot;
12
- * changing the kernel/credential does. A principal switch driven by a NEW
13
- * `getCredential` closure (rather than a new `credential` string) is therefore
14
- * NOT observed here — remount the provider (React `key`) to rebind it.
15
- */
4
+ /** Stable ownership key. Capability objects intentionally use reference identity. */
16
5
  export declare function configIdentity(config: ShellConfig | Shell): string;
17
- /** Resolve whoami when the bound kernel exposes an auth surface; else null. */
18
6
  export declare function resolveSelf(shell: Shell): Promise<SelfNode | null>;
19
7
  //# sourceMappingURL=boot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../../src/session/boot/boot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAErD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,MAAM,IAAI,WAAW,CAEhF;AAeD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,MAAM,CAYlE;AAED,+EAA+E;AAC/E,wBAAsB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAQxE"}
1
+ {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../../src/session/boot/boot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAErD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,MAAM,IAAI,WAAW,CAEhF;AAcD,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,MAAM,CAKlE;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAGxE"}
@@ -3,43 +3,25 @@ export function isShellConfig(config) {
3
3
  }
4
4
  let prebuiltCounter = 0;
5
5
  const prebuiltIds = new WeakMap();
6
- /** Stable id per prebuilt-Shell object reference (a new object reboots). */
7
6
  function prebuiltId(shell) {
8
7
  let id = prebuiltIds.get(shell);
9
8
  if (id === undefined) {
10
- prebuiltCounter += 1;
11
- id = `prebuilt#${prebuiltCounter}`;
9
+ id = `prebuilt#${++prebuiltCounter}`;
12
10
  prebuiltIds.set(shell, id);
13
11
  }
14
12
  return id;
15
13
  }
16
- /**
17
- * Identity of a config — primitive fields only, so re-passing an inline `fetch`,
18
- * `adapter`, `getCredential`, or `parentWindow` each render does not reboot;
19
- * changing the kernel/credential does. A principal switch driven by a NEW
20
- * `getCredential` closure (rather than a new `credential` string) is therefore
21
- * NOT observed here — remount the provider (React `key`) to rebind it.
22
- */
14
+ /** Stable ownership key. Capability objects intentionally use reference identity. */
23
15
  export function configIdentity(config) {
24
16
  if (!isShellConfig(config))
25
17
  return prebuiltId(config);
26
- if (config.mode === 'standalone') {
27
- return [
28
- 'standalone',
29
- config.kernelUrl,
30
- config.credential ?? '',
31
- config.mintIdentity ?? '',
32
- config.windowId ?? '',
33
- ].join('|');
34
- }
35
- return `sandboxed|${config.initTimeoutMs ?? ''}`;
18
+ if (config.mode === 'sandboxed')
19
+ return prebuiltId(config);
20
+ if (config.client !== undefined)
21
+ return `standalone-client|${prebuiltId(config.client)}`;
22
+ return `standalone-session|${prebuiltId(config.session)}`;
36
23
  }
37
- /** Resolve whoami when the bound kernel exposes an auth surface; else null. */
38
24
  export async function resolveSelf(shell) {
39
- const kernel = shell.kernel;
40
- const auth = kernel.auth;
41
- const whoami = auth?.whoami;
42
- if (typeof whoami !== 'function')
43
- return null;
44
- return whoami.call(auth);
25
+ const auth = shell.kernel.auth;
26
+ return typeof auth.whoami === 'function' ? auth.whoami() : null;
45
27
  }
@@ -5,4 +5,5 @@ export { useKernelClient } from './kernel-client.hook.js';
5
5
  export { useKernelInstance } from './kernel-instance.hook.js';
6
6
  export type { KernelInstance } from './kernel-instance.hook.js';
7
7
  export { useConnection } from './connection/connection.hook.js';
8
+ export type { ConnectionStatus, ConnectionValue } from './connection/connection.store.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAC/D,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA"}
@@ -1,9 +1,6 @@
1
+ /** Public, non-secret identity of the connected source Kernel. */
1
2
  export interface KernelInstance {
2
- /** Kernel envelope endpoint this shell is bound to. */
3
3
  readonly url: string;
4
- /** Current kernel credential. Never cache; read per request. */
5
- token(): string;
6
4
  }
7
- /** Low-level access for direct kernel-envelope calls and token exchange code. */
8
5
  export declare function useKernelInstance(): KernelInstance;
9
6
  //# sourceMappingURL=kernel-instance.hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kernel-instance.hook.d.ts","sourceRoot":"","sources":["../../src/session/kernel-instance.hook.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,KAAK,IAAI,MAAM,CAAA;CAChB;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,IAAI,cAAc,CASlD"}
1
+ {"version":3,"file":"kernel-instance.hook.d.ts","sourceRoot":"","sources":["../../src/session/kernel-instance.hook.ts"],"names":[],"mappings":"AAIA,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAGlD"}
@@ -1,10 +1,6 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useKernelClient } from './kernel-client.hook.js';
3
- /** Low-level access for direct kernel-envelope calls and token exchange code. */
4
3
  export function useKernelInstance() {
5
4
  const kernel = useKernelClient();
6
- return useMemo(() => ({
7
- url: kernel.url,
8
- token: () => kernel.authToken(),
9
- }), [kernel]);
5
+ return useMemo(() => Object.freeze({ url: kernel.url }), [kernel]);
10
6
  }
@@ -1,31 +1,17 @@
1
1
  import type { Shell, ShellConfig } from '@astrale-os/shell';
2
2
  import type { ReactElement, ReactNode } from 'react';
3
- /** Global error channel payload (API §2). */
4
3
  export type ShellError = {
5
- kind: 'refresh';
6
- shape: unknown;
7
- error: unknown;
8
- } | {
9
- kind: 'mutation';
10
- mutationId: string;
11
- error: unknown;
12
- } | {
13
- kind: 'connection';
14
- error: unknown;
4
+ readonly kind: 'connection';
5
+ readonly error: unknown;
15
6
  };
16
7
  export interface ShellProviderProps {
17
- /**
18
- * Shell config — or a prebuilt Shell (tests, storybook). Keyed by identity: a
19
- * config change disposes and reboots.
20
- */
21
- config: ShellConfig | Shell;
22
- /** Rendered until status === 'ready'. Default: null. */
23
- fallback?: ReactNode;
24
- /** Rendered when boot fails; `retry` re-runs init. Default: rethrow to the nearest boundary. */
25
- errorFallback?: (error: unknown, retry: () => void) => ReactNode;
26
- /** Global error channel: warm-read refresh failures, rolled-back mutations, watch drops. */
27
- onError?: (error: ShellError) => void;
28
- children: ReactNode;
8
+ /** A Shell configuration or an already-constructed Shell capability. */
9
+ readonly config: ShellConfig | Shell;
10
+ readonly fallback?: ReactNode;
11
+ readonly errorFallback?: (error: unknown, retry: () => void) => ReactNode;
12
+ readonly onError?: (error: ShellError) => void;
13
+ readonly children: ReactNode;
29
14
  }
15
+ /** Own and initialize exactly one Shell for a React subtree. */
30
16
  export declare function ShellProvider(props: ShellProviderProps): ReactElement | null;
31
17
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/session/provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AA0BpD,6CAA6C;AAC7C,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE1C,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,MAAM,EAAE,WAAW,GAAG,KAAK,CAAA;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,gGAAgG;IAChG,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAA;IAChE,4FAA4F;IAC5F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAmBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,GAAG,IAAI,CA0I5E"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/session/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAiBpD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjF,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAA;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAA;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,GAAG,IAAI,CAyG5E"}