@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/dist/schema/write.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const writableCache = new WeakMap();
|
|
2
|
-
export function writableFor(kernel, memory) {
|
|
3
|
-
let entry = writableCache.get(kernel);
|
|
4
|
-
if (entry === undefined) {
|
|
5
|
-
const nodeIndex = new Map();
|
|
6
|
-
entry = { writable: withMemoryWrites(kernel, memory, nodeIndex), nodeIndex };
|
|
7
|
-
writableCache.set(kernel, entry);
|
|
8
|
-
}
|
|
9
|
-
return entry;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Wrap a session view so `updateNode`/`createNode` route through the memory's
|
|
13
|
-
* optimistic write shorthands. `BoundNode.update` addresses a node by `@<id>`,
|
|
14
|
-
* but the memory needs the node's class and tree path — so an `@<id>` ref is translated
|
|
15
|
-
* through `nodeIndex` (populated at bind time). A ref that is NOT indexed (a node
|
|
16
|
-
* that was never bound) falls back to the raw kernel-client floor:
|
|
17
|
-
* it still dispatches, just without the overlay — matching the imperative floor.
|
|
18
|
-
*/
|
|
19
|
-
function withMemoryWrites(kernel, memory, nodeIndex) {
|
|
20
|
-
const base = kernel;
|
|
21
|
-
const rawUpdate = base.updateNode.bind(base);
|
|
22
|
-
return extendCapabilities(kernel, {
|
|
23
|
-
updateNode: (cls, ref, props) => {
|
|
24
|
-
const node = indexedNode(nodeIndex, ref);
|
|
25
|
-
return node !== null ? memory.update(node, props) : rawUpdate(cls, ref, props);
|
|
26
|
-
},
|
|
27
|
-
createNode: (cls, at, props) => memory.create(cls, at, props),
|
|
28
|
-
// Credential rebind stays on the raw kernel-client floor (§6 note).
|
|
29
|
-
as: (cred) => base.as(cred),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
/** Overlay memory writes without materializing a possibly virtual session surface. */
|
|
33
|
-
function extendCapabilities(base, extension) {
|
|
34
|
-
return new Proxy(base, {
|
|
35
|
-
get(target, prop, receiver) {
|
|
36
|
-
return Object.prototype.hasOwnProperty.call(extension, prop)
|
|
37
|
-
? Reflect.get(extension, prop, extension)
|
|
38
|
-
: Reflect.get(target, prop, receiver);
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/** The tree path an `@<id>` write ref maps to, via the bind-time index; else null. */
|
|
43
|
-
function indexedNode(nodeIndex, ref) {
|
|
44
|
-
if (typeof ref !== 'string' || !ref.startsWith('@'))
|
|
45
|
-
return null;
|
|
46
|
-
return nodeIndex.get(ref.slice(1)) ?? null;
|
|
47
|
-
}
|
|
48
|
-
/** Record a bound node's raw value so the write cap retains its class and tree path. */
|
|
49
|
-
export function recordNode(nodeIndex, node) {
|
|
50
|
-
const wrapped = node;
|
|
51
|
-
const candidate = wrapped?.raw !== null && typeof wrapped?.raw === 'object' ? wrapped.raw : node;
|
|
52
|
-
const n = candidate;
|
|
53
|
-
if (n !== null && typeof n.id === 'string' && typeof n.path?.raw === 'string') {
|
|
54
|
-
nodeIndex.set(n.id, candidate);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { RoleNode } from '@astrale-os/shell'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* useRoles (API §12.2) — the roles self holds (`has_role` out-edges), over the
|
|
5
|
-
* async OS namespace (one-shot today, §12 flag).
|
|
6
|
-
*/
|
|
7
|
-
import { useMemo } from 'react'
|
|
8
|
-
|
|
9
|
-
import type { ReadState } from '../graph/memory/read/envelope.js'
|
|
10
|
-
|
|
11
|
-
import { useAsyncResource } from '../graph/async.js'
|
|
12
|
-
import { useShell } from '../session/shell.hook.js'
|
|
13
|
-
import { isOsPlaneAvailable } from './user/user.store.js'
|
|
14
|
-
|
|
15
|
-
const NO_ROLES: readonly RoleNode[] = []
|
|
16
|
-
|
|
17
|
-
export interface RolesResult extends ReadState {
|
|
18
|
-
readonly roles: readonly RoleNode[]
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function useRoles(): RolesResult {
|
|
22
|
-
const shell = useShell()
|
|
23
|
-
// OS plane unavailable (§12.2) → idle: no roles read.
|
|
24
|
-
const available = isOsPlaneAvailable(shell)
|
|
25
|
-
const res = useAsyncResource<readonly RoleNode[]>(
|
|
26
|
-
available ? () => shell.user.roles() : null,
|
|
27
|
-
NO_ROLES,
|
|
28
|
-
[shell, available],
|
|
29
|
-
)
|
|
30
|
-
return useMemo(
|
|
31
|
-
() => ({
|
|
32
|
-
roles: res.data,
|
|
33
|
-
pending: res.pending,
|
|
34
|
-
error: res.error,
|
|
35
|
-
live: false,
|
|
36
|
-
seq: 0,
|
|
37
|
-
refetch: res.refetch,
|
|
38
|
-
}),
|
|
39
|
-
[res],
|
|
40
|
-
)
|
|
41
|
-
}
|
package/src/graph/memory/base.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { GraphApi } from '@astrale-os/kernel-client/graph'
|
|
2
|
-
import type { GraphMemory, MemoryEvent } from '@astrale-os/kernel-client/store'
|
|
3
|
-
/**
|
|
4
|
-
* The base memory (API §5.4). One `GraphMemory` per live Shell — the partial
|
|
5
|
-
* client copy of the graph every graph/schema/nav hook reads through, so they all
|
|
6
|
-
* share one cache, one dedupe, one optimistic overlay. Derived from `shell.kernel`
|
|
7
|
-
* and memoized on the Shell object. Its `onError` fans out through a per-Shell
|
|
8
|
-
* sink the provider registers, so warm-refresh failures and rolled-back mutations
|
|
9
|
-
* reach the provider's `onError` channel (§2).
|
|
10
|
-
*/
|
|
11
|
-
import type { Shell } from '@astrale-os/shell'
|
|
12
|
-
|
|
13
|
-
import { createMemory } from '@astrale-os/kernel-client/store'
|
|
14
|
-
|
|
15
|
-
/** One memory per Shell reference — shared by every hook under that provider. */
|
|
16
|
-
const memoryByShell = new WeakMap<Shell, GraphMemory>()
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Per-Shell error sink (API §2/§8). The provider registers a bridge here; the
|
|
20
|
-
* memory emits refresh/mutation/divergence events through it, read lazily at
|
|
21
|
-
* emit time so registration order doesn't matter. Cleared on provider unmount.
|
|
22
|
-
*/
|
|
23
|
-
const errorSinks = new WeakMap<Shell, (event: MemoryEvent) => void>()
|
|
24
|
-
|
|
25
|
-
/** Register (or clear) the provider's memory-event bridge for a Shell. */
|
|
26
|
-
export function setMemoryErrorSink(
|
|
27
|
-
shell: Shell,
|
|
28
|
-
sink: ((event: MemoryEvent) => void) | null,
|
|
29
|
-
): void {
|
|
30
|
-
if (sink === null) errorSinks.delete(shell)
|
|
31
|
-
else errorSinks.set(shell, sink)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The base (default-scope) memory for a Shell — the SAME instance every graph/
|
|
36
|
-
* schema/nav hook reads through `useMemory`, so the provider can seat it in
|
|
37
|
-
* `GraphContext` (selection's liveness source) without minting a rival copy.
|
|
38
|
-
* Its `onError` fans out through the per-Shell sink so warm-refresh failures and
|
|
39
|
-
* rolled-back mutations reach `ShellProvider`'s `onError` channel (§2).
|
|
40
|
-
*/
|
|
41
|
-
export function baseMemoryFor(shell: Shell): GraphMemory {
|
|
42
|
-
let memory = memoryByShell.get(shell)
|
|
43
|
-
if (memory === undefined) {
|
|
44
|
-
memory = createMemory(shell.kernel as GraphApi, {
|
|
45
|
-
onError: (event) => errorSinks.get(shell)?.(event),
|
|
46
|
-
})
|
|
47
|
-
memoryByShell.set(shell, memory)
|
|
48
|
-
}
|
|
49
|
-
return memory
|
|
50
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
LiveResult,
|
|
3
|
-
ReadOptions as StoreReadOptions,
|
|
4
|
-
ShapeInput,
|
|
5
|
-
} from '@astrale-os/kernel-client/store'
|
|
6
|
-
|
|
7
|
-
import { canonicalizeAST, shapeInputToAST, stableStringify } from '@astrale-os/kernel-client/store'
|
|
8
|
-
/**
|
|
9
|
-
* The shared read substrate (API §1, §5). One `useSyncExternalStore` binding over
|
|
10
|
-
* a memory shape — the substrate every graph read hook narrows. Handles the four
|
|
11
|
-
* cross-cutting concerns once: idle inputs (§1.3), suspense-first on a cold shape
|
|
12
|
-
* (§1.4), stale-while-revalidate + `keepPrevious` (§1.5), and referential
|
|
13
|
-
* stability (§1.7 — an unchanged shape returns the store's own stable snapshot).
|
|
14
|
-
*/
|
|
15
|
-
import { useCallback, useRef, useSyncExternalStore } from 'react'
|
|
16
|
-
|
|
17
|
-
import type { CoreReadOptions, RawRead } from './envelope.js'
|
|
18
|
-
|
|
19
|
-
import { useMemory } from '../scope.js'
|
|
20
|
-
import { EMPTY_PENDING, IDLE_READ, withPending } from './envelope.js'
|
|
21
|
-
import { isIdleInput } from './idle.js'
|
|
22
|
-
|
|
23
|
-
const NOOP_UNSUB = (): void => {}
|
|
24
|
-
const IDLE_TOKEN = ' idle'
|
|
25
|
-
|
|
26
|
-
/** Project shell-react read options onto the store's — `with`/`window`/`live` key the shape. */
|
|
27
|
-
function storeReadOptions(opts?: CoreReadOptions): StoreReadOptions | undefined {
|
|
28
|
-
if (opts === undefined) return undefined
|
|
29
|
-
const out: StoreReadOptions = {}
|
|
30
|
-
if (opts.live !== undefined) out.live = opts.live
|
|
31
|
-
if (opts.window !== undefined) out.window = opts.window
|
|
32
|
-
// `with` is a PermName at the store/kernel (READ lit-up today); the public
|
|
33
|
-
// `PermMask` typing reconciles with the grant epoch (API §14 G7).
|
|
34
|
-
if (opts.with !== undefined) out.with = opts.with as unknown as StoreReadOptions['with']
|
|
35
|
-
return out
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* A stable per-render key for a shape input + its keying options, so the
|
|
40
|
-
* subscription/snapshot closures only re-bind when the LOGICAL read changes
|
|
41
|
-
* (not when an inline builder closure is re-created each render).
|
|
42
|
-
*/
|
|
43
|
-
function shapeToken(shape: ShapeInput, opts?: CoreReadOptions): string {
|
|
44
|
-
const canon = stableStringify(canonicalizeAST(shapeInputToAST(shape)))
|
|
45
|
-
return `${canon}#w=${String(opts?.with ?? '')}#win=${opts?.window ?? ''}#live=${
|
|
46
|
-
opts?.live === false ? '0' : '1'
|
|
47
|
-
}`
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Subscribe to a memory shape and project it. `null`/`undefined` shape → idle.
|
|
52
|
-
* Cold + `suspend` (default) throws the cold-shape promise; `suspend:false`
|
|
53
|
-
* returns empty-pending; `keepPrevious` returns the last data while confirming.
|
|
54
|
-
*/
|
|
55
|
-
export function useRead(shape: ShapeInput | null | undefined, opts?: CoreReadOptions): RawRead {
|
|
56
|
-
const memory = useMemory()
|
|
57
|
-
const idle = isIdleInput(shape)
|
|
58
|
-
|
|
59
|
-
const shapeRef = useRef<ShapeInput | null | undefined>(shape)
|
|
60
|
-
shapeRef.current = shape
|
|
61
|
-
const optsRef = useRef<CoreReadOptions | undefined>(opts)
|
|
62
|
-
optsRef.current = opts
|
|
63
|
-
|
|
64
|
-
const token = idle ? IDLE_TOKEN : shapeToken(shape as ShapeInput, opts)
|
|
65
|
-
|
|
66
|
-
const subscribe = useCallback(
|
|
67
|
-
(onStoreChange: () => void) => {
|
|
68
|
-
const s = shapeRef.current
|
|
69
|
-
if (token === IDLE_TOKEN || s === null || s === undefined) return NOOP_UNSUB
|
|
70
|
-
return memory.subscribe(s, onStoreChange, storeReadOptions(optsRef.current))
|
|
71
|
-
},
|
|
72
|
-
[memory, token],
|
|
73
|
-
)
|
|
74
|
-
const getSnapshot = useCallback((): LiveResult | null => {
|
|
75
|
-
const s = shapeRef.current
|
|
76
|
-
if (token === IDLE_TOKEN || s === null || s === undefined) return null
|
|
77
|
-
return memory.getSnapshot(s, storeReadOptions(optsRef.current))
|
|
78
|
-
}, [memory, token])
|
|
79
|
-
|
|
80
|
-
const snap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
|
|
81
|
-
const prevRef = useRef<LiveResult | null>(null)
|
|
82
|
-
|
|
83
|
-
if (idle) return IDLE_READ
|
|
84
|
-
|
|
85
|
-
const warm = memory.peek(shape as ShapeInput, storeReadOptions(opts)) !== null
|
|
86
|
-
if (warm && snap !== null) {
|
|
87
|
-
prevRef.current = snap
|
|
88
|
-
return snap
|
|
89
|
-
}
|
|
90
|
-
if (opts?.keepPrevious === true && prevRef.current !== null) {
|
|
91
|
-
return withPending(prevRef.current)
|
|
92
|
-
}
|
|
93
|
-
if (opts?.suspend !== false) {
|
|
94
|
-
// Cold FAILURE (§1.4): the shape fetched and rejected with no data to show —
|
|
95
|
-
// throw the error to the nearest boundary. Re-throwing the promise here would
|
|
96
|
-
// re-arm a fresh fetch every retry (the entry's inflight was cleared on
|
|
97
|
-
// failure), looping render→fetch→reject forever. This breaks that loop.
|
|
98
|
-
if (snap !== null && snap.error !== undefined) throw snap.error
|
|
99
|
-
// Cold shape: suspend on the first-confirmed-data promise (§1.4).
|
|
100
|
-
throw memory.promise(shape as ShapeInput, storeReadOptions(opts))
|
|
101
|
-
}
|
|
102
|
-
return EMPTY_PENDING
|
|
103
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { GraphApi } from '@astrale-os/kernel-client/graph'
|
|
2
|
-
import type { GraphMemory } from '@astrale-os/kernel-client/store'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Memory scope resolution (API §5.4). `useMemory` returns the memory for this
|
|
6
|
-
* subtree: the base memory derived from the provider's Shell, re-scoped (and
|
|
7
|
-
* re-api'd) to the `<ActAs>` principal via `forScope` when an identity binding is
|
|
8
|
-
* present — so a principal never shares cached results with another.
|
|
9
|
-
*/
|
|
10
|
-
import { useContext, useMemo } from 'react'
|
|
11
|
-
|
|
12
|
-
import { IdentityContext } from '../../auth/act-as.context.js'
|
|
13
|
-
import { ShellContext } from '../../session/session.context.js'
|
|
14
|
-
import { baseMemoryFor } from './base.js'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The memory for this subtree. Throws outside a `<ShellProvider>`. Above any
|
|
18
|
-
* `<ActAs>` it is the base memory; inside one it is scoped by the binding.
|
|
19
|
-
*/
|
|
20
|
-
export function useMemory(): GraphMemory {
|
|
21
|
-
const runtime = useContext(ShellContext)
|
|
22
|
-
const binding = useContext(IdentityContext)
|
|
23
|
-
const shell = runtime?.shell ?? null
|
|
24
|
-
return useMemo(() => {
|
|
25
|
-
if (shell === null) throw new Error('graph hooks must be used within a <ShellProvider>')
|
|
26
|
-
const base = baseMemoryFor(shell)
|
|
27
|
-
return binding === null ? base : base.forScope(binding.scope, binding.kernel as GraphApi)
|
|
28
|
-
}, [shell, binding])
|
|
29
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { NodeRefInput } from '@astrale-os/kernel-client'
|
|
2
|
-
import type { PathLike } from '@astrale-os/kernel-client/graph'
|
|
3
|
-
import type { GraphMemory } from '@astrale-os/kernel-client/store'
|
|
4
|
-
|
|
5
|
-
import { rawOf } from '@astrale-os/kernel-client/graph'
|
|
6
|
-
/**
|
|
7
|
-
* useMove (API §5, the G1 seam) — dispatch the sealed `node::move` method (the one
|
|
8
|
-
* tree op no patch arm can express). PESSIMISTIC today (honest `pending`); affected
|
|
9
|
-
* container shapes revalidate on settlement. Turns optimistic when the `nodes.move`
|
|
10
|
-
* patch arm lands, with zero consumer change.
|
|
11
|
-
*/
|
|
12
|
-
import { useCallback } from 'react'
|
|
13
|
-
|
|
14
|
-
import type { Action } from '../action.js'
|
|
15
|
-
import type { Node } from '../memory/read/envelope.js'
|
|
16
|
-
|
|
17
|
-
import { useSessionKernel } from '../../auth/session-kernel.js'
|
|
18
|
-
import { useAction } from '../action.js'
|
|
19
|
-
import { useMemory } from '../memory/scope.js'
|
|
20
|
-
|
|
21
|
-
export type MoveAction = Action<[node: Node | NodeRefInput, to: PathLike], void>
|
|
22
|
-
|
|
23
|
-
export function useMove(): MoveAction {
|
|
24
|
-
const kernel = useSessionKernel()
|
|
25
|
-
const memory = useMemory()
|
|
26
|
-
const run = useCallback(
|
|
27
|
-
async (node: Node | NodeRefInput, to: PathLike): Promise<void> => {
|
|
28
|
-
const method = isNode(node) ? `@${node.id}::move` : `${rawOf(node)}::move`
|
|
29
|
-
await kernel.call(method, { to: rawOf(to) })
|
|
30
|
-
await reconcileMove(memory, node, to)
|
|
31
|
-
},
|
|
32
|
-
[kernel, memory],
|
|
33
|
-
)
|
|
34
|
-
return useAction(run)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function isNode(x: Node | NodeRefInput): x is Node {
|
|
38
|
-
return typeof x === 'object' && x !== null && 'id' in x && 'class' in x && 'path' in x
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Root-first parent of a raw absolute path, or `null` at the root. */
|
|
42
|
-
function parentPathOf(raw: string): string | null {
|
|
43
|
-
const trimmed = raw.replace(/\/+$/, '')
|
|
44
|
-
const i = trimmed.lastIndexOf('/')
|
|
45
|
-
if (i < 0) return null
|
|
46
|
-
return i === 0 ? '/' : trimmed.slice(0, i)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Best-effort settlement reconciliation (Tier 0): refetch the source and
|
|
51
|
-
* destination container's default `children` shapes when they are observed. A
|
|
52
|
-
* custom-ordered/filtered children shape is keyed distinctly and is not reached
|
|
53
|
-
* here — consumers get honest `pending` and reconcile on G1.
|
|
54
|
-
*/
|
|
55
|
-
async function reconcileMove(
|
|
56
|
-
memory: GraphMemory,
|
|
57
|
-
node: Node | NodeRefInput,
|
|
58
|
-
to: PathLike,
|
|
59
|
-
): Promise<void> {
|
|
60
|
-
const path = isNode(node) ? rawOf(node.path) : rawOf(node)
|
|
61
|
-
const containers = new Set<string>([rawOf(to)])
|
|
62
|
-
const old = parentPathOf(path)
|
|
63
|
-
if (old !== null) containers.add(old)
|
|
64
|
-
await Promise.allSettled(
|
|
65
|
-
[...containers].map((c) => {
|
|
66
|
-
const snap = memory.peek((q) => q.from(c).children())
|
|
67
|
-
return snap !== null ? snap.refetch() : Promise.resolve()
|
|
68
|
-
}),
|
|
69
|
-
)
|
|
70
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { PatchBuilder } from '@astrale-os/kernel-client/graph'
|
|
2
|
-
import type { GraphMemory } from '@astrale-os/kernel-client/store'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* useMutate (API 5/1.6) - build a graph-scoped Action. The callback receives
|
|
6
|
-
* this subtree's GraphMemory, so callers do not need a separate useGraph() just
|
|
7
|
-
* to author the mutation. Patch-shaped writes are optimistic via their own
|
|
8
|
-
* overlay; pass a function `optimistic` to preview an opaque dispatch effect.
|
|
9
|
-
*/
|
|
10
|
-
import { useCallback, useRef } from 'react'
|
|
11
|
-
|
|
12
|
-
import type { Action } from '../action.js'
|
|
13
|
-
|
|
14
|
-
import { useAction } from '../action.js'
|
|
15
|
-
import { useMemory } from '../memory/scope.js'
|
|
16
|
-
|
|
17
|
-
export interface UseMutateOptions<A extends unknown[], R> {
|
|
18
|
-
/**
|
|
19
|
-
* `'auto'` (default) / `false`: the write's own overlay governs optimism - the
|
|
20
|
-
* callback's graph writes apply the authored patch. A function opens a
|
|
21
|
-
* MANUAL overlay decoupled from what the callback dispatches.
|
|
22
|
-
*/
|
|
23
|
-
optimistic?: 'auto' | false | ((overlay: PatchBuilder, ...args: A) => void)
|
|
24
|
-
/** default 'auto'. false = keep the manual overlay on failure (caller reconciles). */
|
|
25
|
-
rollback?: 'auto' | false
|
|
26
|
-
onCommit?: (result: R) => void
|
|
27
|
-
onError?: (error: unknown) => void
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function useMutate<A extends unknown[], R>(
|
|
31
|
-
fn: (graph: GraphMemory, ...args: A) => Promise<R>,
|
|
32
|
-
opts?: UseMutateOptions<A, R>,
|
|
33
|
-
): Action<A, R> {
|
|
34
|
-
const memory = useMemory()
|
|
35
|
-
const fnRef = useRef(fn)
|
|
36
|
-
fnRef.current = fn
|
|
37
|
-
const optsRef = useRef(opts)
|
|
38
|
-
optsRef.current = opts
|
|
39
|
-
|
|
40
|
-
const run = useCallback(
|
|
41
|
-
async (...args: A): Promise<R> => {
|
|
42
|
-
const o = optsRef.current
|
|
43
|
-
const optimistic = o?.optimistic
|
|
44
|
-
if (typeof optimistic === 'function') {
|
|
45
|
-
const overlay = memory.overlay((m) => optimistic(m, ...args))
|
|
46
|
-
try {
|
|
47
|
-
const result = await fnRef.current(memory, ...args)
|
|
48
|
-
overlay.commit()
|
|
49
|
-
o?.onCommit?.(result)
|
|
50
|
-
return result
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (o?.rollback !== false) overlay.rollback()
|
|
53
|
-
o?.onError?.(error)
|
|
54
|
-
throw error
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
const result = await fnRef.current(memory, ...args)
|
|
59
|
-
o?.onCommit?.(result)
|
|
60
|
-
return result
|
|
61
|
-
} catch (error) {
|
|
62
|
-
o?.onError?.(error)
|
|
63
|
-
throw error
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
[memory],
|
|
67
|
-
)
|
|
68
|
-
return useAction(run)
|
|
69
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type { AnyBoundNode, TypeNames } from '@astrale-os/kernel-client'
|
|
2
|
-
import type {
|
|
3
|
-
GatherBuilder,
|
|
4
|
-
OrderInput,
|
|
5
|
-
PathLike,
|
|
6
|
-
QuerySource,
|
|
7
|
-
WalkOpts,
|
|
8
|
-
} from '@astrale-os/kernel-client/graph'
|
|
9
|
-
import type { Schema } from '@astrale-os/kernel-dsl'
|
|
10
|
-
|
|
11
|
-
import { rawOf } from '@astrale-os/kernel-client/graph'
|
|
12
|
-
/**
|
|
13
|
-
* useChildren (API §5 + §6) — ONE public symbol, overloaded: pass `opts.type`
|
|
14
|
-
* (over a `BoundNode` parent) for the typed children, or a bare parent for the
|
|
15
|
-
* untyped children. Both ride the SAME windowed memory shape. The untyped floor
|
|
16
|
-
* is a windowed, live read of a node's direct children; the typed twin binds them.
|
|
17
|
-
*/
|
|
18
|
-
import { useMemo } from 'react'
|
|
19
|
-
|
|
20
|
-
import type { TypedChildrenResult } from '../../schema/types.js'
|
|
21
|
-
import type { ReadState, Node, ReadOptions, Windowed } from '../memory/read/envelope.js'
|
|
22
|
-
|
|
23
|
-
import { useChildren as useChildrenTyped } from '../../schema/bind-read.js'
|
|
24
|
-
import { useRead } from '../memory/read/read.js'
|
|
25
|
-
|
|
26
|
-
export interface ChildrenOptions extends ReadOptions {
|
|
27
|
-
/** Restrict to these classes (dual-path descent filter). */
|
|
28
|
-
classes?: PathLike[]
|
|
29
|
-
/** Server-ordered by a node prop / `id`. */
|
|
30
|
-
order?: OrderInput
|
|
31
|
-
/** Page size; `more.load()` extends. */
|
|
32
|
-
limit?: number
|
|
33
|
-
/** `append` (default, infinite) vs `paged` (replace). */
|
|
34
|
-
window?: 'append' | 'paged'
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface ChildrenResult extends ReadState, Windowed {
|
|
38
|
-
/** Ordered, all loaded pages, parent excluded. */
|
|
39
|
-
readonly children: readonly Node[]
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** A node's direct children — windowed, live; `null` parent is idle (§1.3). */
|
|
43
|
-
function useChildrenUntyped(
|
|
44
|
-
parent: Node | PathLike | null | undefined,
|
|
45
|
-
opts?: ChildrenOptions,
|
|
46
|
-
): ChildrenResult {
|
|
47
|
-
const shape = isIdle(parent) ? null : childrenShape(parent, opts)
|
|
48
|
-
const r = useRead(shape, opts)
|
|
49
|
-
return useMemo(
|
|
50
|
-
() => ({
|
|
51
|
-
pending: r.pending,
|
|
52
|
-
error: r.error,
|
|
53
|
-
live: r.live,
|
|
54
|
-
seq: r.seq,
|
|
55
|
-
refetch: r.refetch,
|
|
56
|
-
children: r.children,
|
|
57
|
-
more: r.more,
|
|
58
|
-
}),
|
|
59
|
-
[r],
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Typed: a bound node's children of `opts.type`. */
|
|
64
|
-
export function useChildren<S extends Schema, T extends TypeNames<S>>(
|
|
65
|
-
parent: AnyBoundNode<S> | null | undefined,
|
|
66
|
-
opts: ReadOptions & {
|
|
67
|
-
type: T
|
|
68
|
-
order?: OrderInput
|
|
69
|
-
limit?: number
|
|
70
|
-
window?: 'append' | 'paged'
|
|
71
|
-
},
|
|
72
|
-
): TypedChildrenResult<S, T>
|
|
73
|
-
/** Untyped: a node's direct children — windowed, live; `null` parent is idle (§1.3). */
|
|
74
|
-
export function useChildren(
|
|
75
|
-
parent: Node | PathLike | null | undefined,
|
|
76
|
-
opts?: ChildrenOptions,
|
|
77
|
-
): ChildrenResult
|
|
78
|
-
export function useChildren(
|
|
79
|
-
parent: unknown,
|
|
80
|
-
opts?: unknown,
|
|
81
|
-
): ReadState & Windowed & { readonly children: readonly unknown[] } {
|
|
82
|
-
if (hasType(opts)) {
|
|
83
|
-
return useChildrenTyped(
|
|
84
|
-
parent as AnyBoundNode<Schema> | null | undefined,
|
|
85
|
-
opts as ReadOptions & { type: string },
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
return useChildrenUntyped(
|
|
89
|
-
parent as Node | PathLike | null | undefined,
|
|
90
|
-
opts as ChildrenOptions | undefined,
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function hasType(opts: unknown): opts is { type: string } {
|
|
95
|
-
return (
|
|
96
|
-
typeof opts === 'object' &&
|
|
97
|
-
opts !== null &&
|
|
98
|
-
'type' in opts &&
|
|
99
|
-
(opts as { type?: unknown }).type !== undefined
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// ── internals ────────────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
function isIdle(x: unknown): x is null | undefined {
|
|
106
|
-
return x === null || x === undefined
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function isNode(x: Node | PathLike): x is Node {
|
|
110
|
-
return typeof x === 'object' && x !== null && 'id' in x && 'class' in x && 'path' in x
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** A parent ref anchored on the node id (stable across rename) or the raw path. */
|
|
114
|
-
function refOf(parent: Node | PathLike): PathLike {
|
|
115
|
-
return isNode(parent) ? `@${parent.id}` : parent
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function walkOptsOf(opts?: ChildrenOptions): WalkOpts | undefined {
|
|
119
|
-
if (opts === undefined) return undefined
|
|
120
|
-
const { classes, order, limit } = opts
|
|
121
|
-
if (classes === undefined && order === undefined && limit === undefined) return undefined
|
|
122
|
-
return {
|
|
123
|
-
...(classes !== undefined ? { classes: classes.map((c) => rawOf(c)) } : {}),
|
|
124
|
-
...(order !== undefined ? { order } : {}),
|
|
125
|
-
...(limit !== undefined ? { limit } : {}),
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function childrenShape(
|
|
130
|
-
parent: Node | PathLike,
|
|
131
|
-
opts?: ChildrenOptions,
|
|
132
|
-
): (q: QuerySource) => GatherBuilder {
|
|
133
|
-
const ref = refOf(parent)
|
|
134
|
-
const walk = walkOptsOf(opts)
|
|
135
|
-
return (q) => q.from(ref).children(walk)
|
|
136
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useGraph (API §5) — the memory handle for this subtree (the raw floor plus the
|
|
3
|
-
* memory's optimistic-auto write shorthands). The same scoped memory every
|
|
4
|
-
* graph/schema/nav hook reads.
|
|
5
|
-
*/
|
|
6
|
-
import type { GraphMemory } from '@astrale-os/kernel-client/store'
|
|
7
|
-
|
|
8
|
-
import { useMemory } from '../memory/scope.js'
|
|
9
|
-
|
|
10
|
-
/** The memory for this subtree — the raw floor plus optimistic-auto shorthands (§5). */
|
|
11
|
-
export function useGraph(): GraphMemory {
|
|
12
|
-
return useMemory()
|
|
13
|
-
}
|