@astrale-os/shell-react 0.2.9 → 0.2.10-beta.3
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.
- package/dist/application/apps/app-host.d.ts +4 -15
- package/dist/application/apps/app-host.d.ts.map +1 -1
- package/dist/application/apps/app-host.js +1 -1
- package/dist/application/apps/apps.hook.d.ts +7 -4
- package/dist/application/apps/apps.hook.d.ts.map +1 -1
- package/dist/application/apps/apps.hook.js +10 -2
- package/dist/application/apps/domains.hook.d.ts +1 -1
- package/dist/application/apps/domains.hook.d.ts.map +1 -1
- package/dist/application/apps/domains.hook.js +1 -1
- package/dist/application/apps/open-app.hook.d.ts +2 -3
- package/dist/application/apps/open-app.hook.d.ts.map +1 -1
- package/dist/application/index.d.ts +2 -4
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +2 -3
- package/dist/application/spaces/space.hook.d.ts +2 -2
- package/dist/application/spaces/space.hook.d.ts.map +1 -1
- package/dist/application/spaces/space.hook.js +2 -2
- package/dist/application/spaces/spaces.hook.d.ts +2 -3
- package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
- package/dist/application/spaces/spaces.hook.js +10 -3
- package/dist/auth/act-as.context.d.ts +15 -32
- package/dist/auth/act-as.context.d.ts.map +1 -1
- package/dist/auth/act-as.context.js +22 -66
- package/dist/auth/auth.hook.d.ts +1 -0
- package/dist/auth/auth.hook.d.ts.map +1 -1
- package/dist/auth/auth.hook.js +2 -22
- package/dist/auth/can.hook.d.ts +10 -38
- package/dist/auth/can.hook.d.ts.map +1 -1
- package/dist/auth/can.hook.js +35 -110
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/self.hook.d.ts +2 -2
- package/dist/auth/self.hook.d.ts.map +1 -1
- package/dist/auth/self.hook.js +0 -7
- package/dist/auth/session-kernel.d.ts +2 -3
- package/dist/auth/session-kernel.d.ts.map +1 -1
- package/dist/auth/session-kernel.js +4 -13
- package/dist/components/astrale.d.ts +14 -0
- package/dist/components/astrale.d.ts.map +1 -0
- package/dist/components/astrale.js +12 -0
- package/dist/components/boundaries.d.ts +47 -0
- package/dist/components/boundaries.d.ts.map +1 -0
- package/dist/components/boundaries.js +55 -0
- package/dist/components/can.d.ts +11 -0
- package/dist/components/can.d.ts.map +1 -0
- package/dist/components/can.js +5 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +3 -0
- package/dist/graph/call/call.hook.d.ts +8 -18
- package/dist/graph/call/call.hook.d.ts.map +1 -1
- package/dist/graph/call/call.hook.js +7 -13
- package/dist/graph/call/stream.hook.d.ts +12 -20
- package/dist/graph/call/stream.hook.d.ts.map +1 -1
- package/dist/graph/call/stream.hook.js +55 -111
- package/dist/graph/graph.context.d.ts +4 -3
- package/dist/graph/graph.context.d.ts.map +1 -1
- package/dist/graph/graph.context.js +2 -8
- package/dist/graph/guards.error.d.ts +7 -8
- package/dist/graph/guards.error.d.ts.map +1 -1
- package/dist/graph/guards.error.js +11 -7
- package/dist/graph/index.d.ts +8 -16
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/index.js +3 -7
- package/dist/graph/memory/read/envelope.d.ts +22 -54
- package/dist/graph/memory/read/envelope.d.ts.map +1 -1
- package/dist/graph/memory/read/envelope.js +26 -20
- package/dist/graph/memory/read/idle.d.ts +1 -15
- package/dist/graph/memory/read/idle.d.ts.map +1 -1
- package/dist/graph/memory/read/idle.js +4 -13
- package/dist/graph/query-definition.hook.d.ts +11 -0
- package/dist/graph/query-definition.hook.d.ts.map +1 -0
- package/dist/graph/query-definition.hook.js +205 -0
- package/dist/graph/resource.d.ts +34 -0
- package/dist/graph/resource.d.ts.map +1 -0
- package/dist/graph/resource.js +244 -0
- package/dist/graph/store.d.ts +25 -0
- package/dist/graph/store.d.ts.map +1 -0
- package/dist/graph/store.js +69 -0
- package/dist/host/actions.hook.d.ts +34 -0
- package/dist/host/actions.hook.d.ts.map +1 -0
- package/dist/host/actions.hook.js +125 -0
- package/dist/host/components.d.ts +15 -0
- package/dist/host/components.d.ts.map +1 -0
- package/dist/host/components.js +14 -0
- package/dist/host/index.d.ts +5 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +3 -0
- package/dist/index.d.ts +26 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -31
- package/dist/intents/envelope.d.ts +7 -19
- package/dist/intents/envelope.d.ts.map +1 -1
- package/dist/intents/envelope.js +2 -3
- package/dist/intents/send-intent.hook.d.ts +5 -7
- package/dist/intents/send-intent.hook.d.ts.map +1 -1
- package/dist/intents/send-intent.hook.js +17 -75
- package/dist/navigation/adapters/adapter.d.ts +5 -0
- package/dist/navigation/adapters/adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.js +4 -0
- package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/url.adapter.js +57 -10
- package/dist/navigation/codec.d.ts +60 -0
- package/dist/navigation/codec.d.ts.map +1 -0
- package/dist/navigation/codec.js +121 -0
- package/dist/navigation/history.d.ts +11 -9
- package/dist/navigation/history.d.ts.map +1 -1
- package/dist/navigation/history.js +6 -8
- package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
- package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/ancestors.hook.js +7 -51
- package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/location.hook.js +4 -6
- package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/scope.hook.js +4 -6
- package/dist/navigation/index.d.ts +4 -2
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +2 -1
- package/dist/navigation/link.d.ts +12 -0
- package/dist/navigation/link.d.ts.map +1 -1
- package/dist/navigation/link.js +13 -2
- package/dist/navigation/location.d.ts +13 -40
- package/dist/navigation/location.d.ts.map +1 -1
- package/dist/navigation/location.js +14 -76
- package/dist/navigation/scope.context.d.ts +17 -26
- package/dist/navigation/scope.context.d.ts.map +1 -1
- package/dist/navigation/scope.context.js +140 -108
- package/dist/navigation/snapshot.d.ts +14 -19
- package/dist/navigation/snapshot.d.ts.map +1 -1
- package/dist/navigation/snapshot.js +48 -44
- package/dist/schema/action.hook.d.ts +44 -0
- package/dist/schema/action.hook.d.ts.map +1 -0
- package/dist/schema/action.hook.js +72 -0
- package/dist/schema/domain.hook.d.ts +12 -7
- package/dist/schema/domain.hook.d.ts.map +1 -1
- package/dist/schema/domain.hook.js +101 -4
- package/dist/schema/index.d.ts +9 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +5 -7
- package/dist/schema/kernel.hook.d.ts +4 -9
- package/dist/schema/kernel.hook.d.ts.map +1 -1
- package/dist/schema/kernel.hook.js +4 -6
- package/dist/schema/mutation.hook.d.ts +9 -0
- package/dist/schema/mutation.hook.d.ts.map +1 -0
- package/dist/schema/mutation.hook.js +41 -0
- package/dist/schema/object.hook.d.ts +16 -0
- package/dist/schema/object.hook.d.ts.map +1 -0
- package/dist/schema/object.hook.js +46 -0
- package/dist/schema/relation.hook.d.ts +46 -0
- package/dist/schema/relation.hook.d.ts.map +1 -0
- package/dist/schema/relation.hook.js +136 -0
- package/dist/selection/live.d.ts +9 -17
- package/dist/selection/live.d.ts.map +1 -1
- package/dist/selection/live.js +65 -112
- package/dist/selection/scope.context.js +5 -4
- package/dist/session/boot/boot.d.ts +1 -13
- package/dist/session/boot/boot.d.ts.map +1 -1
- package/dist/session/boot/boot.js +9 -27
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.d.ts +1 -4
- package/dist/session/kernel-instance.hook.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.js +1 -5
- package/dist/session/provider.d.ts +9 -23
- package/dist/session/provider.d.ts.map +1 -1
- package/dist/session/provider.js +29 -75
- package/dist/session/session.context.d.ts +5 -0
- package/dist/session/session.context.d.ts.map +1 -1
- package/dist/window/adopt.d.ts +0 -1
- package/dist/window/adopt.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.d.ts +10 -6
- package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.js +14 -72
- package/dist/window/hooks/views-for.hook.d.ts +4 -3
- package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
- package/dist/window/hooks/views-for.hook.js +6 -22
- package/dist/window/hooks/windows.hook.d.ts.map +1 -1
- package/dist/window/hooks/windows.hook.js +3 -4
- package/dist/window/host.d.ts +9 -11
- package/dist/window/host.d.ts.map +1 -1
- package/dist/window/host.js +26 -62
- package/dist/window/hub.d.ts +2 -0
- package/dist/window/hub.d.ts.map +1 -1
- package/dist/window/hub.js +33 -0
- package/dist/window/index.d.ts +2 -2
- package/dist/window/index.d.ts.map +1 -1
- package/dist/window/index.js +2 -2
- package/dist/window/lifecycle/mount.d.ts +5 -44
- package/dist/window/lifecycle/mount.d.ts.map +1 -1
- package/dist/window/lifecycle/mount.js +14 -120
- package/dist/window/lifecycle/states.d.ts +0 -5
- package/dist/window/lifecycle/states.d.ts.map +1 -1
- package/package.json +20 -8
- package/src/application/apps/app-host.tsx +11 -15
- package/src/application/apps/apps.hook.ts +13 -6
- package/src/application/apps/domains.hook.ts +1 -1
- package/src/application/apps/open-app.hook.ts +3 -4
- package/src/application/index.ts +4 -6
- package/src/application/spaces/space.hook.ts +5 -6
- package/src/application/spaces/spaces.hook.ts +14 -9
- package/src/auth/act-as.context.tsx +37 -91
- package/src/auth/auth.hook.ts +2 -30
- package/src/auth/can.hook.ts +44 -135
- package/src/auth/index.ts +1 -0
- package/src/auth/self.hook.ts +2 -9
- package/src/auth/session-kernel.ts +6 -16
- package/src/components/astrale.tsx +40 -0
- package/src/components/boundaries.tsx +113 -0
- package/src/components/can.tsx +16 -0
- package/src/components/index.ts +13 -0
- package/src/graph/call/call.hook.ts +22 -27
- package/src/graph/call/stream.hook.ts +66 -143
- package/src/graph/graph.context.ts +6 -11
- package/src/graph/guards.error.ts +17 -55
- package/src/graph/index.ts +23 -17
- package/src/graph/memory/read/envelope.ts +40 -65
- package/src/graph/memory/read/idle.ts +5 -18
- package/src/graph/query-definition.hook.ts +270 -0
- package/src/graph/resource.ts +358 -0
- package/src/graph/store.ts +97 -0
- package/src/host/actions.hook.ts +165 -0
- package/src/host/components.tsx +29 -0
- package/src/host/index.ts +17 -0
- package/src/index.ts +131 -124
- package/src/intents/envelope.ts +7 -23
- package/src/intents/send-intent.hook.ts +24 -79
- package/src/navigation/adapters/adapter.ts +3 -0
- package/src/navigation/adapters/memory.adapter.ts +4 -0
- package/src/navigation/adapters/url.adapter.ts +48 -8
- package/src/navigation/codec.ts +190 -0
- package/src/navigation/history.ts +20 -11
- package/src/navigation/hooks/ancestors.hook.ts +10 -60
- package/src/navigation/hooks/location.hook.ts +4 -6
- package/src/navigation/hooks/scope.hook.ts +4 -6
- package/src/navigation/index.ts +18 -2
- package/src/navigation/link.tsx +27 -2
- package/src/navigation/location.ts +26 -93
- package/src/navigation/scope.context.tsx +151 -136
- package/src/navigation/snapshot.ts +69 -50
- package/src/schema/action.hook.ts +146 -0
- package/src/schema/domain.hook.ts +127 -11
- package/src/schema/index.ts +9 -30
- package/src/schema/kernel.hook.ts +6 -13
- package/src/schema/mutation.hook.ts +63 -0
- package/src/schema/object.hook.ts +85 -0
- package/src/schema/relation.hook.ts +253 -0
- package/src/selection/live.ts +75 -125
- package/src/selection/scope.context.tsx +4 -4
- package/src/session/boot/boot.ts +8 -33
- package/src/session/index.ts +1 -0
- package/src/session/kernel-instance.hook.ts +2 -11
- package/src/session/provider.tsx +34 -103
- package/src/session/session.context.ts +6 -0
- package/src/window/adopt.ts +0 -1
- package/src/window/hooks/target-node.hook.ts +20 -85
- package/src/window/hooks/views-for.hook.ts +12 -25
- package/src/window/hooks/windows.hook.ts +3 -4
- package/src/window/host.tsx +35 -77
- package/src/window/hub.ts +33 -0
- package/src/window/index.ts +3 -3
- package/src/window/lifecycle/mount.ts +15 -160
- package/src/window/lifecycle/states.ts +1 -5
- package/dist/application/roles.hook.d.ts +0 -7
- package/dist/application/roles.hook.d.ts.map +0 -1
- package/dist/application/roles.hook.js +0 -23
- package/dist/graph/memory/base.d.ts +0 -21
- package/dist/graph/memory/base.d.ts.map +0 -1
- package/dist/graph/memory/base.js +0 -33
- package/dist/graph/memory/read/read.d.ts +0 -9
- package/dist/graph/memory/read/read.d.ts.map +0 -1
- package/dist/graph/memory/read/read.js +0 -87
- package/dist/graph/memory/scope.d.ts +0 -7
- package/dist/graph/memory/scope.d.ts.map +0 -1
- package/dist/graph/memory/scope.js +0 -25
- package/dist/graph/mutate/move.hook.d.ts +0 -7
- package/dist/graph/mutate/move.hook.d.ts.map +0 -1
- package/dist/graph/mutate/move.hook.js +0 -49
- package/dist/graph/mutate/mutate.hook.d.ts +0 -17
- package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
- package/dist/graph/mutate/mutate.hook.js +0 -45
- package/dist/graph/query/children.hook.d.ts +0 -29
- package/dist/graph/query/children.hook.d.ts.map +0 -1
- package/dist/graph/query/children.hook.js +0 -64
- package/dist/graph/query/graph.hook.d.ts +0 -9
- package/dist/graph/query/graph.hook.d.ts.map +0 -1
- package/dist/graph/query/graph.hook.js +0 -5
- package/dist/graph/query/neighbors.hook.d.ts +0 -7
- package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
- package/dist/graph/query/neighbors.hook.js +0 -104
- package/dist/graph/query/node.hook.d.ts +0 -14
- package/dist/graph/query/node.hook.d.ts.map +0 -1
- package/dist/graph/query/node.hook.js +0 -43
- package/dist/graph/query/query.hook.d.ts +0 -14
- package/dist/graph/query/query.hook.d.ts.map +0 -1
- package/dist/graph/query/query.hook.js +0 -23
- package/dist/schema/bind-read.d.ts +0 -37
- package/dist/schema/bind-read.d.ts.map +0 -1
- package/dist/schema/bind-read.js +0 -205
- package/dist/schema/binding.d.ts +0 -21
- package/dist/schema/binding.d.ts.map +0 -1
- package/dist/schema/binding.js +0 -99
- package/dist/schema/function.hook.d.ts +0 -9
- package/dist/schema/function.hook.d.ts.map +0 -1
- package/dist/schema/function.hook.js +0 -40
- package/dist/schema/method.hook.d.ts +0 -14
- package/dist/schema/method.hook.d.ts.map +0 -1
- package/dist/schema/method.hook.js +0 -49
- package/dist/schema/tag.d.ts +0 -11
- package/dist/schema/tag.d.ts.map +0 -1
- package/dist/schema/tag.js +0 -11
- package/dist/schema/types.d.ts +0 -73
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js +0 -1
- package/dist/schema/write.d.ts +0 -16
- package/dist/schema/write.d.ts.map +0 -1
- package/dist/schema/write.js +0 -56
- package/src/application/roles.hook.ts +0 -41
- package/src/graph/memory/base.ts +0 -50
- package/src/graph/memory/read/read.ts +0 -103
- package/src/graph/memory/scope.ts +0 -29
- package/src/graph/mutate/move.hook.ts +0 -70
- package/src/graph/mutate/mutate.hook.ts +0 -69
- package/src/graph/query/children.hook.ts +0 -136
- package/src/graph/query/graph.hook.ts +0 -13
- package/src/graph/query/neighbors.hook.ts +0 -159
- package/src/graph/query/node.hook.ts +0 -83
- package/src/graph/query/query.hook.ts +0 -42
- package/src/schema/bind-read.ts +0 -319
- package/src/schema/binding.ts +0 -146
- package/src/schema/function.hook.ts +0 -68
- package/src/schema/method.hook.ts +0 -103
- package/src/schema/tag.ts +0 -19
- package/src/schema/types.ts +0 -150
- package/src/schema/write.ts +0 -96
package/src/session/provider.tsx
CHANGED
|
@@ -1,94 +1,54 @@
|
|
|
1
|
-
import type { MemoryEvent } from '@astrale-os/kernel-client/store'
|
|
2
1
|
import type { Shell, ShellConfig } from '@astrale-os/shell'
|
|
3
2
|
import type { ReactElement, ReactNode } from 'react'
|
|
4
3
|
|
|
5
4
|
import { createShell } from '@astrale-os/shell'
|
|
6
|
-
|
|
7
|
-
* ShellProvider — the composition root (API §2, SPEC §5): owns the shell boot
|
|
8
|
-
* state machine (a config OR a prebuilt Shell; `createShell → init → whoami →
|
|
9
|
-
* ready`), seats `ShellContext` and `GraphContext`, and registers its boot-retry
|
|
10
|
-
* into the per-shell connection store. One live shell per mounted provider,
|
|
11
|
-
* StrictMode/HMR-safe (deferred teardown), keyed on config identity. Children
|
|
12
|
-
* render only at `ready`, so useShell/useSelf are synchronous below.
|
|
13
|
-
*/
|
|
14
|
-
import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'
|
|
5
|
+
import { useCallback, useEffect, useReducer, useRef, useState } from 'react'
|
|
15
6
|
|
|
16
|
-
import type { GraphMemory } from '../graph/graph.context.js'
|
|
17
7
|
import type { BootRef } from './boot/ownership.js'
|
|
18
8
|
import type { SelfNode } from './session.context.js'
|
|
19
9
|
|
|
20
10
|
import { primeUser } from '../application/user/user.store.js'
|
|
21
11
|
import { GraphContext } from '../graph/graph.context.js'
|
|
22
|
-
import {
|
|
12
|
+
import { resolveGraphStoreScope, retainStore, storeFor } from '../graph/store.js'
|
|
23
13
|
import { configIdentity, isShellConfig, resolveSelf } from './boot/boot.js'
|
|
24
14
|
import { cancelTeardown, disposeShell, scheduleTeardown } from './boot/ownership.js'
|
|
25
15
|
import { bootReducer, INITIAL_BOOT } from './boot/status.js'
|
|
26
16
|
import { connectionStore } from './connection/connection.store.js'
|
|
27
17
|
import { ShellContext } from './session.context.js'
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
export type ShellError =
|
|
31
|
-
| { kind: 'refresh'; shape: unknown; error: unknown }
|
|
32
|
-
| { kind: 'mutation'; mutationId: string; error: unknown }
|
|
33
|
-
| { kind: 'connection'; error: unknown }
|
|
19
|
+
export type ShellError = { readonly kind: 'connection'; readonly error: unknown }
|
|
34
20
|
|
|
35
21
|
export interface ShellProviderProps {
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
fallback?: ReactNode
|
|
43
|
-
/** Rendered when boot fails; `retry` re-runs init. Default: rethrow to the nearest boundary. */
|
|
44
|
-
errorFallback?: (error: unknown, retry: () => void) => ReactNode
|
|
45
|
-
/** Global error channel: warm-read refresh failures, rolled-back mutations, watch drops. */
|
|
46
|
-
onError?: (error: ShellError) => void
|
|
47
|
-
children: ReactNode
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Map a memory event to the documented `ShellError` union (API §2). `refresh`
|
|
52
|
-
* (warm-read revalidation failure) and `mutation` (rolled-back write) are the
|
|
53
|
-
* two the channel promises; `divergence`/`invariant` are Tier-0/dev tripwires
|
|
54
|
-
* outside the union and are not bridged here.
|
|
55
|
-
*/
|
|
56
|
-
function toShellError(event: MemoryEvent): ShellError | null {
|
|
57
|
-
switch (event.kind) {
|
|
58
|
-
case 'refresh':
|
|
59
|
-
return { kind: 'refresh', shape: event.shape, error: event.error }
|
|
60
|
-
case 'mutation':
|
|
61
|
-
return { kind: 'mutation', mutationId: event.mutationId, error: event.error }
|
|
62
|
-
default:
|
|
63
|
-
return null
|
|
64
|
-
}
|
|
22
|
+
/** A Shell configuration or an already-constructed Shell capability. */
|
|
23
|
+
readonly config: ShellConfig | Shell
|
|
24
|
+
readonly fallback?: ReactNode
|
|
25
|
+
readonly errorFallback?: (error: unknown, retry: () => void) => ReactNode
|
|
26
|
+
readonly onError?: (error: ShellError) => void
|
|
27
|
+
readonly children: ReactNode
|
|
65
28
|
}
|
|
66
29
|
|
|
30
|
+
/** Own and initialize exactly one Shell for a React subtree. */
|
|
67
31
|
export function ShellProvider(props: ShellProviderProps): ReactElement | null {
|
|
68
32
|
const { config, fallback, errorFallback, onError, children } = props
|
|
69
|
-
|
|
70
33
|
const [state, dispatch] = useReducer(bootReducer, INITIAL_BOOT)
|
|
71
34
|
const [attempt, setAttempt] = useState(0)
|
|
72
|
-
|
|
73
35
|
const bootRef = useRef<BootRef>({ key: null, shell: null, generation: 0 })
|
|
74
36
|
const configRef = useRef(config)
|
|
75
37
|
configRef.current = config
|
|
76
38
|
const onErrorRef = useRef(onError)
|
|
77
39
|
onErrorRef.current = onError
|
|
78
|
-
|
|
79
40
|
const configKey = configIdentity(config)
|
|
80
41
|
|
|
81
42
|
const startBoot = useCallback((ref: BootRef) => {
|
|
82
43
|
const generation = (ref.generation += 1)
|
|
83
44
|
dispatch({ type: 'connecting' })
|
|
84
|
-
|
|
85
45
|
let shell: Shell
|
|
86
|
-
const current = configRef.current
|
|
87
46
|
try {
|
|
47
|
+
const current = configRef.current
|
|
88
48
|
shell = isShellConfig(current) ? createShell(current) : current
|
|
89
|
-
} catch (
|
|
90
|
-
dispatch({ type: 'error', error
|
|
91
|
-
onErrorRef.current?.({ kind: 'connection', error
|
|
49
|
+
} catch (error) {
|
|
50
|
+
dispatch({ type: 'error', error })
|
|
51
|
+
onErrorRef.current?.({ kind: 'connection', error })
|
|
92
52
|
return
|
|
93
53
|
}
|
|
94
54
|
ref.shell = shell
|
|
@@ -99,33 +59,29 @@ export function ShellProvider(props: ShellProviderProps): ReactElement | null {
|
|
|
99
59
|
if (generation !== ref.generation) return
|
|
100
60
|
const self: SelfNode | null = await resolveSelf(shell)
|
|
101
61
|
if (generation !== ref.generation) return
|
|
102
|
-
// Pre-resolve the OS-plane user binding (API §2/§12.2) — NON-FATAL: a
|
|
103
|
-
// missing OS plane marks it unavailable without failing boot (whoami above
|
|
104
|
-
// stays the fatal gate). Seeds the user store so `useUser` is synchronous.
|
|
105
62
|
await primeUser(shell)
|
|
106
63
|
if (generation !== ref.generation) return
|
|
107
|
-
|
|
108
|
-
} catch (err) {
|
|
64
|
+
const storeScope = await resolveGraphStoreScope(shell, self)
|
|
109
65
|
if (generation !== ref.generation) return
|
|
110
|
-
|
|
111
|
-
|
|
66
|
+
const graph = storeFor(shell, storeScope)
|
|
67
|
+
dispatch({
|
|
68
|
+
type: 'ready',
|
|
69
|
+
runtime: { shell, self, storeScope, store: graph.store, ownsStore: graph.owned },
|
|
70
|
+
})
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (generation !== ref.generation) return
|
|
73
|
+
dispatch({ type: 'error', error })
|
|
74
|
+
onErrorRef.current?.({ kind: 'connection', error })
|
|
112
75
|
}
|
|
113
76
|
})()
|
|
114
77
|
}, [])
|
|
115
78
|
|
|
116
79
|
useEffect(() => {
|
|
117
80
|
const ref = bootRef.current
|
|
118
|
-
// The shell this provider will run with once the effect settles: a prebuilt
|
|
119
|
-
// Shell is the config object itself; a config-built one is whatever this
|
|
120
|
-
// instance already booted (adopted on a StrictMode/HMR re-setup). Cancel any
|
|
121
|
-
// pending deferred teardown for it before deciding — this also cancels a
|
|
122
|
-
// teardown another provider scheduled for the SAME prebuilt Shell.
|
|
123
81
|
const current = configRef.current
|
|
124
82
|
const adopting = isShellConfig(current) ? ref.shell : current
|
|
125
83
|
if (adopting !== null) cancelTeardown(adopting)
|
|
126
|
-
|
|
127
84
|
if (ref.key !== configKey) {
|
|
128
|
-
// First boot, config change, or a retry that cleared the key: reboot fresh.
|
|
129
85
|
if (ref.shell !== null) {
|
|
130
86
|
cancelTeardown(ref.shell)
|
|
131
87
|
disposeShell(ref.shell)
|
|
@@ -134,12 +90,7 @@ export function ShellProvider(props: ShellProviderProps): ReactElement | null {
|
|
|
134
90
|
ref.shell = null
|
|
135
91
|
startBoot(ref)
|
|
136
92
|
}
|
|
137
|
-
// Same key already booting/booted → adopt (StrictMode's second setup).
|
|
138
|
-
|
|
139
93
|
return () => {
|
|
140
|
-
// Defer teardown one macrotask; a synchronous re-setup (StrictMode/HMR or a
|
|
141
|
-
// different provider adopting the same prebuilt Shell) cancels it first and
|
|
142
|
-
// keeps the same live shell.
|
|
143
94
|
if (ref.shell !== null) scheduleTeardown(ref.shell, ref)
|
|
144
95
|
else ref.key = null
|
|
145
96
|
}
|
|
@@ -154,52 +105,32 @@ export function ShellProvider(props: ShellProviderProps): ReactElement | null {
|
|
|
154
105
|
}
|
|
155
106
|
ref.key = null
|
|
156
107
|
dispatch({ type: 'connecting' })
|
|
157
|
-
setAttempt((
|
|
108
|
+
setAttempt((value) => value + 1)
|
|
158
109
|
}, [])
|
|
159
110
|
|
|
160
|
-
// The base (default-scope) memory for the booted Shell — the SAME instance
|
|
161
|
-
// the graph/schema/nav hooks read through `graph/memory/scope.ts`. Seated in
|
|
162
|
-
// `GraphContext` so selection's liveness has a source; null until ready.
|
|
163
111
|
const shell = state.runtime?.shell ?? null
|
|
164
|
-
const memory = useMemo<GraphMemory | null>(
|
|
165
|
-
() => (shell === null ? null : baseMemoryFor(shell)),
|
|
166
|
-
[shell],
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
// Bridge the memory's event channel onto the provider `onError` (API §2/§8):
|
|
170
|
-
// warm-refresh failures and rolled-back mutations surface here rather than being
|
|
171
|
-
// swallowed. Registered while the booted shell is live; cleared on teardown.
|
|
172
112
|
useEffect(() => {
|
|
173
|
-
if (shell
|
|
174
|
-
|
|
175
|
-
const mapped = toShellError(event)
|
|
176
|
-
if (mapped !== null) onErrorRef.current?.(mapped)
|
|
177
|
-
})
|
|
178
|
-
return () => setMemoryErrorSink(shell, null)
|
|
179
|
-
}, [shell])
|
|
113
|
+
if (shell !== null) connectionStore(shell).setRetry(retry)
|
|
114
|
+
}, [shell, retry])
|
|
180
115
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
// until the transport-status + result-`seq` feed lands, with no surface change.
|
|
116
|
+
const store = state.runtime?.store ?? null
|
|
117
|
+
const storeScope = state.runtime?.storeScope ?? null
|
|
184
118
|
useEffect(() => {
|
|
185
|
-
if (shell === null) return
|
|
186
|
-
|
|
187
|
-
}, [shell,
|
|
119
|
+
if (shell === null || store === null || storeScope === null) return
|
|
120
|
+
return retainStore(storeFor(shell, storeScope))
|
|
121
|
+
}, [shell, store, storeScope])
|
|
188
122
|
|
|
189
123
|
if (state.status === 'error') {
|
|
190
|
-
// Wrapped in a fragment so the component's declared return type stays
|
|
191
|
-
// `ReactElement | null` — valid JSX under @types/react 18 AND 19 (the react
|
|
192
|
-
// peer range is >=18), even though `errorFallback`/`fallback` yield ReactNode.
|
|
193
124
|
if (errorFallback !== undefined) return <>{errorFallback(state.error, retry)}</>
|
|
194
125
|
throw state.error
|
|
195
126
|
}
|
|
196
127
|
if (state.status !== 'ready' || state.runtime === null) {
|
|
197
|
-
return fallback
|
|
128
|
+
return fallback === undefined ? null : <>{fallback}</>
|
|
198
129
|
}
|
|
199
130
|
|
|
200
131
|
return (
|
|
201
132
|
<ShellContext.Provider value={state.runtime}>
|
|
202
|
-
<GraphContext.Provider value={
|
|
133
|
+
<GraphContext.Provider value={state.runtime.store}>{children}</GraphContext.Provider>
|
|
203
134
|
</ShellContext.Provider>
|
|
204
135
|
)
|
|
205
136
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GraphStore } from '@astrale-os/kernel-client/store'
|
|
1
2
|
import type { KernelClient, Shell } from '@astrale-os/shell'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -7,6 +8,8 @@ import type { KernelClient, Shell } from '@astrale-os/shell'
|
|
|
7
8
|
*/
|
|
8
9
|
import { createContext } from 'react'
|
|
9
10
|
|
|
11
|
+
import type { GraphStoreScope } from '../graph/store.js'
|
|
12
|
+
|
|
10
13
|
/**
|
|
11
14
|
* whoami's node type, derived from the auth surface so shell-react needs no
|
|
12
15
|
* direct `@astrale-os/kernel-core` dependency (`Node` is not yet re-exported by
|
|
@@ -22,6 +25,9 @@ export interface ShellRuntime {
|
|
|
22
25
|
* bound kernel exposes no auth surface (a bare prebuilt Shell in tests).
|
|
23
26
|
*/
|
|
24
27
|
readonly self: SelfNode | null
|
|
28
|
+
readonly storeScope: GraphStoreScope
|
|
29
|
+
readonly store: GraphStore
|
|
30
|
+
readonly ownsStore: boolean
|
|
25
31
|
}
|
|
26
32
|
export const ShellContext = createContext<ShellRuntime | null>(null)
|
|
27
33
|
ShellContext.displayName = 'AstraleShellContext'
|
package/src/window/adopt.ts
CHANGED
|
@@ -14,7 +14,6 @@ export interface AdoptRecord {
|
|
|
14
14
|
readonly window: Window
|
|
15
15
|
readonly slot: StageSlot
|
|
16
16
|
readonly state: WindowState
|
|
17
|
-
readonly targetId: string | undefined
|
|
18
17
|
/** Close the window, release its slot, drop it from the registry (fired if unadopted). */
|
|
19
18
|
dispose(): void
|
|
20
19
|
}
|
|
@@ -1,94 +1,29 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* The id starts from `shell.targetNodeId` (handshake) and a host `setTarget`
|
|
6
|
-
* intent retargets it; the id resolves to a live `Node` through the shell kernel.
|
|
7
|
-
*
|
|
8
|
-
* Honest subset (flagged): the read is a one-shot `kernel.get` re-run on id
|
|
9
|
-
* change, not a memory watch, so `live` is false. Once composed with `useNode(id)`
|
|
10
|
-
* it becomes real stale-while-revalidate liveness with no consumer change.
|
|
11
|
-
*/
|
|
12
|
-
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
|
+
import { Path } from '@astrale-os/sdk/graph/path'
|
|
4
|
+
import { useCallback, useMemo, useSyncExternalStore } from 'react'
|
|
13
5
|
|
|
14
|
-
import type {
|
|
15
|
-
import type { Node } from '../lifecycle/mount.js'
|
|
6
|
+
import type { GraphResource } from '../../graph/resource.js'
|
|
16
7
|
|
|
17
|
-
import {
|
|
8
|
+
import { useDynamicObject } from '../../schema/object.hook.js'
|
|
18
9
|
import { useShell } from '../../session/shell.hook.js'
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return id.startsWith('/') || id.startsWith('@') ? id : `@${id}`
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ReadSnapshot {
|
|
30
|
-
readonly node: Node | null
|
|
31
|
-
readonly pending: boolean
|
|
32
|
-
readonly error: unknown
|
|
11
|
+
/**
|
|
12
|
+
* Read the canonical target admitted by the parent handshake and subsequent
|
|
13
|
+
* parent-owned hot swaps without remounting this View document.
|
|
14
|
+
*/
|
|
15
|
+
export function useTargetNode(): GraphResource<Node | null> {
|
|
16
|
+
return useDynamicObject(useTargetPath())
|
|
33
17
|
}
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export function useTargetNode(): NodeResult {
|
|
19
|
+
/** Reactive canonical target Path; null represents an explicit parent clear. */
|
|
20
|
+
export function useTargetPath(): Path | null {
|
|
38
21
|
const shell = useShell()
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const nodeId = (message.envelope.payload as { nodeId?: string }).nodeId
|
|
47
|
-
if (typeof nodeId === 'string') setId(nodeId)
|
|
48
|
-
})
|
|
49
|
-
}, [shell])
|
|
50
|
-
|
|
51
|
-
return useNodeRead(shell.kernel, id)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** One-shot get + refetch, in the read envelope. The graph-module seam. */
|
|
55
|
-
function useNodeRead(kernel: KernelClient, id: string | null): NodeResult {
|
|
56
|
-
const [snap, setSnap] = useState<ReadSnapshot>(IDLE_READ)
|
|
57
|
-
const aliveRef = useRef(true)
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
aliveRef.current = true
|
|
60
|
-
return () => {
|
|
61
|
-
aliveRef.current = false
|
|
62
|
-
}
|
|
63
|
-
}, [])
|
|
64
|
-
|
|
65
|
-
const load = useCallback(async (): Promise<void> => {
|
|
66
|
-
if (id === null) {
|
|
67
|
-
if (aliveRef.current) setSnap(IDLE_READ)
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
if (aliveRef.current) setSnap((s) => ({ node: s.node, pending: true, error: undefined }))
|
|
71
|
-
try {
|
|
72
|
-
const node = await kernel.get(toRef(id))
|
|
73
|
-
if (aliveRef.current) setSnap({ node: node ?? null, pending: false, error: undefined })
|
|
74
|
-
} catch (error) {
|
|
75
|
-
if (aliveRef.current) setSnap((s) => ({ node: s.node, pending: false, error }))
|
|
76
|
-
}
|
|
77
|
-
}, [kernel, id])
|
|
78
|
-
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
void load()
|
|
81
|
-
}, [load])
|
|
82
|
-
|
|
83
|
-
if (id === null) {
|
|
84
|
-
return { ...idleReadState(), node: null }
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
node: snap.node,
|
|
88
|
-
pending: snap.pending,
|
|
89
|
-
error: snap.error,
|
|
90
|
-
live: false,
|
|
91
|
-
seq: 0,
|
|
92
|
-
refetch: load,
|
|
93
|
-
}
|
|
22
|
+
const subscribe = useCallback(
|
|
23
|
+
(listener: () => void) => shell.onTargetChange(() => listener()),
|
|
24
|
+
[shell],
|
|
25
|
+
)
|
|
26
|
+
const snapshot = useCallback(() => shell.targetNodeId, [shell])
|
|
27
|
+
const target = useSyncExternalStore(subscribe, snapshot, snapshot)
|
|
28
|
+
return useMemo(() => (target === undefined ? null : Path.parse(target)), [target])
|
|
94
29
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
2
|
+
import type { NodePath, PathLike } from '@astrale-os/sdk/graph/path'
|
|
3
|
+
import type { ResolvedView } from '@astrale-os/shell'
|
|
3
4
|
|
|
5
|
+
import { Path } from '@astrale-os/sdk/graph/path'
|
|
4
6
|
/**
|
|
5
7
|
* useViewsFor (API §10) — "what Views can render this node", as mountable
|
|
6
8
|
* `ViewDescriptor`s for the open-with menu. Backed one-shot (`live:false`) by the
|
|
@@ -10,23 +12,22 @@ import type { Shell } from '@astrale-os/shell'
|
|
|
10
12
|
import { useMemo } from 'react'
|
|
11
13
|
|
|
12
14
|
import type { ReadState } from '../../graph/memory/read/envelope.js'
|
|
13
|
-
import type { Node, ViewDescriptor } from '../lifecycle/mount.js'
|
|
14
15
|
|
|
15
16
|
import { useAsyncResource } from '../../graph/async.js'
|
|
16
17
|
import { useShell } from '../../session/shell.hook.js'
|
|
17
18
|
|
|
18
19
|
export interface ViewsForResult extends ReadState {
|
|
19
|
-
readonly views: readonly
|
|
20
|
+
readonly views: readonly ResolvedView[]
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
const NO_VIEWS: readonly
|
|
23
|
+
const NO_VIEWS: readonly ResolvedView[] = Object.freeze([])
|
|
23
24
|
|
|
24
25
|
export function useViewsFor(node: Node | PathLike | null | undefined): ViewsForResult {
|
|
25
26
|
const shell = useShell()
|
|
26
27
|
const target = resolvePath(node)
|
|
27
28
|
|
|
28
|
-
const res = useAsyncResource<readonly
|
|
29
|
-
target === null ? null : () =>
|
|
29
|
+
const res = useAsyncResource<readonly ResolvedView[]>(
|
|
30
|
+
target === null ? null : () => shell.views.resolve(target),
|
|
30
31
|
NO_VIEWS,
|
|
31
32
|
[shell, target],
|
|
32
33
|
)
|
|
@@ -44,23 +45,9 @@ export function useViewsFor(node: Node | PathLike | null | undefined): ViewsForR
|
|
|
44
45
|
)
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
const rows = await shell.views.resolve(node)
|
|
50
|
-
if (rows.length === 0) return NO_VIEWS
|
|
51
|
-
return rows.map((r) => ({ id: r.id, path: r.path, url: r.url, handshake: r.handshake }))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** A path/`@id` the kernel read surface accepts, or `null` for an idle subject. */
|
|
55
|
-
function resolvePath(node: Node | PathLike | null | undefined): string | null {
|
|
48
|
+
/** One canonical target, or `null` for an idle subject. */
|
|
49
|
+
function resolvePath(node: Node | PathLike | null | undefined): NodePath | null {
|
|
56
50
|
if (node === null || node === undefined) return null
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
return node.startsWith('/') || node.startsWith('@') ? node : `@${node}`
|
|
60
|
-
}
|
|
61
|
-
const obj = node as { path?: { raw?: unknown }; id?: unknown; raw?: unknown }
|
|
62
|
-
if (typeof obj.path?.raw === 'string') return obj.path.raw
|
|
63
|
-
if (typeof obj.id === 'string') return `@${obj.id}`
|
|
64
|
-
if (typeof obj.raw === 'string') return obj.raw
|
|
65
|
-
return null
|
|
51
|
+
if ('id' in node) return Path.id(node.id).raw
|
|
52
|
+
return Path.from(node).raw
|
|
66
53
|
}
|
|
@@ -2,10 +2,9 @@ import type { Window } from '@astrale-os/shell'
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* useWindows / useWindowList (API §10) — reactive views over the windows a
|
|
5
|
-
* `ViewHost`/`AppHost`
|
|
6
|
-
* window-change feed, so
|
|
7
|
-
*
|
|
8
|
-
* tracked here — flagged in the module report as a shell foundation gap.
|
|
5
|
+
* `ViewHost`/`AppHost` or the framework-neutral Shell mounts. The hub mirrors
|
|
6
|
+
* Shell's immutable window-change feed, so credential, location, lifecycle,
|
|
7
|
+
* and imperative mounts remain reactive through one snapshot authority.
|
|
9
8
|
*/
|
|
10
9
|
import { useMemo, useSyncExternalStore } from 'react'
|
|
11
10
|
|