@astrale-os/shell-react 0.2.10-beta.3 → 0.3.1

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 (115) hide show
  1. package/dist/application/apps/app-host.d.ts +5 -5
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +18 -39
  4. package/dist/application/apps/apps.hook.d.ts +4 -11
  5. package/dist/application/apps/apps.hook.d.ts.map +1 -1
  6. package/dist/application/apps/apps.hook.js +9 -49
  7. package/dist/application/apps/open-app.hook.d.ts +4 -7
  8. package/dist/application/apps/open-app.hook.d.ts.map +1 -1
  9. package/dist/application/apps/open-app.hook.js +2 -2
  10. package/dist/application/index.d.ts +1 -3
  11. package/dist/application/index.d.ts.map +1 -1
  12. package/dist/application/index.js +1 -2
  13. package/dist/application/spaces/space.hook.d.ts.map +1 -1
  14. package/dist/application/spaces/space.hook.js +4 -1
  15. package/dist/auth/act-as.context.d.ts +1 -1
  16. package/dist/auth/act-as.context.d.ts.map +1 -1
  17. package/dist/auth/auth.hook.d.ts +1 -1
  18. package/dist/auth/auth.hook.d.ts.map +1 -1
  19. package/dist/auth/can.hook.d.ts +2 -2
  20. package/dist/auth/can.hook.d.ts.map +1 -1
  21. package/dist/auth/self.hook.d.ts +1 -1
  22. package/dist/auth/self.hook.d.ts.map +1 -1
  23. package/dist/components/can.d.ts +2 -2
  24. package/dist/components/can.d.ts.map +1 -1
  25. package/dist/graph/call/call.hook.d.ts +2 -2
  26. package/dist/graph/call/call.hook.d.ts.map +1 -1
  27. package/dist/graph/call/stream.hook.d.ts +2 -2
  28. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  29. package/dist/graph/graph.context.d.ts +1 -1
  30. package/dist/graph/graph.context.d.ts.map +1 -1
  31. package/dist/graph/guards.error.d.ts +4 -4
  32. package/dist/graph/guards.error.d.ts.map +1 -1
  33. package/dist/graph/guards.error.js +4 -4
  34. package/dist/graph/query-definition.hook.d.ts +1 -2
  35. package/dist/graph/query-definition.hook.d.ts.map +1 -1
  36. package/dist/graph/query-definition.hook.js +4 -10
  37. package/dist/graph/resource.d.ts +1 -1
  38. package/dist/graph/resource.d.ts.map +1 -1
  39. package/dist/graph/store.d.ts +2 -2
  40. package/dist/graph/store.d.ts.map +1 -1
  41. package/dist/graph/store.js +1 -1
  42. package/dist/index.d.ts +5 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +1 -1
  45. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  46. package/dist/navigation/adapters/url.adapter.js +2 -5
  47. package/dist/navigation/codec.d.ts.map +1 -1
  48. package/dist/navigation/codec.js +1 -7
  49. package/dist/navigation/link.js +1 -1
  50. package/dist/navigation/scope.context.d.ts +1 -1
  51. package/dist/navigation/scope.context.d.ts.map +1 -1
  52. package/dist/navigation/scope.context.js +3 -6
  53. package/dist/navigation/snapshot.d.ts +1 -1
  54. package/dist/navigation/snapshot.d.ts.map +1 -1
  55. package/dist/navigation/snapshot.js +2 -8
  56. package/dist/navigation/view-key.d.ts +3 -0
  57. package/dist/navigation/view-key.d.ts.map +1 -0
  58. package/dist/navigation/view-key.js +8 -0
  59. package/dist/schema/action.hook.d.ts +11 -7
  60. package/dist/schema/action.hook.d.ts.map +1 -1
  61. package/dist/schema/action.hook.js +11 -6
  62. package/dist/schema/domain.hook.js +12 -13
  63. package/dist/schema/kernel.hook.d.ts +1 -1
  64. package/dist/schema/kernel.hook.d.ts.map +1 -1
  65. package/dist/schema/kernel.hook.js +1 -1
  66. package/dist/schema/mutation.hook.d.ts +2 -2
  67. package/dist/schema/mutation.hook.d.ts.map +1 -1
  68. package/dist/schema/mutation.hook.js +6 -5
  69. package/dist/schema/object.hook.d.ts +3 -6
  70. package/dist/schema/object.hook.d.ts.map +1 -1
  71. package/dist/schema/object.hook.js +4 -5
  72. package/dist/schema/relation.hook.d.ts +29 -19
  73. package/dist/schema/relation.hook.d.ts.map +1 -1
  74. package/dist/schema/relation.hook.js +45 -63
  75. package/dist/selection/live.d.ts.map +1 -1
  76. package/dist/selection/live.js +1 -2
  77. package/dist/session/session.context.d.ts +3 -4
  78. package/dist/session/session.context.d.ts.map +1 -1
  79. package/package.json +4 -14
  80. package/src/application/apps/app-host.tsx +22 -52
  81. package/src/application/apps/apps.hook.ts +14 -64
  82. package/src/application/apps/open-app.hook.ts +5 -10
  83. package/src/application/index.ts +2 -12
  84. package/src/application/spaces/space.hook.ts +6 -1
  85. package/src/auth/act-as.context.tsx +1 -1
  86. package/src/auth/auth.hook.ts +1 -1
  87. package/src/auth/can.hook.ts +3 -3
  88. package/src/auth/self.hook.ts +1 -1
  89. package/src/components/can.tsx +2 -2
  90. package/src/graph/call/call.hook.ts +2 -2
  91. package/src/graph/call/stream.hook.ts +2 -2
  92. package/src/graph/graph.context.ts +1 -1
  93. package/src/graph/guards.error.ts +4 -4
  94. package/src/graph/query-definition.hook.ts +13 -23
  95. package/src/graph/resource.ts +1 -1
  96. package/src/graph/store.ts +3 -3
  97. package/src/index.ts +3 -7
  98. package/src/navigation/adapters/url.adapter.ts +3 -4
  99. package/src/navigation/codec.ts +1 -7
  100. package/src/navigation/link.tsx +1 -1
  101. package/src/navigation/scope.context.tsx +5 -6
  102. package/src/navigation/snapshot.ts +4 -9
  103. package/src/navigation/view-key.ts +11 -0
  104. package/src/schema/action.hook.ts +45 -28
  105. package/src/schema/domain.hook.ts +9 -10
  106. package/src/schema/kernel.hook.ts +1 -1
  107. package/src/schema/mutation.hook.ts +13 -9
  108. package/src/schema/object.hook.ts +10 -18
  109. package/src/schema/relation.hook.ts +127 -145
  110. package/src/selection/live.ts +1 -2
  111. package/src/session/session.context.ts +3 -4
  112. package/dist/application/apps/domains.hook.d.ts +0 -7
  113. package/dist/application/apps/domains.hook.d.ts.map +0 -1
  114. package/dist/application/apps/domains.hook.js +0 -18
  115. package/src/application/apps/domains.hook.ts +0 -37
@@ -1,14 +1,11 @@
1
- import type { StoreQueryResponse } from '@astrale-os/kernel-client/store'
2
- import type {
3
- BoundInstanceOf,
4
- Definition,
5
- EdgeEndpointAcceptedDefinitionsOf,
6
- } from '@astrale-os/sdk/domain'
7
- import type { LinkedCountOf } from '@astrale-os/sdk/query'
1
+ import type { BoundNode } from '@astrale-os/sdk/client'
2
+ import type { StoreQueryResponse } from '@astrale-os/sdk/client/store'
3
+ import type { NodeId } from '@astrale-os/sdk/graph/node'
4
+ import type { ClassKey as ClassKeyValue, ClassRef, ResolvedClass } from '@astrale-os/sdk/schema'
8
5
 
9
- import { NodeId } from '@astrale-os/sdk/graph/node'
10
6
  import { Path } from '@astrale-os/sdk/graph/path'
11
7
  import { Query } from '@astrale-os/sdk/query'
8
+ import { ClassKey } from '@astrale-os/sdk/schema'
12
9
  import { useCallback, useMemo } from 'react'
13
10
 
14
11
  import type { GraphResource } from '../graph/resource.js'
@@ -16,42 +13,61 @@ import type { GraphResource } from '../graph/resource.js'
16
13
  import { useStoreResource } from '../graph/resource.js'
17
14
  import { bindingFor } from './domain.hook.js'
18
15
 
19
- type DefinitionCoordinates = Pick<
20
- Definition<'class' | 'interface'>,
21
- 'kind' | 'origin' | 'name' | 'key' | 'schemaRef' | 'definition'
22
- >
23
- type NodeDefinition = DefinitionCoordinates & { readonly family: 'node' }
24
- type EdgeDefinition = DefinitionCoordinates & { readonly family: 'edge' }
25
16
  type EndpointRole = 'source' | 'target'
26
17
  type RelationCardinality = '1' | '0..1' | '0..*' | '1..*'
27
18
  type RuntimeEndpoint = {
28
- readonly accepts: readonly {
29
- readonly origin: string
30
- readonly kind: 'class' | 'interface'
31
- readonly name: string
32
- }[]
19
+ readonly accepts: readonly ClassRef[]
33
20
  readonly outgoing?: RelationCardinality
34
21
  readonly incoming?: RelationCardinality
35
22
  }
23
+ type DefinitionOf<Relation> =
24
+ Relation extends ResolvedClass<
25
+ 'edge',
26
+ infer _Properties,
27
+ infer _Methods,
28
+ infer _StaticMethods,
29
+ infer _SelfProperties,
30
+ infer _SelfMethods,
31
+ infer _SelfStaticMethods,
32
+ infer Definition
33
+ >
34
+ ? Definition
35
+ : never
36
+ type EndpointsOf<Relation> =
37
+ DefinitionOf<Relation> extends {
38
+ readonly orientation: 'directed'
39
+ readonly endpoints: infer Endpoints
40
+ }
41
+ ? Endpoints
42
+ : never
36
43
  type Opposite<Role extends EndpointRole> = Role extends 'source' ? 'target' : 'source'
37
- type Accepted<
38
- Definition extends EdgeDefinition,
39
- Role extends EndpointRole,
40
- > = EdgeEndpointAcceptedDefinitionsOf<Definition, Opposite<Role>>
41
- type StartingDefinition<
42
- Relation extends EdgeDefinition,
43
- Role extends EndpointRole,
44
- > = EdgeEndpointAcceptedDefinitionsOf<Relation, Role> & NodeDefinition
45
- type RelatedDefinition<Relation extends EdgeDefinition, Role extends EndpointRole> = Accepted<
46
- Relation,
47
- Role
48
- > &
49
- NodeDefinition
50
- type EffectiveCardinality<
51
- Relation extends EdgeDefinition,
52
- Role extends EndpointRole,
53
- To extends RelatedDefinition<Relation, Role>,
54
- > = LinkedCountOf<Relation, Role, To>
44
+ type AcceptedAt<Relation, Role extends EndpointRole> = Role extends keyof EndpointsOf<Relation>
45
+ ? EndpointsOf<Relation>[Role] extends { readonly accepts: readonly (infer Accepted)[] }
46
+ ? Accepted
47
+ : never
48
+ : never
49
+ type DeclaredCardinality<Relation, Role extends EndpointRole> = Role extends 'source'
50
+ ? EndpointsOf<Relation> extends { readonly source: { readonly outgoing: infer Count } }
51
+ ? Extract<Count, RelationCardinality>
52
+ : RelationCardinality
53
+ : EndpointsOf<Relation> extends { readonly target: { readonly incoming: infer Count } }
54
+ ? Extract<Count, RelationCardinality>
55
+ : RelationCardinality
56
+ type CoversOpposite<Relation, Role extends EndpointRole, To extends ResolvedClass<'node'>> = [
57
+ AcceptedAt<Relation, Opposite<Role>>,
58
+ ] extends [To['ref']]
59
+ ? true
60
+ : false
61
+ type EffectiveCardinality<Relation, Role extends EndpointRole, To extends ResolvedClass<'node'>> =
62
+ DeclaredCardinality<Relation, Role> extends infer Count extends RelationCardinality
63
+ ? CoversOpposite<Relation, Role, To> extends true
64
+ ? Count
65
+ : Count extends '1'
66
+ ? '0..1'
67
+ : Count extends '1..*'
68
+ ? '0..*'
69
+ : Count
70
+ : RelationCardinality
55
71
 
56
72
  export interface RelationUnavailable {
57
73
  readonly kind: 'required-hidden-or-invalid'
@@ -68,59 +84,50 @@ export class RelationUnavailableError extends Error {
68
84
  }
69
85
  }
70
86
 
71
- export type RelationResource<T, C extends string> = C extends '1' | '0..1'
87
+ export type RelationResource<T, Cardinality extends RelationCardinality> = Cardinality extends
88
+ | '1'
89
+ | '0..1'
72
90
  ? GraphResource<T | null> & {
73
- readonly cardinality: C
91
+ readonly cardinality: Cardinality
74
92
  readonly unavailable?: RelationUnavailable
75
93
  require(): T
76
94
  }
77
95
  : GraphResource<readonly T[]> & {
78
- readonly cardinality: C
96
+ readonly cardinality: Cardinality
79
97
  readonly unavailable?: RelationUnavailable
80
98
  require(): readonly T[]
81
99
  }
82
100
 
83
101
  export interface RelationOptions<Role extends EndpointRole, To> {
84
102
  readonly from: Role
85
- /** Exact rich opposite-endpoint definition used to admit and brand returned nodes. */
86
103
  readonly to: To
87
104
  readonly page?: { readonly size: number }
88
105
  }
89
106
 
90
- /** Traverse one exact rich Edge definition with endpoint and cardinality inference. */
107
+ /** Traverse one directed resolved Edge Class and bind the selected opposite Nodes. */
91
108
  export function useRelation<
92
- Definition extends EdgeDefinition,
109
+ Relation extends ResolvedClass<'edge'>,
93
110
  Role extends EndpointRole,
94
- To extends RelatedDefinition<Definition, Role>,
111
+ To extends ResolvedClass<'node'>,
112
+ Source extends ResolvedClass<'node'>,
95
113
  >(
96
- definition: Definition,
97
- source: BoundInstanceOf<StartingDefinition<Definition, Role>> | null | undefined,
114
+ relation: Relation,
115
+ source: BoundNode<Source> | null | undefined,
98
116
  options: RelationOptions<Role, To>,
99
- ): RelationResource<BoundInstanceOf<To>, EffectiveCardinality<Definition, Role, To>> {
100
- const binding = bindingFor(definition)
101
- if (source !== null && source !== undefined) {
102
- admitSource(binding, definition, options.from, source)
103
- }
104
- admitRelatedDefinition(binding, definition, options.from, options.to)
105
- const path = source === null || source === undefined ? null : Path.id(NodeId(source.id))
117
+ ): RelationResource<BoundNode<To>, EffectiveCardinality<Relation, Role, To>> {
118
+ const binding = bindingFor(relation)
119
+ if (source !== null && source !== undefined) admitSource(binding, relation, options.from, source)
120
+ admitRelatedDefinition(binding, relation, options.from, options.to)
121
+ const path = source === null || source === undefined ? null : Path.id(source.id as NodeId)
106
122
  const query = useMemo(() => {
107
123
  if (path === null) return null
108
- const root = Query.from({ kind: 'node', paths: [path], binding: 'relation_source' })
109
- const admitted = root.filter({ satisfies: source!.$.definition.schemaRef })
110
- const expanded = admitted.expand({
111
- via: [definition.schemaRef],
124
+ const expanded = Query.from({ nodes: [path] }).expand({
125
+ via: [relation],
112
126
  direction: options.from === 'source' ? 'outgoing' : 'incoming',
113
127
  })
114
- return expanded
115
- .filter({ satisfies: options.to.schemaRef })
116
- .select({ kind: 'graph', binding: expanded.node })
117
- }, [definition, options.from, options.to, path?.raw, source])
118
- const cardinality: RelationCardinality = effectiveCardinality(
119
- binding,
120
- definition,
121
- options.from,
122
- options.to,
123
- )
128
+ return expanded.filter({ class: options.to }).select({ kind: 'graph', binding: expanded.node })
129
+ }, [relation, options.from, options.to, path?.raw])
130
+ const cardinality = effectiveCardinality(binding, relation, options.from, options.to)
124
131
  const project = useCallback(
125
132
  (response: StoreQueryResponse<NonNullable<typeof query>>) => {
126
133
  const result = response.result
@@ -134,30 +141,21 @@ export function useRelation<
134
141
  const byId = new Map(result.graph.nodes.map((node) => [node.id, node]))
135
142
  const values = result.selection.ids.flatMap((id) => {
136
143
  const node = byId.get(id)
137
- if (node === undefined) return []
138
- const bind = binding.$.bind as unknown as (
139
- expected: To,
140
- value: typeof node,
141
- ) => BoundInstanceOf<To>
142
- return [bind(options.to, node)]
144
+ return node === undefined ? [] : [binding.wrapNode(options.to, node)]
143
145
  })
144
146
  if (cardinality === '0..1') return values[0] ?? null
145
147
  if (cardinality === '1') return values[0]
146
148
  if (cardinality === '1..*' && values.length === 0) return undefined
147
149
  return Object.freeze(values)
148
150
  },
149
- [binding, cardinality, options.to, query],
151
+ [binding, cardinality, options.to],
150
152
  )
151
153
  const resource = useStoreResource(query, options.page?.size ?? 50, project)
152
154
  const unavailable =
153
- (cardinality === '1' &&
154
- resource.data === undefined &&
155
- resource.state !== 'idle' &&
156
- resource.state !== 'loading') ||
157
- (cardinality === '1..*' &&
158
- resource.data === undefined &&
159
- resource.state !== 'idle' &&
160
- resource.state !== 'loading')
155
+ (cardinality === '1' || cardinality === '1..*') &&
156
+ resource.data === undefined &&
157
+ resource.state !== 'idle' &&
158
+ resource.state !== 'loading'
161
159
  ? Object.freeze({ kind: 'required-hidden-or-invalid' as const, cardinality })
162
160
  : undefined
163
161
  const require = () => {
@@ -172,82 +170,66 @@ export function useRelation<
172
170
  cardinality,
173
171
  ...(unavailable === undefined ? {} : { unavailable }),
174
172
  require,
175
- }) as RelationResource<BoundInstanceOf<To>, EffectiveCardinality<Definition, Role, To>>
173
+ }) as RelationResource<BoundNode<To>, EffectiveCardinality<Relation, Role, To>>
176
174
  }
177
175
 
178
- function admitSource<Relation extends EdgeDefinition, Role extends EndpointRole>(
176
+ function admitSource(
179
177
  binding: ReturnType<typeof bindingFor>,
180
- relation: Relation,
181
- from: Role,
182
- source: BoundInstanceOf<StartingDefinition<Relation, Role>>,
178
+ relation: ResolvedClass<'edge'>,
179
+ from: EndpointRole,
180
+ source: { readonly id: NodeId; readonly class: ClassKeyValue },
183
181
  ): void {
184
- const accepted = edgeEndpoints(relation)[from].accepts
185
- const matches = accepted.some((ref) => {
186
- const candidate = binding.$.inspect(ref) as Definition<'class' | 'interface'>
187
- return source.$.definition.satisfies(candidate)
188
- })
182
+ const exact = binding.domain.definition(ClassKey.ref(ClassKey(source.class)))
183
+ const matches =
184
+ exact?.ref.kind === 'class' &&
185
+ exact.kind === 'node' &&
186
+ edgeEndpoints(relation)[from].accepts.some((ref) => {
187
+ const accepted = binding.domain.definition(ref)
188
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && exact.satisfies(accepted)
189
+ })
189
190
  if (!matches) throw new TypeError('Relation source does not satisfy the selected endpoint.')
190
191
  }
191
192
 
192
- function endpointCardinality(definition: EdgeDefinition, side: EndpointRole): RelationCardinality {
193
- const endpoint = edgeEndpoints(definition)[side]
194
- const cardinality = side === 'source' ? endpoint.outgoing : endpoint.incoming
195
- if (cardinality === undefined) {
196
- throw new TypeError(`Relation ${side} endpoint does not expose its traversal cardinality.`)
197
- }
198
- return cardinality
199
- }
200
-
201
- function effectiveCardinality<
202
- Relation extends EdgeDefinition,
203
- Role extends EndpointRole,
204
- To extends RelatedDefinition<Relation, Role>,
205
- >(
193
+ function admitRelatedDefinition(
206
194
  binding: ReturnType<typeof bindingFor>,
207
- relation: Relation,
208
- from: Role,
209
- to: To,
210
- ): EffectiveCardinality<Relation, Role, To> {
211
- const base = endpointCardinality(relation, from)
212
- if (base !== '1' && base !== '1..*') {
213
- return base as EffectiveCardinality<Relation, Role, To>
214
- }
215
- const opposite: EndpointRole = from === 'source' ? 'target' : 'source'
216
- const coversEndpoint = edgeEndpoints(relation)[opposite].accepts.every((ref) => {
217
- const candidate = binding.$.inspect(ref) as Definition<'class' | 'interface'>
218
- return candidate.satisfies(to)
195
+ relation: ResolvedClass<'edge'>,
196
+ from: EndpointRole,
197
+ to: ResolvedClass<'node'>,
198
+ ): void {
199
+ const opposite = from === 'source' ? 'target' : 'source'
200
+ const matches = edgeEndpoints(relation)[opposite].accepts.some((ref) => {
201
+ const accepted = binding.domain.definition(ref)
202
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && to.satisfies(accepted)
219
203
  })
220
- return (coversEndpoint ? base : base === '1' ? '0..1' : '0..*') as EffectiveCardinality<
221
- Relation,
222
- Role,
223
- To
224
- >
204
+ if (!matches) {
205
+ throw new TypeError('Relation target Class is not admitted by the opposite endpoint.')
206
+ }
225
207
  }
226
208
 
227
- function admitRelatedDefinition<
228
- Relation extends EdgeDefinition,
229
- Role extends EndpointRole,
230
- To extends RelatedDefinition<Relation, Role>,
231
- >(binding: ReturnType<typeof bindingFor>, relation: Relation, from: Role, to: To): void {
232
- const opposite: EndpointRole = from === 'source' ? 'target' : 'source'
233
- const accepted = edgeEndpoints(relation)[opposite].accepts
234
- const matches = accepted.some((ref) => {
235
- const candidate = binding.$.inspect(ref) as Definition<'class' | 'interface'>
236
- return to.satisfies(candidate)
209
+ function effectiveCardinality(
210
+ binding: ReturnType<typeof bindingFor>,
211
+ relation: ResolvedClass<'edge'>,
212
+ from: EndpointRole,
213
+ to: ResolvedClass<'node'>,
214
+ ): RelationCardinality {
215
+ const endpoint = edgeEndpoints(relation)[from]
216
+ const base = from === 'source' ? endpoint.outgoing : endpoint.incoming
217
+ if (base === undefined) throw new TypeError(`Relation ${from} cardinality is absent.`)
218
+ if (base !== '1' && base !== '1..*') return base
219
+ const opposite = from === 'source' ? 'target' : 'source'
220
+ const covers = edgeEndpoints(relation)[opposite].accepts.every((ref) => {
221
+ const accepted = binding.domain.definition(ref)
222
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && accepted.satisfies(to)
237
223
  })
238
- if (!matches)
239
- throw new TypeError('Relation target definition is not admitted by the opposite endpoint.')
224
+ return covers ? base : base === '1' ? '0..1' : '0..*'
240
225
  }
241
226
 
242
- function edgeEndpoints(relation: EdgeDefinition): Readonly<Record<EndpointRole, RuntimeEndpoint>> {
243
- const declaration = relation.definition as unknown as {
244
- readonly family?: unknown
245
- readonly endpoints?: Partial<Record<EndpointRole, RuntimeEndpoint>>
246
- }
247
- const source = declaration.endpoints?.source
248
- const target = declaration.endpoints?.target
249
- if (declaration.family !== 'edge' || source === undefined || target === undefined) {
250
- throw new TypeError('Relation definition does not expose admitted Edge endpoints.')
227
+ function edgeEndpoints(
228
+ relation: ResolvedClass<'edge'>,
229
+ ): Readonly<Record<EndpointRole, RuntimeEndpoint>> {
230
+ const definition = relation.definition
231
+ if (definition.orientation !== 'directed') {
232
+ throw new TypeError('useRelation currently requires a directed Edge Class.')
251
233
  }
252
- return Object.freeze({ source, target })
234
+ return definition.endpoints
253
235
  }
@@ -1,6 +1,5 @@
1
1
  import type { Node, NodeId } from '@astrale-os/sdk/graph/node'
2
2
 
3
- import { Path } from '@astrale-os/sdk/graph/path'
4
3
  import { useCallback, useEffect, useRef, useState } from 'react'
5
4
 
6
5
  import { useSessionKernel } from '../auth/session-kernel.js'
@@ -58,7 +57,7 @@ export function useResolvedNodes(orderedIds: readonly NodeId[]): ResolvedSelecti
58
57
  }
59
58
  setState({ key: currentKey, aliveIds: ids, nodes: [], pending: true, error: undefined })
60
59
  try {
61
- const values = await Promise.all(ids.map((nodeId) => graph.get(Path.id(nodeId))))
60
+ const values = await Promise.all(ids.map((nodeId) => graph.get(nodeId)))
62
61
  if (!alive.current || id !== generation.current) return
63
62
  const aliveIds: NodeId[] = []
64
63
  const nodes: Node[] = []
@@ -1,4 +1,4 @@
1
- import type { GraphStore } from '@astrale-os/kernel-client/store'
1
+ import type { GraphStore } from '@astrale-os/sdk/client/store'
2
2
  import type { KernelClient, Shell } from '@astrale-os/shell'
3
3
 
4
4
  /**
@@ -11,9 +11,8 @@ import { createContext } from 'react'
11
11
  import type { GraphStoreScope } from '../graph/store.js'
12
12
 
13
13
  /**
14
- * whoami's node type, derived from the auth surface so shell-react needs no
15
- * direct `@astrale-os/kernel-core` dependency (`Node` is not yet re-exported by
16
- * kernel-client — API §14 G8). Swap for the blessed re-export when it lands.
14
+ * whoami's node type, derived from the SDK auth surface so this package does
15
+ * not duplicate the canonical Client node projection.
17
16
  */
18
17
  export type SelfNode = Awaited<ReturnType<KernelClient['auth']['whoami']>>
19
18
 
@@ -1,7 +0,0 @@
1
- import type { DomainSearchResult } from '@astrale-os/shell';
2
- import type { ReadState } from '../../graph/memory/read/envelope.js';
3
- export interface DomainsResult extends ReadState {
4
- readonly domains: readonly DomainSearchResult[];
5
- }
6
- export declare function useInstalledDomains(): DomainsResult;
7
- //# sourceMappingURL=domains.hook.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"domains.hook.d.ts","sourceRoot":"","sources":["../../../src/application/apps/domains.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAI3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAQpE,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAChD;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CAoBnD"}
@@ -1,18 +0,0 @@
1
- import { useMemo } from 'react';
2
- import { useAsyncResource } from '../../graph/async.js';
3
- import { useShell } from '../../session/shell.hook.js';
4
- import { isOsPlaneAvailable } from '../user/user.store.js';
5
- const NO_DOMAINS = [];
6
- export function useInstalledDomains() {
7
- const shell = useShell();
8
- const available = isOsPlaneAvailable(shell);
9
- const result = useAsyncResource(available ? () => shell.apps.searchDomains() : null, NO_DOMAINS, [shell, available]);
10
- return useMemo(() => ({
11
- domains: result.data,
12
- pending: result.pending,
13
- error: result.error,
14
- live: false,
15
- seq: 0,
16
- refetch: result.refetch,
17
- }), [result]);
18
- }
@@ -1,37 +0,0 @@
1
- import type { DomainSearchResult } from '@astrale-os/shell'
2
-
3
- import { useMemo } from 'react'
4
-
5
- import type { ReadState } from '../../graph/memory/read/envelope.js'
6
-
7
- import { useAsyncResource } from '../../graph/async.js'
8
- import { useShell } from '../../session/shell.hook.js'
9
- import { isOsPlaneAvailable } from '../user/user.store.js'
10
-
11
- const NO_DOMAINS: readonly DomainSearchResult[] = []
12
-
13
- export interface DomainsResult extends ReadState {
14
- readonly domains: readonly DomainSearchResult[]
15
- }
16
-
17
- export function useInstalledDomains(): DomainsResult {
18
- const shell = useShell()
19
- const available = isOsPlaneAvailable(shell)
20
- const result = useAsyncResource<readonly DomainSearchResult[]>(
21
- available ? () => shell.apps.searchDomains() : null,
22
- NO_DOMAINS,
23
- [shell, available],
24
- )
25
-
26
- return useMemo(
27
- () => ({
28
- domains: result.data,
29
- pending: result.pending,
30
- error: result.error,
31
- live: false,
32
- seq: 0,
33
- refetch: result.refetch,
34
- }),
35
- [result],
36
- )
37
- }