@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
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InputOf,
|
|
3
|
+
InstanceMethod,
|
|
4
|
+
OutputOf,
|
|
5
|
+
ReceiverOf,
|
|
6
|
+
RemoteCallableOf,
|
|
7
|
+
} from '@astrale-os/sdk/domain'
|
|
8
|
+
import type { NodeId } from '@astrale-os/sdk/graph/node'
|
|
9
|
+
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
|
+
|
|
13
|
+
import { Path } from '@astrale-os/sdk/graph/path'
|
|
14
|
+
import { useCallback, useMemo, useRef } from 'react'
|
|
15
|
+
|
|
16
|
+
import type { Action as AsyncAction } from '../graph/action.js'
|
|
17
|
+
|
|
18
|
+
import { useAction as useAsyncAction } from '../graph/action.js'
|
|
19
|
+
import { useGraphStore } from '../graph/store.js'
|
|
20
|
+
import { bindingFor } from './domain.hook.js'
|
|
21
|
+
|
|
22
|
+
type Callable = RemoteCallableOf<schema.DomainSchema> | InstanceMethod
|
|
23
|
+
|
|
24
|
+
const QUERY_REFRESH = Symbol('shell-react.query-refresh')
|
|
25
|
+
|
|
26
|
+
export interface QueryRefresh {
|
|
27
|
+
readonly id: string
|
|
28
|
+
readonly [QUERY_REFRESH]: () => {
|
|
29
|
+
readonly ast: QueryAST
|
|
30
|
+
readonly page: Readonly<{ readonly size: number }>
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type RefreshableQuery<Input, Query extends QueryAST> = {
|
|
35
|
+
readonly id: string
|
|
36
|
+
readonly page: Readonly<{ readonly size: number }>
|
|
37
|
+
prepare?(input: Input): Input
|
|
38
|
+
build(input: Input): Query
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Pair one exact named Query definition with its admitted input for targeted invalidation. */
|
|
42
|
+
export function queryRefresh<Input, Query extends QueryAST>(
|
|
43
|
+
definition: RefreshableQuery<Input, Query>,
|
|
44
|
+
input: Input,
|
|
45
|
+
): QueryRefresh {
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
id: definition.id,
|
|
48
|
+
[QUERY_REFRESH]: () => {
|
|
49
|
+
const prepared = definition.prepare?.(input) ?? input
|
|
50
|
+
return Object.freeze({ ast: definition.build(prepared), page: definition.page })
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type ActionRefresh =
|
|
56
|
+
| 'all'
|
|
57
|
+
| 'none'
|
|
58
|
+
| {
|
|
59
|
+
readonly queries: readonly QueryRefresh[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ActionOptions extends DomainInvokeOptions {
|
|
63
|
+
readonly refresh?: ActionRefresh
|
|
64
|
+
readonly onError?: (error: unknown) => void
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type ActionArgs<C extends Callable> = C extends InstanceMethod
|
|
68
|
+
? [receiver: ReceiverOf<C>, input: InputOf<C>]
|
|
69
|
+
: [input: InputOf<C>]
|
|
70
|
+
|
|
71
|
+
export interface DomainAction<Args extends unknown[], Result> {
|
|
72
|
+
run(...args: Args): Promise<Result>
|
|
73
|
+
readonly pending: boolean
|
|
74
|
+
readonly error: unknown
|
|
75
|
+
readonly result: Result | undefined
|
|
76
|
+
reset(): void
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Invoke one schema-declared Function or Method and invalidate Store by explicit policy. */
|
|
80
|
+
export function useAction<C extends Callable>(
|
|
81
|
+
callable: C,
|
|
82
|
+
options: ActionOptions = {},
|
|
83
|
+
): DomainAction<ActionArgs<C>, OutputOf<C>> {
|
|
84
|
+
const binding = bindingFor(callable)
|
|
85
|
+
const store = useGraphStore()
|
|
86
|
+
const callableRef = useRef(callable)
|
|
87
|
+
callableRef.current = callable
|
|
88
|
+
const bindingRef = useRef(binding)
|
|
89
|
+
bindingRef.current = binding
|
|
90
|
+
const optionsRef = useRef(options)
|
|
91
|
+
optionsRef.current = options
|
|
92
|
+
|
|
93
|
+
const invoke = useCallback(
|
|
94
|
+
async (...args: ActionArgs<C>): Promise<OutputOf<C>> => {
|
|
95
|
+
const current = callableRef.current
|
|
96
|
+
const policy = optionsRef.current
|
|
97
|
+
const { refresh: _refresh, onError: _onError, ...request } = policy
|
|
98
|
+
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)
|
|
106
|
+
const refresh = policy.refresh ?? 'all'
|
|
107
|
+
if (refresh === 'all') store.invalidate()
|
|
108
|
+
else if (refresh !== 'none') {
|
|
109
|
+
refresh.queries.forEach((query) => {
|
|
110
|
+
const target = query[QUERY_REFRESH]()
|
|
111
|
+
store.invalidate(target.ast, { page: target.page })
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
return result
|
|
115
|
+
} catch (error) {
|
|
116
|
+
policy.onError?.(error)
|
|
117
|
+
throw error
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
[store],
|
|
121
|
+
)
|
|
122
|
+
const action = useAsyncAction(invoke as (...args: ActionArgs<C>) => Promise<OutputOf<C>>)
|
|
123
|
+
return useMemo(() => projectAction(action), [action])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function projectAction<Args extends unknown[], Result>(
|
|
127
|
+
action: AsyncAction<Args, Result>,
|
|
128
|
+
): DomainAction<Args, Result> {
|
|
129
|
+
return {
|
|
130
|
+
run: (...args) => action(...args),
|
|
131
|
+
get pending() {
|
|
132
|
+
return action.pending
|
|
133
|
+
},
|
|
134
|
+
get error() {
|
|
135
|
+
return action.error
|
|
136
|
+
},
|
|
137
|
+
get result() {
|
|
138
|
+
return action.result
|
|
139
|
+
},
|
|
140
|
+
reset: action.reset,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function receiverPath(receiver: { readonly id: NodeId }): string {
|
|
145
|
+
return Path.id(receiver.id).raw
|
|
146
|
+
}
|
|
@@ -1,16 +1,132 @@
|
|
|
1
|
+
import type { DomainBinding, KernelClient } from '@astrale-os/shell'
|
|
2
|
+
|
|
3
|
+
import { schema } from '@astrale-os/sdk/schema'
|
|
4
|
+
|
|
5
|
+
import { useSessionKernel } from '../auth/session-kernel.js'
|
|
6
|
+
|
|
7
|
+
type Resource<T> =
|
|
8
|
+
| { readonly status: 'pending'; readonly promise: Promise<void> }
|
|
9
|
+
| { readonly status: 'ready'; readonly value: T }
|
|
10
|
+
| { readonly status: 'failed'; readonly error: unknown }
|
|
11
|
+
|
|
12
|
+
const typed = new WeakMap<KernelClient, WeakMap<object, Resource<DomainBinding>>>()
|
|
13
|
+
const dynamic = new WeakMap<KernelClient, Resource<DomainBinding>>()
|
|
14
|
+
const aggregates = new WeakMap<
|
|
15
|
+
KernelClient,
|
|
16
|
+
Map<string, Resource<Readonly<Record<string, DomainBinding>>>>
|
|
17
|
+
>()
|
|
18
|
+
const bindingByValue = new WeakMap<object, DomainBinding>()
|
|
19
|
+
|
|
1
20
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* shared scoped memory, so typed writes are optimistic and revalidate (§6).
|
|
21
|
+
* Resolve an exact verified DomainBinding. The first render suspends while Session snapshot and schema
|
|
22
|
+
* revision checks complete; later renders return the retained binding synchronously.
|
|
5
23
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
24
|
+
export function useDomain<const S extends schema.DomainSchema>(schema: S): DomainBinding<S> {
|
|
25
|
+
const kernel = useSessionKernel()
|
|
26
|
+
let bySchema = typed.get(kernel)
|
|
27
|
+
if (bySchema === undefined) {
|
|
28
|
+
bySchema = new WeakMap()
|
|
29
|
+
typed.set(kernel, bySchema)
|
|
30
|
+
}
|
|
31
|
+
let resource = bySchema.get(schema)
|
|
32
|
+
if (resource === undefined) {
|
|
33
|
+
resource = createResource(kernel.domain(schema)) as Resource<DomainBinding>
|
|
34
|
+
bySchema.set(schema, resource)
|
|
35
|
+
}
|
|
36
|
+
const binding = read(resource) as unknown as DomainBinding<S>
|
|
37
|
+
registerBinding(binding as unknown as DomainBinding)
|
|
38
|
+
return binding
|
|
39
|
+
}
|
|
8
40
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
41
|
+
/** Dynamic verified root binding used by tools that intentionally do not carry a schema witness. */
|
|
42
|
+
export function useDynamicDomain(): DomainBinding {
|
|
43
|
+
const kernel = useSessionKernel()
|
|
44
|
+
let resource = dynamic.get(kernel)
|
|
45
|
+
if (resource === undefined) {
|
|
46
|
+
resource = createResource(kernel.domain())
|
|
47
|
+
dynamic.set(kernel, resource)
|
|
48
|
+
}
|
|
49
|
+
const binding = read(resource)
|
|
50
|
+
registerBinding(binding)
|
|
51
|
+
return binding
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Bind several exact installed schemas behind one Suspense boundary and stable named result. */
|
|
55
|
+
export function useDomains<const Schemas extends Readonly<Record<string, schema.DomainSchema>>>(
|
|
56
|
+
schemas: Schemas,
|
|
57
|
+
): { readonly [Name in keyof Schemas]: DomainBinding<Schemas[Name]> } {
|
|
58
|
+
const kernel = useSessionKernel()
|
|
59
|
+
const names = Object.keys(schemas).sort()
|
|
60
|
+
if (names.length === 0) return Object.freeze({}) as never
|
|
61
|
+
const key = names
|
|
62
|
+
.map((name) => `${name}\u0000${schemas[name]!.origin}\u0000${schema.revision(schemas[name]!)}`)
|
|
63
|
+
.join('\u0001')
|
|
64
|
+
let bySet = aggregates.get(kernel)
|
|
65
|
+
if (bySet === undefined) {
|
|
66
|
+
bySet = new Map()
|
|
67
|
+
aggregates.set(kernel, bySet)
|
|
68
|
+
}
|
|
69
|
+
let resource = bySet.get(key)
|
|
70
|
+
if (resource === undefined) {
|
|
71
|
+
resource = createResource(
|
|
72
|
+
Promise.all(
|
|
73
|
+
names.map(async (name) => [name, await kernel.domain(schemas[name]!)] as const),
|
|
74
|
+
).then((entries) => Object.freeze(Object.fromEntries(entries))),
|
|
75
|
+
)
|
|
76
|
+
bySet.set(key, resource)
|
|
77
|
+
}
|
|
78
|
+
const values = read(resource)
|
|
79
|
+
Object.values(values).forEach(registerBinding)
|
|
80
|
+
return values as { readonly [Name in keyof Schemas]: DomainBinding<Schemas[Name]> }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function bindingFor(value: object): DomainBinding {
|
|
84
|
+
const binding = bindingByValue.get(value)
|
|
85
|
+
if (binding === undefined) {
|
|
86
|
+
throw new Error('The definition is not owned by a Domain bound in this React runtime.')
|
|
87
|
+
}
|
|
88
|
+
return binding
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function registerBinding(binding: DomainBinding): void {
|
|
92
|
+
const seen = new WeakSet<object>()
|
|
93
|
+
const visit = (value: unknown, depth: number): void => {
|
|
94
|
+
if (depth > 4 || value === null || typeof value !== 'object' || seen.has(value)) return
|
|
95
|
+
seen.add(value)
|
|
96
|
+
bindingByValue.set(value, binding)
|
|
97
|
+
for (const [key, child] of Object.entries(value)) {
|
|
98
|
+
if (key === 'schema' || key === 'publication' || key === 'session') continue
|
|
99
|
+
visit(child, depth + 1)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
visit(binding, 0)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function createResource<T>(promise: Promise<T>): Resource<T> {
|
|
106
|
+
const cell: {
|
|
107
|
+
status: 'pending' | 'ready' | 'failed'
|
|
108
|
+
promise: Promise<void>
|
|
109
|
+
value?: T
|
|
110
|
+
error?: unknown
|
|
111
|
+
} = {
|
|
112
|
+
status: 'pending',
|
|
113
|
+
promise: Promise.resolve(),
|
|
114
|
+
}
|
|
115
|
+
cell.promise = promise.then(
|
|
116
|
+
(value) => {
|
|
117
|
+
cell.status = 'ready'
|
|
118
|
+
cell.value = value
|
|
119
|
+
},
|
|
120
|
+
(error: unknown) => {
|
|
121
|
+
cell.status = 'failed'
|
|
122
|
+
cell.error = error
|
|
123
|
+
},
|
|
124
|
+
)
|
|
125
|
+
return cell as Resource<T>
|
|
126
|
+
}
|
|
12
127
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
128
|
+
function read<T>(resource: Resource<T>): T {
|
|
129
|
+
if (resource.status === 'pending') throw resource.promise
|
|
130
|
+
if (resource.status === 'failed') throw resource.error
|
|
131
|
+
return resource.value
|
|
16
132
|
}
|
package/src/schema/index.ts
CHANGED
|
@@ -1,31 +1,10 @@
|
|
|
1
|
-
// schema — the typing substrate (API §6). Typed kernel/domain bindings, typed
|
|
2
|
-
// reads, method/function dispatch. See SHELL_REACT_API.md.
|
|
3
1
|
export { useKernel } from './kernel.hook.js'
|
|
4
|
-
export { useDomain } from './domain.hook.js'
|
|
5
|
-
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from './
|
|
12
|
-
export {
|
|
13
|
-
export { useMethod } from './method.hook.js'
|
|
14
|
-
export type { MethodOptions } from './method.hook.js'
|
|
15
|
-
export { useFunction } from './function.hook.js'
|
|
16
|
-
export type { FunctionOptions } from './function.hook.js'
|
|
17
|
-
export type {
|
|
18
|
-
AutoMethodAction,
|
|
19
|
-
BoundMethodAction,
|
|
20
|
-
EndpointResult,
|
|
21
|
-
FunctionNames,
|
|
22
|
-
FunctionParams,
|
|
23
|
-
FunctionResult,
|
|
24
|
-
MethodIsStatic,
|
|
25
|
-
MethodNames,
|
|
26
|
-
MethodParams,
|
|
27
|
-
MethodResult,
|
|
28
|
-
TargetedMethodAction,
|
|
29
|
-
TypedChildrenResult,
|
|
30
|
-
TypedNodeResult,
|
|
31
|
-
} from './types.js'
|
|
2
|
+
export { useDomain, useDomains, useDynamicDomain } from './domain.hook.js'
|
|
3
|
+
export { queryRefresh, useAction } from './action.hook.js'
|
|
4
|
+
export type { ActionOptions, ActionRefresh, DomainAction, QueryRefresh } from './action.hook.js'
|
|
5
|
+
export { useMutation } from './mutation.hook.js'
|
|
6
|
+
export type { MutationOptions } from './mutation.hook.js'
|
|
7
|
+
export { useDynamicObject, useObject } from './object.hook.js'
|
|
8
|
+
export type { RichReadOptions } from './object.hook.js'
|
|
9
|
+
export { RelationUnavailableError, useRelation } from './relation.hook.js'
|
|
10
|
+
export type { RelationOptions, RelationResource, RelationUnavailable } from './relation.hook.js'
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
* useKernel (API §6) — the typed kernel, `kernel.withSchema(KernelSchema)`,
|
|
3
|
-
* memoized per (effective) session. The kernel's own schema baked in; dispatch
|
|
4
|
-
* and reads run as the subtree's principal over its scoped memory (§4).
|
|
5
|
-
*/
|
|
6
|
-
import type { FnMap, SchemaBoundView } from '@astrale-os/kernel-client'
|
|
1
|
+
import type { DomainBinding } from '@astrale-os/shell'
|
|
7
2
|
|
|
8
|
-
import { KernelSchema } from '@astrale-os/kernel
|
|
3
|
+
import { KernelSchema } from '@astrale-os/sdk/schema/kernel'
|
|
9
4
|
|
|
10
|
-
import {
|
|
11
|
-
import { useMemory } from '../graph/memory/scope.js'
|
|
12
|
-
import { bindingFor } from './binding.js'
|
|
5
|
+
import { useDomain } from './domain.hook.js'
|
|
13
6
|
|
|
14
|
-
/** The
|
|
15
|
-
export function useKernel():
|
|
16
|
-
return
|
|
7
|
+
/** The verified, exactly typed Kernel Domain binding. */
|
|
8
|
+
export function useKernel(): DomainBinding<typeof KernelSchema> {
|
|
9
|
+
return useDomain(KernelSchema)
|
|
17
10
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { MutationDefinition } from '@astrale-os/sdk/mutation'
|
|
2
|
+
|
|
3
|
+
import { bindMutations } from '@astrale-os/sdk/mutation'
|
|
4
|
+
import { useCallback, useMemo, useRef } from 'react'
|
|
5
|
+
|
|
6
|
+
import type { Action as AsyncAction } from '../graph/action.js'
|
|
7
|
+
import type { DomainAction } from './action.hook.js'
|
|
8
|
+
|
|
9
|
+
import { useAction as useAsyncAction } from '../graph/action.js'
|
|
10
|
+
import { useGraphStore } from '../graph/store.js'
|
|
11
|
+
|
|
12
|
+
export interface MutationOptions {
|
|
13
|
+
readonly optimistic?: boolean
|
|
14
|
+
readonly onError?: (error: unknown) => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Execute one named SDK Mutation definition through GraphStore optimism/invalidation. */
|
|
18
|
+
export function useMutation<Input, Output>(
|
|
19
|
+
definition: MutationDefinition<Input, Output>,
|
|
20
|
+
options: MutationOptions = {},
|
|
21
|
+
): DomainAction<[Input], Output> {
|
|
22
|
+
const store = useGraphStore()
|
|
23
|
+
const definitionRef = useRef(definition)
|
|
24
|
+
definitionRef.current = definition
|
|
25
|
+
const optionsRef = useRef(options)
|
|
26
|
+
optionsRef.current = options
|
|
27
|
+
const run = useCallback(
|
|
28
|
+
async (input: Input): Promise<Output> => {
|
|
29
|
+
const execute = bindMutations((ast) =>
|
|
30
|
+
store.mutate(ast, {
|
|
31
|
+
optimistic: optionsRef.current.optimistic ?? true,
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
34
|
+
try {
|
|
35
|
+
return await execute(definitionRef.current, input)
|
|
36
|
+
} catch (error) {
|
|
37
|
+
optionsRef.current.onError?.(error)
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
[store],
|
|
42
|
+
)
|
|
43
|
+
const action = useAsyncAction(run)
|
|
44
|
+
return useMemo(() => project(action), [action])
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function project<Input, Output>(
|
|
48
|
+
action: AsyncAction<[Input], Output>,
|
|
49
|
+
): DomainAction<[Input], Output> {
|
|
50
|
+
return {
|
|
51
|
+
run: (input) => action(input),
|
|
52
|
+
get pending() {
|
|
53
|
+
return action.pending
|
|
54
|
+
},
|
|
55
|
+
get error() {
|
|
56
|
+
return action.error
|
|
57
|
+
},
|
|
58
|
+
get result() {
|
|
59
|
+
return action.result
|
|
60
|
+
},
|
|
61
|
+
reset: action.reset,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { StoreQueryResponse } from '@astrale-os/kernel-client/store'
|
|
2
|
+
import type { BoundInstanceOf, Definition } from '@astrale-os/sdk/domain'
|
|
3
|
+
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
4
|
+
import type { PathLike } from '@astrale-os/sdk/graph/path'
|
|
5
|
+
|
|
6
|
+
import { Path } from '@astrale-os/sdk/graph/path'
|
|
7
|
+
import { Query } from '@astrale-os/sdk/query'
|
|
8
|
+
import { useCallback, useMemo } from 'react'
|
|
9
|
+
|
|
10
|
+
import type { GraphResource } from '../graph/resource.js'
|
|
11
|
+
|
|
12
|
+
import { useStoreResource } from '../graph/resource.js'
|
|
13
|
+
import { bindingFor } from './domain.hook.js'
|
|
14
|
+
|
|
15
|
+
export interface RichReadOptions {
|
|
16
|
+
readonly pageSize?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type ObjectDefinition = Pick<
|
|
20
|
+
Definition<'class' | 'interface'>,
|
|
21
|
+
'kind' | 'origin' | 'name' | 'key' | 'schemaRef' | 'definition'
|
|
22
|
+
> & { readonly family: 'node' }
|
|
23
|
+
|
|
24
|
+
/** Read and bind one exact rich object definition exclusively through GraphStore. */
|
|
25
|
+
export function useObject<RichDefinition extends ObjectDefinition>(
|
|
26
|
+
definition: RichDefinition,
|
|
27
|
+
target: PathLike | null | undefined,
|
|
28
|
+
options: RichReadOptions = {},
|
|
29
|
+
): GraphResource<BoundInstanceOf<RichDefinition> | null> {
|
|
30
|
+
const binding = bindingFor(definition)
|
|
31
|
+
const path = target === null || target === undefined ? null : Path.from(target)
|
|
32
|
+
const query = useMemo(
|
|
33
|
+
() =>
|
|
34
|
+
path === null
|
|
35
|
+
? null
|
|
36
|
+
: Query.from({ kind: 'node', paths: [path], binding: 'object' })
|
|
37
|
+
.filter({ satisfies: definition.schemaRef })
|
|
38
|
+
.select({ kind: 'graph' }),
|
|
39
|
+
[definition, path?.raw],
|
|
40
|
+
)
|
|
41
|
+
const project = useCallback(
|
|
42
|
+
(response: StoreQueryResponse<NonNullable<typeof query>>) => {
|
|
43
|
+
const result = response.result
|
|
44
|
+
if (result.kind !== 'graph' || result.selection.kind !== 'node') return null
|
|
45
|
+
const id = result.selection.ids[0]
|
|
46
|
+
const node =
|
|
47
|
+
id === undefined
|
|
48
|
+
? undefined
|
|
49
|
+
: result.graph.nodes.find((candidate: { readonly id: unknown }) => candidate.id === id)
|
|
50
|
+
const bind = binding.$.bind as unknown as (
|
|
51
|
+
expected: RichDefinition,
|
|
52
|
+
value: Node,
|
|
53
|
+
) => BoundInstanceOf<RichDefinition>
|
|
54
|
+
return node === undefined ? null : bind(definition, node)
|
|
55
|
+
},
|
|
56
|
+
[binding, definition],
|
|
57
|
+
)
|
|
58
|
+
return useStoreResource(query, options.pageSize ?? 1, project)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Explicitly untyped point read for inspectors; it never impersonates `useObject`. */
|
|
62
|
+
export function useDynamicObject(
|
|
63
|
+
target: PathLike | null | undefined,
|
|
64
|
+
options: RichReadOptions = {},
|
|
65
|
+
): GraphResource<Node | null> {
|
|
66
|
+
const path = target === null || target === undefined ? null : Path.from(target)
|
|
67
|
+
const query = useMemo(
|
|
68
|
+
() =>
|
|
69
|
+
path === null
|
|
70
|
+
? null
|
|
71
|
+
: Query.from({ kind: 'node', paths: [path], binding: 'dynamic_object' }).select({
|
|
72
|
+
kind: 'graph',
|
|
73
|
+
}),
|
|
74
|
+
[path?.raw],
|
|
75
|
+
)
|
|
76
|
+
const project = useCallback((response: StoreQueryResponse<NonNullable<typeof query>>) => {
|
|
77
|
+
const result = response.result
|
|
78
|
+
if (result.kind !== 'graph' || result.selection.kind !== 'node') return null
|
|
79
|
+
const id = result.selection.ids[0]
|
|
80
|
+
return id === undefined
|
|
81
|
+
? null
|
|
82
|
+
: (result.graph.nodes.find((candidate) => candidate.id === id) ?? null)
|
|
83
|
+
}, [])
|
|
84
|
+
return useStoreResource(query, options.pageSize ?? 1, project)
|
|
85
|
+
}
|