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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) 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/astrale.d.ts +14 -0
  24. package/dist/components/astrale.d.ts.map +1 -0
  25. package/dist/components/astrale.js +12 -0
  26. package/dist/components/can.d.ts +2 -2
  27. package/dist/components/can.d.ts.map +1 -1
  28. package/dist/components/index.d.ts +2 -3
  29. package/dist/components/index.d.ts.map +1 -1
  30. package/dist/components/index.js +1 -2
  31. package/dist/graph/call/call.hook.d.ts +2 -2
  32. package/dist/graph/call/call.hook.d.ts.map +1 -1
  33. package/dist/graph/call/stream.hook.d.ts +2 -2
  34. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  35. package/dist/graph/graph.context.d.ts +1 -1
  36. package/dist/graph/graph.context.d.ts.map +1 -1
  37. package/dist/graph/guards.error.d.ts +4 -4
  38. package/dist/graph/guards.error.d.ts.map +1 -1
  39. package/dist/graph/guards.error.js +4 -4
  40. package/dist/graph/query-definition.hook.d.ts +1 -2
  41. package/dist/graph/query-definition.hook.d.ts.map +1 -1
  42. package/dist/graph/query-definition.hook.js +4 -10
  43. package/dist/graph/resource.d.ts +1 -1
  44. package/dist/graph/resource.d.ts.map +1 -1
  45. package/dist/graph/store.d.ts +2 -2
  46. package/dist/graph/store.d.ts.map +1 -1
  47. package/dist/graph/store.js +1 -1
  48. package/dist/index.d.ts +7 -7
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -2
  51. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  52. package/dist/navigation/adapters/url.adapter.js +2 -5
  53. package/dist/navigation/codec.d.ts.map +1 -1
  54. package/dist/navigation/codec.js +1 -7
  55. package/dist/navigation/link.js +1 -1
  56. package/dist/navigation/scope.context.d.ts +1 -1
  57. package/dist/navigation/scope.context.d.ts.map +1 -1
  58. package/dist/navigation/scope.context.js +3 -6
  59. package/dist/navigation/snapshot.d.ts +1 -1
  60. package/dist/navigation/snapshot.d.ts.map +1 -1
  61. package/dist/navigation/snapshot.js +2 -8
  62. package/dist/navigation/view-key.d.ts +3 -0
  63. package/dist/navigation/view-key.d.ts.map +1 -0
  64. package/dist/navigation/view-key.js +8 -0
  65. package/dist/schema/action.hook.d.ts +11 -7
  66. package/dist/schema/action.hook.d.ts.map +1 -1
  67. package/dist/schema/action.hook.js +11 -6
  68. package/dist/schema/domain.hook.js +12 -13
  69. package/dist/schema/kernel.hook.d.ts +1 -1
  70. package/dist/schema/kernel.hook.d.ts.map +1 -1
  71. package/dist/schema/kernel.hook.js +1 -1
  72. package/dist/schema/mutation.hook.d.ts +2 -2
  73. package/dist/schema/mutation.hook.d.ts.map +1 -1
  74. package/dist/schema/mutation.hook.js +6 -5
  75. package/dist/schema/object.hook.d.ts +3 -6
  76. package/dist/schema/object.hook.d.ts.map +1 -1
  77. package/dist/schema/object.hook.js +4 -5
  78. package/dist/schema/relation.hook.d.ts +29 -19
  79. package/dist/schema/relation.hook.d.ts.map +1 -1
  80. package/dist/schema/relation.hook.js +45 -63
  81. package/dist/selection/live.d.ts.map +1 -1
  82. package/dist/selection/live.js +1 -2
  83. package/dist/session/session.context.d.ts +3 -4
  84. package/dist/session/session.context.d.ts.map +1 -1
  85. package/package.json +6 -5
  86. package/src/application/apps/app-host.tsx +22 -52
  87. package/src/application/apps/apps.hook.ts +14 -64
  88. package/src/application/apps/open-app.hook.ts +5 -10
  89. package/src/application/index.ts +2 -12
  90. package/src/application/spaces/space.hook.ts +6 -1
  91. package/src/auth/act-as.context.tsx +1 -1
  92. package/src/auth/auth.hook.ts +1 -1
  93. package/src/auth/can.hook.ts +3 -3
  94. package/src/auth/self.hook.ts +1 -1
  95. package/src/components/astrale.tsx +40 -0
  96. package/src/components/can.tsx +2 -2
  97. package/src/components/index.ts +2 -3
  98. package/src/graph/call/call.hook.ts +2 -2
  99. package/src/graph/call/stream.hook.ts +2 -2
  100. package/src/graph/graph.context.ts +1 -1
  101. package/src/graph/guards.error.ts +4 -4
  102. package/src/graph/query-definition.hook.ts +13 -23
  103. package/src/graph/resource.ts +1 -1
  104. package/src/graph/store.ts +3 -3
  105. package/src/index.ts +5 -14
  106. package/src/navigation/adapters/url.adapter.ts +3 -4
  107. package/src/navigation/codec.ts +1 -7
  108. package/src/navigation/link.tsx +1 -1
  109. package/src/navigation/scope.context.tsx +5 -6
  110. package/src/navigation/snapshot.ts +4 -9
  111. package/src/navigation/view-key.ts +11 -0
  112. package/src/schema/action.hook.ts +45 -28
  113. package/src/schema/domain.hook.ts +9 -10
  114. package/src/schema/kernel.hook.ts +1 -1
  115. package/src/schema/mutation.hook.ts +13 -9
  116. package/src/schema/object.hook.ts +10 -18
  117. package/src/schema/relation.hook.ts +127 -145
  118. package/src/selection/live.ts +1 -2
  119. package/src/session/session.context.ts +3 -4
  120. package/dist/application/apps/domains.hook.d.ts +0 -7
  121. package/dist/application/apps/domains.hook.d.ts.map +0 -1
  122. package/dist/application/apps/domains.hook.js +0 -18
  123. package/dist/components/mount-domain-frontend.d.ts +0 -22
  124. package/dist/components/mount-domain-frontend.d.ts.map +0 -1
  125. package/dist/components/mount-domain-frontend.js +0 -85
  126. package/dist/components/view-app.d.ts +0 -16
  127. package/dist/components/view-app.d.ts.map +0 -1
  128. package/dist/components/view-app.js +0 -16
  129. package/src/application/apps/domains.hook.ts +0 -37
  130. package/src/components/mount-domain-frontend.tsx +0 -158
  131. package/src/components/view-app.tsx +0 -49
@@ -1,5 +1,7 @@
1
+ import type { PathLike } from '@astrale-os/sdk/graph/path'
1
2
  import type { NodeTarget, SpaceNode } from '@astrale-os/shell'
2
3
 
4
+ import { Path } from '@astrale-os/sdk/graph/path'
3
5
  /**
4
6
  * useSpace(ref) (API §12.2) — a single space by ref; `null`/`undefined` (or an
5
7
  * unavailable OS plane) is idle (§1.3). One-shot today (§12 flag).
@@ -11,7 +13,6 @@ import type { CurrentSpaceResult } from './current-space.hook.js'
11
13
  import { useAsyncResource } from '../../graph/async.js'
12
14
  import { isIdleInput } from '../../graph/memory/read/idle.js'
13
15
  import { useShell } from '../../session/shell.hook.js'
14
- import { targetKey } from '../apps/apps.hook.js'
15
16
  import { isOsPlaneAvailable } from '../user/user.store.js'
16
17
 
17
18
  export type SpaceResult = CurrentSpaceResult
@@ -38,3 +39,7 @@ export function useSpace(ref: NodeTarget | null | undefined): SpaceResult {
38
39
  [idle, res],
39
40
  )
40
41
  }
42
+
43
+ function targetKey(input: NodeTarget): string {
44
+ return typeof input === 'string' ? `text:${input}` : `path:${Path.from(input as PathLike).raw}`
45
+ }
@@ -1,4 +1,4 @@
1
- import type { Identity } from '@astrale-os/kernel-client/auth'
1
+ import type { Identity } from '@astrale-os/sdk/auth'
2
2
  import type { KernelClient } from '@astrale-os/shell'
3
3
  import type { ReactElement, ReactNode } from 'react'
4
4
 
@@ -1,4 +1,4 @@
1
- import type { AuthApi } from '@astrale-os/kernel-client/auth'
1
+ import type { AuthApi } from '@astrale-os/sdk/auth'
2
2
 
3
3
  import { useIdentityBinding } from './act-as.context.js'
4
4
 
@@ -1,6 +1,6 @@
1
1
  import type { NodeId } from '@astrale-os/sdk/graph/node'
2
2
  import type { PathLike } from '@astrale-os/sdk/graph/path'
3
- import type { schema } from '@astrale-os/sdk/schema'
3
+ import type { PolicyRef } from '@astrale-os/sdk/schema'
4
4
 
5
5
  import { Path } from '@astrale-os/sdk/graph/path'
6
6
  import { useEffect, useState } from 'react'
@@ -14,7 +14,7 @@ export type PolicyObject = NodeId | { readonly id: NodeId }
14
14
  * invoked callable remains the authorization enforcement point.
15
15
  */
16
16
  export function useCan(
17
- policy: PathLike | schema.PolicyRef | null | undefined,
17
+ policy: PathLike | PolicyRef | null | undefined,
18
18
  object: PolicyObject | null | undefined,
19
19
  ): boolean | undefined {
20
20
  const { kernel } = useIdentityBinding()
@@ -45,7 +45,7 @@ export function useCan(
45
45
  return decision
46
46
  }
47
47
 
48
- function policyPath(policy: PathLike | schema.PolicyRef | null | undefined) {
48
+ function policyPath(policy: PathLike | PolicyRef | null | undefined) {
49
49
  if (policy === null || policy === undefined) return null
50
50
  return policy instanceof Path || typeof policy === 'string'
51
51
  ? Path.from(policy).raw
@@ -1,4 +1,4 @@
1
- import type { Identity } from '@astrale-os/kernel-client/auth'
1
+ import type { Identity } from '@astrale-os/sdk/auth'
2
2
 
3
3
  import { useIdentityBinding } from './act-as.context.js'
4
4
 
@@ -0,0 +1,40 @@
1
+ import type { Shell, ShellConfig } from '@astrale-os/shell'
2
+ import type { ReactElement, ReactNode } from 'react'
3
+
4
+ import { Suspense } from 'react'
5
+
6
+ import type { ShellProviderProps } from '../session/provider.js'
7
+
8
+ import { ShellProvider } from '../session/provider.js'
9
+ import { ViewStage } from '../window/stage.js'
10
+ import { defaultViewError, defaultViewLoading, ViewErrorBoundary } from './boundaries.js'
11
+
12
+ const SANDBOXED_SHELL = Object.freeze({ mode: 'sandboxed' as const })
13
+
14
+ export interface AstraleProps {
15
+ /** Defaults to the child-side sandbox handshake; pass a Shell for an embedded host or test. */
16
+ readonly config?: ShellConfig | Shell
17
+ readonly fallback?: ReactNode
18
+ readonly errorFallback?: ShellProviderProps['errorFallback']
19
+ readonly onError?: (error: unknown) => void
20
+ readonly children: ReactNode
21
+ }
22
+
23
+ /** Complete Astrale runtime root without taking ownership of application routing. */
24
+ export function Astrale(props: AstraleProps): ReactElement {
25
+ const loading = props.fallback ?? defaultViewLoading()
26
+ const errorFallback = props.errorFallback ?? defaultViewError
27
+ return (
28
+ <ShellProvider
29
+ config={props.config ?? SANDBOXED_SHELL}
30
+ fallback={loading}
31
+ errorFallback={errorFallback}
32
+ onError={({ error }) => props.onError?.(error)}
33
+ >
34
+ <ViewErrorBoundary fallback={errorFallback} onError={props.onError}>
35
+ <Suspense fallback={loading}>{props.children}</Suspense>
36
+ </ViewErrorBoundary>
37
+ <ViewStage />
38
+ </ShellProvider>
39
+ )
40
+ }
@@ -1,5 +1,5 @@
1
1
  import type { PathLike } from '@astrale-os/sdk/graph/path'
2
- import type { schema } from '@astrale-os/sdk/schema'
2
+ import type { PolicyRef } from '@astrale-os/sdk/schema'
3
3
  import type { ReactElement, ReactNode } from 'react'
4
4
 
5
5
  import type { PolicyObject } from '../auth/can.hook.js'
@@ -7,7 +7,7 @@ import type { PolicyObject } from '../auth/can.hook.js'
7
7
  import { useCan } from '../auth/can.hook.js'
8
8
 
9
9
  export function Can(props: {
10
- readonly policy: PathLike | schema.PolicyRef
10
+ readonly policy: PathLike | PolicyRef
11
11
  readonly object: PolicyObject
12
12
  readonly children: ReactNode
13
13
  readonly fallback?: ReactNode
@@ -9,6 +9,5 @@ export {
9
9
  ViewBoundary,
10
10
  } from './boundaries.js'
11
11
  export type { ViewErrorBoundaryProps } from './boundaries.js'
12
- export { ViewApp } from './view-app.js'
13
- export { mountDomainFrontend } from './mount-domain-frontend.js'
14
- export type { MountedDomainFrontend, MountDomainFrontendOptions } from './mount-domain-frontend.js'
12
+ export { Astrale } from './astrale.js'
13
+ export type { AstraleProps } from './astrale.js'
@@ -1,5 +1,5 @@
1
- import type { Call } from '@astrale-os/kernel-client'
2
- import type { SessionRequestOptions } from '@astrale-os/kernel-client/session'
1
+ import type { Call } from '@astrale-os/sdk/client'
2
+ import type { SessionRequestOptions } from '@astrale-os/sdk/client/session'
3
3
  import type { Value } from '@astrale-os/sdk/value'
4
4
 
5
5
  import type { Action } from '../action.js'
@@ -1,5 +1,5 @@
1
- import type { Call } from '@astrale-os/kernel-client'
2
- import type { SessionRequestOptions } from '@astrale-os/kernel-client/session'
1
+ import type { Call } from '@astrale-os/sdk/client'
2
+ import type { SessionRequestOptions } from '@astrale-os/sdk/client/session'
3
3
  import type { Value } from '@astrale-os/sdk/value'
4
4
  import type { KernelClient } from '@astrale-os/shell'
5
5
 
@@ -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
 
3
3
  import { createContext } from 'react'
4
4
 
@@ -4,12 +4,12 @@ export {
4
4
  ResponseError,
5
5
  StaleRouteError,
6
6
  TransportError,
7
- } from '@astrale-os/kernel-client'
8
- export { NodeUnavailableError } from '@astrale-os/kernel-client/graph'
7
+ } from '@astrale-os/sdk/client'
8
+ export { NodeUnavailableError } from '@astrale-os/sdk/client'
9
9
  export { UnsupportedFeatureError } from './memory/read/envelope.js'
10
10
 
11
- import { ClientError } from '@astrale-os/kernel-client'
12
- import { NodeUnavailableError } from '@astrale-os/kernel-client/graph'
11
+ import { ClientError } from '@astrale-os/sdk/client'
12
+ import { NodeUnavailableError } from '@astrale-os/sdk/client'
13
13
 
14
14
  export function isClientError(error: unknown): error is ClientError {
15
15
  return error instanceof ClientError
@@ -1,18 +1,12 @@
1
- import type { GraphStore, StoreQueryResponse, StoreSnapshot } from '@astrale-os/kernel-client/store'
2
- import type {
3
- QueryAstExecutionOptions,
4
- QueryDefinition,
5
- QueryValueBinder,
6
- } from '@astrale-os/sdk/query'
7
- import type { QueryAST } from '@astrale-os/sdk/query'
8
- import type { DomainBinding } from '@astrale-os/shell'
1
+ import type { QueryPageRequest } from '@astrale-os/sdk/client'
2
+ import type { GraphStore, StoreQueryResponse, StoreSnapshot } from '@astrale-os/sdk/client/store'
3
+ import type { QueryAST, QueryDefinition } from '@astrale-os/sdk/query'
9
4
 
10
- import { bindQueries } from '@astrale-os/sdk/query'
5
+ import { executeQuery } from '@astrale-os/sdk/query'
11
6
  import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'
12
7
 
13
8
  import type { GraphResource, GraphResourceState } from './resource.js'
14
9
 
15
- import { useDynamicDomain } from '../schema/domain.hook.js'
16
10
  import { retainRefreshScheduler } from './resource.js'
17
11
  import { useGraphStore } from './store.js'
18
12
 
@@ -24,7 +18,7 @@ export interface QueryResourceOptions {
24
18
 
25
19
  interface TouchedShape {
26
20
  readonly ast: QueryAST
27
- readonly options: QueryAstExecutionOptions
21
+ readonly options: { readonly page: QueryPageRequest }
28
22
  }
29
23
 
30
24
  interface DefinitionSnapshot<Output> {
@@ -33,7 +27,7 @@ interface DefinitionSnapshot<Output> {
33
27
  readonly error?: unknown
34
28
  }
35
29
 
36
- class DefinitionObserver<Input, Output, Query extends QueryAST> {
30
+ class DefinitionObserver<Input, Output> {
37
31
  private readonly listeners = new Set<() => void>()
38
32
  private subscriptions: readonly (() => void)[] = Object.freeze([])
39
33
  private touched: readonly TouchedShape[] = Object.freeze([])
@@ -45,8 +39,7 @@ class DefinitionObserver<Input, Output, Query extends QueryAST> {
45
39
 
46
40
  constructor(
47
41
  private readonly store: GraphStore,
48
- private readonly binding: DomainBinding,
49
- private readonly definition: QueryDefinition<Input, Output, Query>,
42
+ private readonly definition: QueryDefinition<Input, Output>,
50
43
  private readonly input: Input,
51
44
  ) {}
52
45
 
@@ -82,14 +75,12 @@ class DefinitionObserver<Input, Output, Query extends QueryAST> {
82
75
  })
83
76
  const execute = async <Ast extends QueryAST>(
84
77
  ast: Ast,
85
- options: QueryAstExecutionOptions,
78
+ options: { readonly page: QueryPageRequest },
86
79
  ): Promise<StoreQueryResponse<Ast>> => {
87
80
  touched.push(Object.freeze({ ast, options }))
88
81
  return this.store.read(ast, { ...options, freshness })
89
82
  }
90
- const bind = this.binding.$.bind as unknown as QueryValueBinder
91
- const query = bindQueries(execute, { bind })
92
- const running = query(this.definition, this.input)
83
+ const running = executeQuery({ query: execute }, this.definition, this.input)
93
84
  .then((data) => {
94
85
  if (!this.started || generation !== this.generation) return
95
86
  this.touched = dedupeShapes(touched)
@@ -157,17 +148,16 @@ class DefinitionObserver<Input, Output, Query extends QueryAST> {
157
148
  }
158
149
 
159
150
  /** Execute one named SDK Query definition exclusively through the current GraphStore. */
160
- export function useQuery<Input, Output, Query extends QueryAST>(
161
- definition: QueryDefinition<Input, Output, Query> | null,
151
+ export function useQuery<Input, Output>(
152
+ definition: QueryDefinition<Input, Output> | null,
162
153
  input: Input,
163
154
  options: QueryResourceOptions = {},
164
155
  ): GraphResource<Output> {
165
156
  const store = useGraphStore()
166
- const binding = useDynamicDomain()
167
157
  const inputIdentity = stableIdentity(input)
168
158
  const observer = useMemo(
169
- () => (definition === null ? null : new DefinitionObserver(store, binding, definition, input)),
170
- [store, binding, definition, inputIdentity],
159
+ () => (definition === null ? null : new DefinitionObserver(store, definition, input)),
160
+ [store, definition, inputIdentity],
171
161
  )
172
162
  const idle = useMemo<DefinitionSnapshot<Output>>(() => Object.freeze({ state: 'idle' }), [])
173
163
  const subscribe = useCallback(
@@ -1,4 +1,4 @@
1
- import type { GraphStore, StoreQueryResponse, StoreSnapshot } from '@astrale-os/kernel-client/store'
1
+ import type { GraphStore, StoreQueryResponse, StoreSnapshot } from '@astrale-os/sdk/client/store'
2
2
  import type { QueryAST } from '@astrale-os/sdk/query'
3
3
 
4
4
  import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'
@@ -1,8 +1,8 @@
1
- import type { GraphApi } from '@astrale-os/kernel-client/graph'
2
- import type { GraphStore as GraphStoreValue } from '@astrale-os/kernel-client/store'
1
+ import type { GraphApi } from '@astrale-os/sdk/client'
2
+ import type { GraphStore as GraphStoreValue } from '@astrale-os/sdk/client/store'
3
3
  import type { Shell } from '@astrale-os/shell'
4
4
 
5
- import { GraphStore } from '@astrale-os/kernel-client/store'
5
+ import { GraphStore } from '@astrale-os/sdk/client/store'
6
6
  import { useContext } from 'react'
7
7
 
8
8
  import { GraphContext } from './graph.context.js'
package/src/index.ts CHANGED
@@ -166,16 +166,11 @@ export {
166
166
  defaultViewError,
167
167
  defaultViewLoading,
168
168
  GraphBoundary,
169
- mountDomainFrontend,
170
- ViewApp,
169
+ Astrale,
171
170
  ViewBoundary,
172
171
  ViewErrorBoundary,
173
172
  } from './components/index.js'
174
- export type {
175
- MountedDomainFrontend,
176
- MountDomainFrontendOptions,
177
- ViewErrorBoundaryProps,
178
- } from './components/index.js'
173
+ export type { AstraleProps, ViewErrorBoundaryProps } from './components/index.js'
179
174
 
180
175
  // Shell application conveniences.
181
176
  export {
@@ -183,7 +178,6 @@ export {
183
178
  AppLogo,
184
179
  useApps,
185
180
  useCurrentSpace,
186
- useInstalledDomains,
187
181
  useOpenApp,
188
182
  useSpace,
189
183
  useSpaces,
@@ -195,7 +189,6 @@ export type {
195
189
  AppLogoProps,
196
190
  AppsResult,
197
191
  CurrentSpaceResult,
198
- DomainsResult,
199
192
  SpaceResult,
200
193
  SpacesResult,
201
194
  } from './application/index.js'
@@ -205,16 +198,14 @@ export { NodeId } from '@astrale-os/sdk/graph/node'
205
198
  export { NodePath, Path } from '@astrale-os/sdk/graph/path'
206
199
  export type { Node } from '@astrale-os/sdk/graph/node'
207
200
  export type { PathLike } from '@astrale-os/sdk/graph/path'
208
- export type { AuthApi, Identity, PolicyDecisionInput } from '@astrale-os/kernel-client/auth'
209
- export type { DomainBinding, DomainInvokeOptions } from '@astrale-os/shell'
201
+ export type { AuthApi, Identity, PolicyDecisionInput } from '@astrale-os/sdk/auth'
202
+ export type { DomainBinding } from '@astrale-os/shell'
210
203
 
211
204
  // Shell contracts retained at the package root for custom full-app composition.
212
205
  export type {
213
- ApplicationNode,
214
- AppSession,
206
+ App,
215
207
  CloseResult,
216
208
  CredentialSnapshot,
217
- DomainSearchResult,
218
209
  HostCapabilities,
219
210
  IntentRegistry,
220
211
  KernelClient,
@@ -1,5 +1,4 @@
1
1
  import { NodePath } from '@astrale-os/sdk/graph/path'
2
- import { Key } from '@astrale-os/sdk/schema'
3
2
 
4
3
  /**
5
4
  * urlAdapter (API §8.1) — the History-API adapter: mirrors the location into the
@@ -9,6 +8,8 @@ import { Key } from '@astrale-os/sdk/schema'
9
8
  import type { SerializedLocation } from '../history.js'
10
9
  import type { NavAdapter } from './adapter.js'
11
10
 
11
+ import { viewKey } from '../view-key.js'
12
+
12
13
  const VIEW_KEY = 'astrale.view'
13
14
  const PARAM_PREFIX = 'astrale.param.'
14
15
 
@@ -55,9 +56,7 @@ export function urlAdapter(opts?: { param?: string }): NavAdapter {
55
56
  node = NodePath(rawNode)
56
57
  const rawView = sp.get(VIEW_KEY)
57
58
  if (rawView !== null) {
58
- const admitted = Key(rawView)
59
- if (!Key.ref(admitted).startsWith('view.')) throw new TypeError('Invalid View key.')
60
- view = admitted as Key.View
59
+ view = viewKey(rawView)
61
60
  }
62
61
  } catch {
63
62
  return null
@@ -2,7 +2,6 @@ import type { Key } from '@astrale-os/sdk/schema'
2
2
  import type { ReactElement, ReactNode } from 'react'
3
3
 
4
4
  import { Path } from '@astrale-os/sdk/graph/path'
5
- import { Key as admitKey } from '@astrale-os/sdk/schema'
6
5
  import { createElement } from 'react'
7
6
 
8
7
  import type { NavAdapter } from './adapters/adapter.js'
@@ -11,6 +10,7 @@ import type { NavSnapshot, SerializedLocation } from './history.js'
11
10
  import { NavScope } from './scope.context.js'
12
11
  import { useNavCtx } from './scope.context.js'
13
12
  import { useHistoryVersion } from './scope.context.js'
13
+ import { viewKey } from './view-key.js'
14
14
 
15
15
  export interface NavigationParam<Value> {
16
16
  encode(value: Value): string
@@ -182,9 +182,3 @@ export function useNavigation<Routes extends NavigationRoutes>(
182
182
 
183
183
  export type NavigationTarget<Definition> =
184
184
  Definition extends NavigationDefinition<infer Routes> ? RouteTarget<Routes> : never
185
-
186
- function viewKey(input: string): Key.View {
187
- const key = admitKey(input)
188
- if (!admitKey.ref(key).startsWith('view.')) throw new TypeError(`Invalid View key '${input}'.`)
189
- return key as Key.View
190
- }
@@ -50,7 +50,7 @@ export function Link(props: LinkProps): ReactElement {
50
50
  const nodeRef = target.node
51
51
 
52
52
  const preload = useCallback(() => {
53
- const query = Query.from({ kind: 'node', paths: [nodeRef] }).select({ kind: 'graph' })
53
+ const query = Query.from({ nodes: [nodeRef] }).select({ kind: 'graph' })
54
54
  void ctx.store.preload(query, { page: { size: 1 } }).catch(() => {})
55
55
  }, [ctx.store, nodeRef])
56
56
 
@@ -1,9 +1,9 @@
1
- import type { GraphStore, StoreQueryResponse } from '@astrale-os/kernel-client/store'
1
+ import type { GraphStore, StoreQueryResponse } from '@astrale-os/sdk/client/store'
2
+ import type { Key } from '@astrale-os/sdk/schema'
2
3
  import type { ReactElement, ReactNode } from 'react'
3
4
 
4
5
  import { NodePath } from '@astrale-os/sdk/graph/path'
5
6
  import { Query } from '@astrale-os/sdk/query'
6
- import { Key } from '@astrale-os/sdk/schema'
7
7
  import {
8
8
  createContext,
9
9
  startTransition,
@@ -28,6 +28,7 @@ import { memoryAdapter } from './adapters/memory.adapter.js'
28
28
  import { NavHistory, seedEntries } from './history.js'
29
29
  import { buildLocation } from './location.js'
30
30
  import { revalidateAndPrune, serializeTarget } from './snapshot.js'
31
+ import { viewKey } from './view-key.js'
31
32
 
32
33
  export interface Navigate {
33
34
  (to: NavTarget, opts?: { replace?: boolean }): void
@@ -85,7 +86,7 @@ export function useGraphPoint(target: NodePath | null): PointResult | null {
85
86
  () =>
86
87
  target === null
87
88
  ? null
88
- : Query.from({ kind: 'node', paths: [target], binding: 'navigation_target' }).select({
89
+ : Query.from({ nodes: [target], binding: 'navigation_target' }).select({
89
90
  kind: 'graph',
90
91
  }),
91
92
  [target],
@@ -253,9 +254,7 @@ function admitLocation(location: SerializedLocation): SerializedLocation {
253
254
  const node = NodePath(location.node)
254
255
  let view: Key.View | undefined
255
256
  if (location.view !== undefined) {
256
- const key = Key(location.view)
257
- if (!Key.ref(key).startsWith('view.')) throw new TypeError('Navigation View key is invalid.')
258
- view = key as Key.View
257
+ view = viewKey(location.view)
259
258
  }
260
259
  const params: Record<string, string> = {}
261
260
  if (location.params !== undefined) {
@@ -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 { Node } from '@astrale-os/sdk/graph/node'
3
3
  import type { NodePath, PathLike } from '@astrale-os/sdk/graph/path'
4
4
  import type { Key } from '@astrale-os/sdk/schema'
@@ -6,10 +6,11 @@ import type { Shell } from '@astrale-os/shell'
6
6
 
7
7
  import { Path } from '@astrale-os/sdk/graph/path'
8
8
  import { Query } from '@astrale-os/sdk/query'
9
- import { Key as admitKey } from '@astrale-os/sdk/schema'
10
9
 
11
10
  import type { NavHistory, SerializedLocation } from './history.js'
12
11
 
12
+ import { viewKey } from './view-key.js'
13
+
13
14
  /** Canonical navigation inputs; there is no implicit slash-tree or bare-id grammar. */
14
15
  export type NavTarget =
15
16
  | PathLike
@@ -44,12 +45,6 @@ export function serializeTarget(target: NavTarget): SerializedLocation {
44
45
  }
45
46
  }
46
47
 
47
- function viewKey(input: string): Key.View {
48
- const key = admitKey(input)
49
- if (!admitKey.ref(key).startsWith('view.')) throw new TypeError(`Invalid View key '${input}'.`)
50
- return key as Key.View
51
- }
52
-
53
48
  /** Drop restored entries that no longer resolve under the authenticated Graph capability. */
54
49
  export async function revalidateAndPrune(
55
50
  history: NavHistory,
@@ -81,7 +76,7 @@ async function resolves(
81
76
  entry: SerializedLocation,
82
77
  ): Promise<boolean> {
83
78
  try {
84
- const query = Query.from({ kind: 'node', paths: [entry.node] }).select({ kind: 'graph' })
79
+ const query = Query.from({ nodes: [entry.node] }).select({ kind: 'graph' })
85
80
  const response = await store.read(query, { page: { size: 1 } })
86
81
  if (
87
82
  response.result.kind !== 'graph' ||
@@ -0,0 +1,11 @@
1
+ import type { Key } from '@astrale-os/sdk/schema'
2
+
3
+ import { Key as admitKey } from '@astrale-os/sdk/schema'
4
+
5
+ export function viewKey(input: string): Key.View {
6
+ const key = admitKey(input)
7
+ if (!key.slice(key.indexOf(':') + 1).startsWith('view.')) {
8
+ throw new TypeError(`Invalid View key '${input}'.`)
9
+ }
10
+ return key as Key.View
11
+ }
@@ -1,25 +1,33 @@
1
- import type {
2
- InputOf,
3
- InstanceMethod,
4
- OutputOf,
5
- ReceiverOf,
6
- RemoteCallableOf,
7
- } from '@astrale-os/sdk/domain'
1
+ import type { BoundNodeFor } from '@astrale-os/sdk/client'
2
+ import type { SessionRequestOptions } from '@astrale-os/sdk/client/session'
8
3
  import type { NodeId } from '@astrale-os/sdk/graph/node'
9
4
  import type { QueryAST } from '@astrale-os/sdk/query'
10
- import type { schema } from '@astrale-os/sdk/schema'
11
- import type { DomainInvokeOptions } from '@astrale-os/shell'
12
-
5
+ import type {
6
+ CallableInputOf,
7
+ CallableResultOf,
8
+ MethodOwnerKeyOf,
9
+ MethodInheritance,
10
+ ResolvedFunction,
11
+ ResolvedMethod,
12
+ } from '@astrale-os/sdk/schema'
13
+
14
+ import { reference } from '@astrale-os/sdk/client/session'
13
15
  import { Path } from '@astrale-os/sdk/graph/path'
14
16
  import { useCallback, useMemo, useRef } from 'react'
15
17
 
16
18
  import type { Action as AsyncAction } from '../graph/action.js'
17
19
 
20
+ import { useSessionKernel } from '../auth/session-kernel.js'
18
21
  import { useAction as useAsyncAction } from '../graph/action.js'
19
22
  import { useGraphStore } from '../graph/store.js'
20
23
  import { bindingFor } from './domain.hook.js'
21
24
 
22
- type Callable = RemoteCallableOf<schema.DomainSchema> | InstanceMethod
25
+ type ExecutableInheritance = Exclude<MethodInheritance, 'abstract'>
26
+ type InstanceMethod = ResolvedMethod<unknown, unknown, false, ExecutableInheritance>
27
+ type StaticMethod = ResolvedMethod<unknown, unknown, true, ExecutableInheritance>
28
+ type Callable = ResolvedFunction | InstanceMethod | StaticMethod
29
+ type Receiver = { readonly id: NodeId }
30
+ type MethodReceiver<C extends InstanceMethod> = BoundNodeFor<MethodOwnerKeyOf<C>>
23
31
 
24
32
  const QUERY_REFRESH = Symbol('shell-react.query-refresh')
25
33
 
@@ -59,14 +67,14 @@ export type ActionRefresh =
59
67
  readonly queries: readonly QueryRefresh[]
60
68
  }
61
69
 
62
- export interface ActionOptions extends DomainInvokeOptions {
70
+ export interface ActionOptions extends SessionRequestOptions {
63
71
  readonly refresh?: ActionRefresh
64
72
  readonly onError?: (error: unknown) => void
65
73
  }
66
74
 
67
75
  type ActionArgs<C extends Callable> = C extends InstanceMethod
68
- ? [receiver: ReceiverOf<C>, input: InputOf<C>]
69
- : [input: InputOf<C>]
76
+ ? [receiver: MethodReceiver<C>, input: CallableInputOf<C>]
77
+ : [input: CallableInputOf<C>]
70
78
 
71
79
  export interface DomainAction<Args extends unknown[], Result> {
72
80
  run(...args: Args): Promise<Result>
@@ -80,8 +88,9 @@ export interface DomainAction<Args extends unknown[], Result> {
80
88
  export function useAction<C extends Callable>(
81
89
  callable: C,
82
90
  options: ActionOptions = {},
83
- ): DomainAction<ActionArgs<C>, OutputOf<C>> {
91
+ ): DomainAction<ActionArgs<C>, CallableResultOf<C>> {
84
92
  const binding = bindingFor(callable)
93
+ const kernel = useSessionKernel()
85
94
  const store = useGraphStore()
86
95
  const callableRef = useRef(callable)
87
96
  callableRef.current = callable
@@ -91,18 +100,22 @@ export function useAction<C extends Callable>(
91
100
  optionsRef.current = options
92
101
 
93
102
  const invoke = useCallback(
94
- async (...args: ActionArgs<C>): Promise<OutputOf<C>> => {
103
+ async (...args: ActionArgs<C>): Promise<CallableResultOf<C>> => {
95
104
  const current = callableRef.current
96
105
  const policy = optionsRef.current
97
106
  const { refresh: _refresh, onError: _onError, ...request } = policy
98
107
  try {
99
- const invokeExact = bindingRef.current.$.invoke as (
100
- ...values: readonly unknown[]
101
- ) => Promise<OutputOf<C>>
102
- const result =
103
- 'on' in current
104
- ? await invokeExact(current, receiverPath(args[0] as ReceiverOf<C>), args[1], request)
105
- : await invokeExact(current, args[0], request)
108
+ const result = isInstanceMethod(current)
109
+ ? await kernel.session.invoke(
110
+ reference(bindingRef.current.domain, current)(receiverPath(args[0] as Receiver)),
111
+ args[1] as never,
112
+ request,
113
+ )
114
+ : await kernel.session.invoke(
115
+ reference(bindingRef.current.domain, current),
116
+ args[0] as never,
117
+ request,
118
+ )
106
119
  const refresh = policy.refresh ?? 'all'
107
120
  if (refresh === 'all') store.invalidate()
108
121
  else if (refresh !== 'none') {
@@ -111,15 +124,15 @@ export function useAction<C extends Callable>(
111
124
  store.invalidate(target.ast, { page: target.page })
112
125
  })
113
126
  }
114
- return result
127
+ return result as CallableResultOf<C>
115
128
  } catch (error) {
116
129
  policy.onError?.(error)
117
130
  throw error
118
131
  }
119
132
  },
120
- [store],
133
+ [kernel, store],
121
134
  )
122
- const action = useAsyncAction(invoke as (...args: ActionArgs<C>) => Promise<OutputOf<C>>)
135
+ const action = useAsyncAction(invoke)
123
136
  return useMemo(() => projectAction(action), [action])
124
137
  }
125
138
 
@@ -141,6 +154,10 @@ function projectAction<Args extends unknown[], Result>(
141
154
  }
142
155
  }
143
156
 
144
- function receiverPath(receiver: { readonly id: NodeId }): string {
145
- return Path.id(receiver.id).raw
157
+ function isInstanceMethod(callable: Callable): callable is InstanceMethod {
158
+ return 'owner' in callable && callable.static === false
159
+ }
160
+
161
+ function receiverPath(receiver: Receiver): Path {
162
+ return Path.id(receiver.id)
146
163
  }