@astrale-os/shell-react 0.2.6 → 0.2.8

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.
@@ -0,0 +1,7 @@
1
+ import type { DomainSearchResult } from '@astrale-os/shell';
2
+ import type { ReadState } from '../../graph/memory/read/envelope.js';
3
+ export interface DomainsResult extends ReadState {
4
+ readonly domains: readonly DomainSearchResult[];
5
+ }
6
+ export declare function useDomains(): DomainsResult;
7
+ //# sourceMappingURL=domains.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.hook.d.ts","sourceRoot":"","sources":["../../../src/application/apps/domains.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAI3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAQpE,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAChD;AAED,wBAAgB,UAAU,IAAI,aAAa,CAoB1C"}
@@ -0,0 +1,18 @@
1
+ import { useMemo } from 'react';
2
+ import { useAsyncResource } from '../../graph/async.js';
3
+ import { useShell } from '../../session/shell.hook.js';
4
+ import { isOsPlaneAvailable } from '../user/user.store.js';
5
+ const NO_DOMAINS = [];
6
+ export function useDomains() {
7
+ const shell = useShell();
8
+ const available = isOsPlaneAvailable(shell);
9
+ const result = useAsyncResource(available ? () => shell.apps.searchDomains() : null, NO_DOMAINS, [shell, available]);
10
+ return useMemo(() => ({
11
+ domains: result.data,
12
+ pending: result.pending,
13
+ error: result.error,
14
+ live: false,
15
+ seq: 0,
16
+ refetch: result.refetch,
17
+ }), [result]);
18
+ }
@@ -7,6 +7,8 @@ export { useSpace } from './spaces/space.hook.js';
7
7
  export type { SpaceResult } from './spaces/space.hook.js';
8
8
  export { useApps } from './apps/apps.hook.js';
9
9
  export type { AppsResult } from './apps/apps.hook.js';
10
+ export { useDomains } from './apps/domains.hook.js';
11
+ export type { DomainsResult } from './apps/domains.hook.js';
10
12
  export { useOpenApp } from './apps/open-app.hook.js';
11
13
  export { AppHost } from './apps/app-host.js';
12
14
  export type { AppHostFallbackState, AppHostProps } from './apps/app-host.js';
@@ -14,5 +16,5 @@ export { AppLogo } from './apps/app-logo.js';
14
16
  export type { AppLogoProps } from './apps/app-logo.js';
15
17
  export { useRoles } from './roles.hook.js';
16
18
  export type { RolesResult } from './roles.hook.js';
17
- export type { ApplicationNode, AppSession, RoleNode, SpaceNode, UserNode } from '@astrale-os/shell';
19
+ export type { ApplicationNode, AppSession, DomainSearchResult, RoleNode, SpaceNode, UserNode, } from '@astrale-os/shell';
18
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,YAAY,EACV,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,SAAS,EACT,QAAQ,GACT,MAAM,mBAAmB,CAAA"}
@@ -1,11 +1,13 @@
1
1
  // application — API §12.2. The OS-plane hooks over the shell package's
2
2
  // `shell.user/spaces/apps` namespaces + the window module: useUser, useSpaces,
3
- // useCurrentSpace, useSpace, useApps, useRoles, useOpenApp, AppHost, AppLogo.
3
+ // useCurrentSpace, useSpace, useApps, useDomains, useRoles, useOpenApp,
4
+ // AppHost, AppLogo.
4
5
  export { useUser } from './user/user.hook.js';
5
6
  export { useSpaces } from './spaces/spaces.hook.js';
6
7
  export { useCurrentSpace } from './spaces/current-space.hook.js';
7
8
  export { useSpace } from './spaces/space.hook.js';
8
9
  export { useApps } from './apps/apps.hook.js';
10
+ export { useDomains } from './apps/domains.hook.js';
9
11
  export { useOpenApp } from './apps/open-app.hook.js';
10
12
  export { AppHost } from './apps/app-host.js';
11
13
  export { AppLogo } from './apps/app-logo.js';
@@ -1 +1 @@
1
- {"version":3,"file":"user.store.d.ts","sourceRoot":"","sources":["../../../src/application/user/user.store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,MAAM,SAAS,GACjB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACxC,qFAAqF;GACnF;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7C,eAAO,MAAM,SAAS,2BAAkC,CAAA;AAKxD,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAExD;AAcD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3D;AAED,wFAAwF;AACxF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAoBhD"}
1
+ {"version":3,"file":"user.store.d.ts","sourceRoot":"","sources":["../../../src/application/user/user.store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,MAAM,SAAS,GACjB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACxC,qFAAqF;GACnF;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7C,eAAO,MAAM,SAAS,2BAAkC,CAAA;AAKxD,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAExD;AAeD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3D;AAED,wFAAwF;AACxF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAoBhD"}
@@ -7,7 +7,8 @@ export function isOsPlaneAvailable(shell) {
7
7
  }
8
8
  function osPlaneError(cause) {
9
9
  const detail = cause instanceof Error ? cause.message : String(cause);
10
- return new Error(`The OS plane is unavailable (useUser/useSpaces/useApps): shell.user.me() could not resolve ` +
10
+ return new Error(`The OS plane is unavailable (useUser/useSpaces/useApps/useDomains): ` +
11
+ `shell.user.me() could not resolve ` +
11
12
  `— the workspace/shell domain may not be installed for this identity. (${detail})`);
12
13
  }
13
14
  /**
package/dist/index.d.ts CHANGED
@@ -28,9 +28,9 @@ export { useCloseGuard, useTargetNode, useViewsFor, useWindow, useWindowList, us
28
28
  export type { CloseGuard, CloseVerdict, ViewDescriptor, ViewHostProps, ViewSource, ViewHostHandle, ViewsForResult, WindowListEntry, WindowState, WindowView, } from './window/index.js';
29
29
  export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
30
30
  export type { EmitIntent, IntentCtx, IntentPayload, IntentReply, SendIntent, } from './intents/index.js';
31
- export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useSpace, useSpaces, useUser, } from './application/index.js';
32
- export type { AppHostFallbackState, AppHostProps, AppLogoProps, AppsResult, CurrentSpaceResult, RolesResult, SpaceResult, SpacesResult, } from './application/index.js';
33
- export type { ApplicationNode, AppSession, RoleNode, SpaceNode, UserNode } from '@astrale-os/shell';
31
+ export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useDomains, useSpace, useSpaces, useUser, } from './application/index.js';
32
+ export type { AppHostFallbackState, AppHostProps, AppLogoProps, AppsResult, CurrentSpaceResult, RolesResult, DomainsResult, SpaceResult, SpacesResult, } from './application/index.js';
33
+ export type { ApplicationNode, AppSession, DomainSearchResult, RoleNode, SpaceNode, UserNode, } from '@astrale-os/shell';
34
34
  export type { Action, ReadState, ReadOptions, Windowed } from './graph/index.js';
35
35
  export * from './graph/guards.error.js';
36
36
  export { DESCRIPTION_KEY, NAME_KEY, STATUS_KEY, descriptionOf, nameOf, normalizeRef, statusOf, } from '@astrale-os/kernel-client';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ export { useCloseGuard, useTargetNode, useViewsFor, useWindow, useWindowList, us
27
27
  // ─── intents (§11) ───────────────────────────────────────────────────────────
28
28
  export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
29
29
  // ─── application — the OS plane (§12) ────────────────────────────────────────
30
- export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useSpace, useSpaces, useUser, } from './application/index.js';
30
+ export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useDomains, useSpace, useSpaces, useUser, } from './application/index.js';
31
31
  // ─── error taxonomy (§1.4) — guards + classes, re-exported from kernel-client ─
32
32
  export * from './graph/guards.error.js';
33
33
  // ─── re-exported kernel-client types (one import surface, §0 preamble) ───────
@@ -1 +1 @@
1
- {"version":3,"file":"send-intent.hook.d.ts","sourceRoot":"","sources":["../../src/intents/send-intent.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAWtE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAM/D,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IACzB,oFAAoF;IACpF,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;KAAE,GAChC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;CAClC;AAED,wBAAgB,aAAa,IAAI,UAAU,CAiE1C"}
1
+ {"version":3,"file":"send-intent.hook.d.ts","sourceRoot":"","sources":["../../src/intents/send-intent.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAWtE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAM/D,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IACzB,oFAAoF;IACpF,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;KAAE,GAChC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;CAClC;AAED,wBAAgB,aAAa,IAAI,UAAU,CAiF1C"}
@@ -29,7 +29,7 @@ export function useSendIntent() {
29
29
  const correlationId = crypto.randomUUID();
30
30
  const message = intentMessage(name, payload, correlationId);
31
31
  const pending = pendingRef.current;
32
- return new Promise((resolve) => {
32
+ return new Promise((resolve, reject) => {
33
33
  let done = false;
34
34
  let offReply = NOOP;
35
35
  let offClose = NOOP;
@@ -43,12 +43,25 @@ export function useSendIntent() {
43
43
  pending.delete(onUnmount);
44
44
  resolve(value);
45
45
  }
46
+ function fail(error) {
47
+ if (done)
48
+ return;
49
+ done = true;
50
+ offReply();
51
+ offClose();
52
+ pending.delete(onUnmount);
53
+ reject(error);
54
+ }
46
55
  const onReply = (m) => {
47
56
  if (m.envelope.name !== INTENT_REPLY)
48
57
  return;
49
58
  const reply = m.envelope.payload;
50
59
  if (reply.correlationId !== correlationId)
51
60
  return;
61
+ if (reply.error) {
62
+ fail(new Error(reply.error.message));
63
+ return;
64
+ }
52
65
  settle(reply.result);
53
66
  };
54
67
  pending.add(onUnmount);
@@ -1 +1 @@
1
- {"version":3,"file":"views-for.hook.d.ts","sourceRoot":"","sources":["../../../src/window/hooks/views-for.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAW/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAKjE,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CAC1C;AAiBD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,CAqBpF"}
1
+ {"version":3,"file":"views-for.hook.d.ts","sourceRoot":"","sources":["../../../src/window/hooks/views-for.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAW/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAKjE,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CAC1C;AAID,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,CAqBpF"}
@@ -1,4 +1,3 @@
1
- import { K } from '@astrale-os/kernel-core';
2
1
  /**
3
2
  * useViewsFor (API §10) — "what Views can render this node", as mountable
4
3
  * `ViewDescriptor`s for the open-with menu. Backed one-shot (`live:false`) by the
@@ -7,14 +6,12 @@ import { K } from '@astrale-os/kernel-core';
7
6
  */
8
7
  import { useMemo } from 'react';
9
8
  import { useAsyncResource } from '../../graph/async.js';
10
- import { useKernelClient } from '../../session/kernel-client.hook.js';
11
- /** The `View.resolve` wire address — the qualified static-method slug from the schema. */
12
- const VIEW_RESOLVE_METHOD = K.View.resolve.path.method.raw;
9
+ import { useShell } from '../../session/shell.hook.js';
13
10
  const NO_VIEWS = Object.freeze([]);
14
11
  export function useViewsFor(node) {
15
- const kernel = useKernelClient();
12
+ const shell = useShell();
16
13
  const target = resolvePath(node);
17
- const res = useAsyncResource(target === null ? null : () => resolveViews(kernel, target), NO_VIEWS, [kernel, target]);
14
+ const res = useAsyncResource(target === null ? null : () => resolveViews(shell, target), NO_VIEWS, [shell, target]);
18
15
  return useMemo(() => ({
19
16
  views: res.data,
20
17
  pending: res.pending,
@@ -25,9 +22,9 @@ export function useViewsFor(node) {
25
22
  }), [res.data, res.pending, res.error, res.refetch]);
26
23
  }
27
24
  /** Dispatch `View.resolve` and project its rows to mountable `ViewDescriptor`s. */
28
- async function resolveViews(kernel, node) {
29
- const rows = (await kernel.call(VIEW_RESOLVE_METHOD, { node }));
30
- if (rows === null || rows === undefined || rows.length === 0)
25
+ async function resolveViews(shell, node) {
26
+ const rows = await shell.views.resolve(node);
27
+ if (rows.length === 0)
31
28
  return NO_VIEWS;
32
29
  return rows.map((r) => ({ id: r.id, path: r.path, url: r.url, handshake: r.handshake }));
33
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE5D,+EAA+E;AAC/E,MAAM,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAExE,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpG,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AA6CD,4EAA4E;AAC5E,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAOpD;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGlE;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMlF"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE5D,+EAA+E;AAC/E,MAAM,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAExE,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpG,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AA2ED,4EAA4E;AAC5E,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAOpD;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGlE;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMlF"}
@@ -24,7 +24,7 @@ async function resolveViewRef(kernel, ref, handshakeHint) {
24
24
  if (node === null)
25
25
  throw new Error(`ViewHost: view not found (${toPath(ref)})`);
26
26
  const props = node.props ?? {};
27
- const url = props.url;
27
+ const url = viewUrl(props);
28
28
  if (typeof url !== 'string' || url.length === 0) {
29
29
  throw new Error('ViewHost: resolved view has no url');
30
30
  }
@@ -32,6 +32,37 @@ async function resolveViewRef(kernel, ref, handshakeHint) {
32
32
  const id = node.id ?? slugOfUrl(url);
33
33
  return { url, handshake, functionId: id };
34
34
  }
35
+ /** Resolve both the legacy flat url and the canonical Function binding. */
36
+ function viewUrl(props) {
37
+ if (typeof props.url === 'string' && props.url.length > 0)
38
+ return props.url;
39
+ const direct = remoteUrlOf(props.binding);
40
+ if (direct !== undefined)
41
+ return direct;
42
+ // Raw graph props can be keyed by the property's canonical graph key rather
43
+ // than its local slug. The binding value remains self-describing.
44
+ for (const value of Object.values(props)) {
45
+ const remoteUrl = remoteUrlOf(value);
46
+ if (remoteUrl !== undefined)
47
+ return remoteUrl;
48
+ }
49
+ return undefined;
50
+ }
51
+ function remoteUrlOf(value) {
52
+ let binding = value;
53
+ if (typeof binding === 'string') {
54
+ try {
55
+ binding = JSON.parse(binding);
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ }
61
+ if (binding === null || typeof binding !== 'object')
62
+ return undefined;
63
+ const remoteUrl = binding.remoteUrl;
64
+ return typeof remoteUrl === 'string' && remoteUrl.length > 0 ? remoteUrl : undefined;
65
+ }
35
66
  function normalizeHandshake(value) {
36
67
  return value === 'none' ? 'none' : 'shell';
37
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/shell-react",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Astrale shell-react — the React face of the shell (provider, hooks, view components)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -44,7 +44,7 @@
44
44
  "react-dom": "^19.2.0",
45
45
  "typescript": "~6.0.1-rc",
46
46
  "vitest": "^3.2.4",
47
- "@astrale-os/shell": "0.3.4"
47
+ "@astrale-os/shell": "0.3.6"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@astrale-os/shell": ">=0.2.0 <1.0.0",
@@ -0,0 +1,37 @@
1
+ import type { DomainSearchResult } from '@astrale-os/shell'
2
+
3
+ import { useMemo } from 'react'
4
+
5
+ import type { ReadState } from '../../graph/memory/read/envelope.js'
6
+
7
+ import { useAsyncResource } from '../../graph/async.js'
8
+ import { useShell } from '../../session/shell.hook.js'
9
+ import { isOsPlaneAvailable } from '../user/user.store.js'
10
+
11
+ const NO_DOMAINS: readonly DomainSearchResult[] = []
12
+
13
+ export interface DomainsResult extends ReadState {
14
+ readonly domains: readonly DomainSearchResult[]
15
+ }
16
+
17
+ export function useDomains(): DomainsResult {
18
+ const shell = useShell()
19
+ const available = isOsPlaneAvailable(shell)
20
+ const result = useAsyncResource<readonly DomainSearchResult[]>(
21
+ available ? () => shell.apps.searchDomains() : null,
22
+ NO_DOMAINS,
23
+ [shell, available],
24
+ )
25
+
26
+ return useMemo(
27
+ () => ({
28
+ domains: result.data,
29
+ pending: result.pending,
30
+ error: result.error,
31
+ live: false,
32
+ seq: 0,
33
+ refetch: result.refetch,
34
+ }),
35
+ [result],
36
+ )
37
+ }
@@ -1,6 +1,7 @@
1
1
  // application — API §12.2. The OS-plane hooks over the shell package's
2
2
  // `shell.user/spaces/apps` namespaces + the window module: useUser, useSpaces,
3
- // useCurrentSpace, useSpace, useApps, useRoles, useOpenApp, AppHost, AppLogo.
3
+ // useCurrentSpace, useSpace, useApps, useDomains, useRoles, useOpenApp,
4
+ // AppHost, AppLogo.
4
5
  export { useUser } from './user/user.hook.js'
5
6
  export { useSpaces } from './spaces/spaces.hook.js'
6
7
  export type { SpacesResult } from './spaces/spaces.hook.js'
@@ -10,6 +11,8 @@ export { useSpace } from './spaces/space.hook.js'
10
11
  export type { SpaceResult } from './spaces/space.hook.js'
11
12
  export { useApps } from './apps/apps.hook.js'
12
13
  export type { AppsResult } from './apps/apps.hook.js'
14
+ export { useDomains } from './apps/domains.hook.js'
15
+ export type { DomainsResult } from './apps/domains.hook.js'
13
16
  export { useOpenApp } from './apps/open-app.hook.js'
14
17
  export { AppHost } from './apps/app-host.js'
15
18
  export type { AppHostFallbackState, AppHostProps } from './apps/app-host.js'
@@ -19,4 +22,11 @@ export { useRoles } from './roles.hook.js'
19
22
  export type { RolesResult } from './roles.hook.js'
20
23
 
21
24
  // The OS node/session types (from the shell package, single import surface).
22
- export type { ApplicationNode, AppSession, RoleNode, SpaceNode, UserNode } from '@astrale-os/shell'
25
+ export type {
26
+ ApplicationNode,
27
+ AppSession,
28
+ DomainSearchResult,
29
+ RoleNode,
30
+ SpaceNode,
31
+ UserNode,
32
+ } from '@astrale-os/shell'
@@ -31,7 +31,8 @@ interface UserSurface {
31
31
  function osPlaneError(cause: unknown): Error {
32
32
  const detail = cause instanceof Error ? cause.message : String(cause)
33
33
  return new Error(
34
- `The OS plane is unavailable (useUser/useSpaces/useApps): shell.user.me() could not resolve ` +
34
+ `The OS plane is unavailable (useUser/useSpaces/useApps/useDomains): ` +
35
+ `shell.user.me() could not resolve ` +
35
36
  `— the workspace/shell domain may not be installed for this identity. (${detail})`,
36
37
  )
37
38
  }
package/src/index.ts CHANGED
@@ -134,6 +134,7 @@ export {
134
134
  useCurrentSpace,
135
135
  useOpenApp,
136
136
  useRoles,
137
+ useDomains,
137
138
  useSpace,
138
139
  useSpaces,
139
140
  useUser,
@@ -145,11 +146,19 @@ export type {
145
146
  AppsResult,
146
147
  CurrentSpaceResult,
147
148
  RolesResult,
149
+ DomainsResult,
148
150
  SpaceResult,
149
151
  SpacesResult,
150
152
  } from './application/index.js'
151
153
  // OS node/session types (from the shell package, single import surface).
152
- export type { ApplicationNode, AppSession, RoleNode, SpaceNode, UserNode } from '@astrale-os/shell'
154
+ export type {
155
+ ApplicationNode,
156
+ AppSession,
157
+ DomainSearchResult,
158
+ RoleNode,
159
+ SpaceNode,
160
+ UserNode,
161
+ } from '@astrale-os/shell'
153
162
 
154
163
  // ─── shared envelopes (§1) ───────────────────────────────────────────────────
155
164
  export type { Action, ReadState, ReadOptions, Windowed } from './graph/index.js'
@@ -51,7 +51,7 @@ export function useSendIntent(): SendIntent {
51
51
  const message = intentMessage(name, payload, correlationId)
52
52
  const pending = pendingRef.current
53
53
 
54
- return new Promise<IntentReply<K> | void>((resolve) => {
54
+ return new Promise<IntentReply<K> | void>((resolve, reject) => {
55
55
  let done = false
56
56
  let offReply = NOOP
57
57
  let offClose = NOOP
@@ -64,10 +64,26 @@ export function useSendIntent(): SendIntent {
64
64
  pending.delete(onUnmount)
65
65
  resolve(value)
66
66
  }
67
+ function fail(error: Error): void {
68
+ if (done) return
69
+ done = true
70
+ offReply()
71
+ offClose()
72
+ pending.delete(onUnmount)
73
+ reject(error)
74
+ }
67
75
  const onReply = (m: IntentMessage): void => {
68
76
  if (m.envelope.name !== INTENT_REPLY) return
69
- const reply = m.envelope.payload as { correlationId: string; result: unknown }
77
+ const reply = m.envelope.payload as {
78
+ correlationId: string
79
+ result?: unknown
80
+ error?: { message: string }
81
+ }
70
82
  if (reply.correlationId !== correlationId) return
83
+ if (reply.error) {
84
+ fail(new Error(reply.error.message))
85
+ return
86
+ }
71
87
  settle(reply.result as IntentReply<K>)
72
88
  }
73
89
 
@@ -1,6 +1,6 @@
1
1
  import type { PathLike } from '@astrale-os/kernel-client/graph'
2
+ import type { Shell } from '@astrale-os/shell'
2
3
 
3
- import { K } from '@astrale-os/kernel-core'
4
4
  /**
5
5
  * useViewsFor (API §10) — "what Views can render this node", as mountable
6
6
  * `ViewDescriptor`s for the open-with menu. Backed one-shot (`live:false`) by the
@@ -13,35 +13,22 @@ import type { ReadState } from '../../graph/memory/read/envelope.js'
13
13
  import type { Node, ViewDescriptor } from '../lifecycle/mount.js'
14
14
 
15
15
  import { useAsyncResource } from '../../graph/async.js'
16
- import { useKernelClient } from '../../session/kernel-client.hook.js'
16
+ import { useShell } from '../../session/shell.hook.js'
17
17
 
18
18
  export interface ViewsForResult extends ReadState {
19
19
  readonly views: readonly ViewDescriptor[]
20
20
  }
21
21
 
22
- /** The `View.resolve` wire address — the qualified static-method slug from the schema. */
23
- const VIEW_RESOLVE_METHOD = K.View.resolve.path.method.raw
24
-
25
- /** The kernel `View.resolve` row shape (id/path/url/name?/handshake?/origin). */
26
- interface ViewOut {
27
- readonly id: string
28
- readonly path: string
29
- readonly url: string
30
- readonly name?: string
31
- readonly handshake?: 'shell' | 'none'
32
- readonly origin: 'self' | 'class'
33
- }
34
-
35
22
  const NO_VIEWS: readonly ViewDescriptor[] = Object.freeze([])
36
23
 
37
24
  export function useViewsFor(node: Node | PathLike | null | undefined): ViewsForResult {
38
- const kernel = useKernelClient()
25
+ const shell = useShell()
39
26
  const target = resolvePath(node)
40
27
 
41
28
  const res = useAsyncResource<readonly ViewDescriptor[]>(
42
- target === null ? null : () => resolveViews(kernel, target),
29
+ target === null ? null : () => resolveViews(shell, target),
43
30
  NO_VIEWS,
44
- [kernel, target],
31
+ [shell, target],
45
32
  )
46
33
 
47
34
  return useMemo<ViewsForResult>(
@@ -58,12 +45,9 @@ export function useViewsFor(node: Node | PathLike | null | undefined): ViewsForR
58
45
  }
59
46
 
60
47
  /** Dispatch `View.resolve` and project its rows to mountable `ViewDescriptor`s. */
61
- async function resolveViews(
62
- kernel: { call(method: string, params: unknown): Promise<unknown> },
63
- node: string,
64
- ): Promise<readonly ViewDescriptor[]> {
65
- const rows = (await kernel.call(VIEW_RESOLVE_METHOD, { node })) as ViewOut[] | null | undefined
66
- if (rows === null || rows === undefined || rows.length === 0) return NO_VIEWS
48
+ async function resolveViews(shell: Shell, node: string): Promise<readonly ViewDescriptor[]> {
49
+ const rows = await shell.views.resolve(node)
50
+ if (rows.length === 0) return NO_VIEWS
67
51
  return rows.map((r) => ({ id: r.id, path: r.path, url: r.url, handshake: r.handshake }))
68
52
  }
69
53
 
@@ -62,7 +62,7 @@ async function resolveViewRef(
62
62
  const node = await kernel.get(toPath(ref))
63
63
  if (node === null) throw new Error(`ViewHost: view not found (${toPath(ref)})`)
64
64
  const props = (node as { id?: string; props?: Record<string, unknown> }).props ?? {}
65
- const url = props.url
65
+ const url = viewUrl(props)
66
66
  if (typeof url !== 'string' || url.length === 0) {
67
67
  throw new Error('ViewHost: resolved view has no url')
68
68
  }
@@ -71,6 +71,36 @@ async function resolveViewRef(
71
71
  return { url, handshake, functionId: id }
72
72
  }
73
73
 
74
+ /** Resolve both the legacy flat url and the canonical Function binding. */
75
+ function viewUrl(props: Record<string, unknown>): string | undefined {
76
+ if (typeof props.url === 'string' && props.url.length > 0) return props.url
77
+
78
+ const direct = remoteUrlOf(props.binding)
79
+ if (direct !== undefined) return direct
80
+
81
+ // Raw graph props can be keyed by the property's canonical graph key rather
82
+ // than its local slug. The binding value remains self-describing.
83
+ for (const value of Object.values(props)) {
84
+ const remoteUrl = remoteUrlOf(value)
85
+ if (remoteUrl !== undefined) return remoteUrl
86
+ }
87
+ return undefined
88
+ }
89
+
90
+ function remoteUrlOf(value: unknown): string | undefined {
91
+ let binding = value
92
+ if (typeof binding === 'string') {
93
+ try {
94
+ binding = JSON.parse(binding)
95
+ } catch {
96
+ return undefined
97
+ }
98
+ }
99
+ if (binding === null || typeof binding !== 'object') return undefined
100
+ const remoteUrl = (binding as { remoteUrl?: unknown }).remoteUrl
101
+ return typeof remoteUrl === 'string' && remoteUrl.length > 0 ? remoteUrl : undefined
102
+ }
103
+
74
104
  function normalizeHandshake(value: unknown): 'shell' | 'none' {
75
105
  return value === 'none' ? 'none' : 'shell'
76
106
  }