@astrale-os/shell-react 0.2.5 → 0.2.6
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/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/intents/emit-intent.hook.d.ts +17 -0
- package/dist/intents/emit-intent.hook.d.ts.map +1 -0
- package/dist/intents/emit-intent.hook.js +22 -0
- package/dist/intents/index.d.ts +2 -0
- package/dist/intents/index.d.ts.map +1 -1
- package/dist/intents/index.js +1 -0
- package/dist/intents/resolve-intent-target.d.ts +12 -0
- package/dist/intents/resolve-intent-target.d.ts.map +1 -0
- package/dist/intents/resolve-intent-target.js +13 -0
- package/dist/intents/send-intent.hook.d.ts.map +1 -1
- package/dist/intents/send-intent.hook.js +2 -14
- package/package.json +1 -1
- package/src/index.ts +8 -2
- package/src/intents/emit-intent.hook.ts +42 -0
- package/src/intents/index.ts +2 -0
- package/src/intents/resolve-intent-target.ts +20 -0
- package/src/intents/send-intent.hook.ts +3 -21
package/dist/index.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export { SelectionScope, useSelection } from './selection/index.js';
|
|
|
26
26
|
export type { Selection, SelectionScopeProps } from './selection/index.js';
|
|
27
27
|
export { useCloseGuard, useTargetNode, useViewsFor, useWindow, useWindowList, useWindows, ViewHost, ViewStage, } from './window/index.js';
|
|
28
28
|
export type { CloseGuard, CloseVerdict, ViewDescriptor, ViewHostProps, ViewSource, ViewHostHandle, ViewsForResult, WindowListEntry, WindowState, WindowView, } from './window/index.js';
|
|
29
|
-
export { useIntent, useSendIntent } from './intents/index.js';
|
|
30
|
-
export type { IntentCtx, IntentPayload, IntentReply, SendIntent } from './intents/index.js';
|
|
29
|
+
export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
|
|
30
|
+
export type { EmitIntent, IntentCtx, IntentPayload, IntentReply, SendIntent, } from './intents/index.js';
|
|
31
31
|
export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useSpace, useSpaces, useUser, } from './application/index.js';
|
|
32
32
|
export type { AppHostFallbackState, AppHostProps, AppLogoProps, AppsResult, CurrentSpaceResult, RolesResult, SpaceResult, SpacesResult, } from './application/index.js';
|
|
33
33
|
export type { ApplicationNode, AppSession, RoleNode, SpaceNode, UserNode } from '@astrale-os/shell';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAChG,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACjE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAKjD,OAAO,EACL,OAAO,EACP,WAAW,EACX,QAAQ,EACR,OAAO,EACP,SAAS,EACT,OAAO,EACP,QAAQ,EACR,SAAS,GACV,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,UAAU,EACV,IAAI,EACJ,UAAU,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGhF,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/F,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,SAAS,EACT,QAAQ,EACR,kBAAkB,GACnB,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnE,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAG1E,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,SAAS,GACV,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ export { SelectionScope, useSelection } from './selection/index.js';
|
|
|
25
25
|
// ─── window (§10) ────────────────────────────────────────────────────────────
|
|
26
26
|
export { useCloseGuard, useTargetNode, useViewsFor, useWindow, useWindowList, useWindows, ViewHost, ViewStage, } from './window/index.js';
|
|
27
27
|
// ─── intents (§11) ───────────────────────────────────────────────────────────
|
|
28
|
-
export { useIntent, useSendIntent } from './intents/index.js';
|
|
28
|
+
export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
|
|
29
29
|
// ─── application — the OS plane (§12) ────────────────────────────────────────
|
|
30
30
|
export { AppHost, AppLogo, useApps, useCurrentSpace, useOpenApp, useRoles, useSpace, useSpaces, useUser, } from './application/index.js';
|
|
31
31
|
// ─── error taxonomy (§1.4) — guards + classes, re-exported from kernel-client ─
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IntentRegistry } from '@astrale-os/shell';
|
|
2
|
+
import type { IntentPayload } from './envelope.js';
|
|
3
|
+
/** Fire-and-forget intent sender returned by {@link useEmitIntent}. */
|
|
4
|
+
export interface EmitIntent {
|
|
5
|
+
<K extends keyof IntentRegistry>(name: K, payload: IntentPayload<K>,
|
|
6
|
+
/** `to`: `'parent'` (reserved) or a child windowId. Default: the parent, if any. */
|
|
7
|
+
opts?: {
|
|
8
|
+
to?: 'parent' | string;
|
|
9
|
+
}): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Return a stable sender for intents that do not need a reply. Emitted messages
|
|
13
|
+
* carry no correlation id, so listeners can handle navigation and notifications
|
|
14
|
+
* without retaining a pending request.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useEmitIntent(): EmitIntent;
|
|
17
|
+
//# sourceMappingURL=emit-intent.hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-intent.hook.d.ts","sourceRoot":"","sources":["../../src/intents/emit-intent.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAIvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAMlD,uEAAuE;AACvE,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,IAAI,CAAA;CACR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAgB1C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useShell } from '../session/shell.hook.js';
|
|
3
|
+
import { intentMessage } from './envelope.js';
|
|
4
|
+
import { resolveIntentTarget } from './resolve-intent-target.js';
|
|
5
|
+
/**
|
|
6
|
+
* Return a stable sender for intents that do not need a reply. Emitted messages
|
|
7
|
+
* carry no correlation id, so listeners can handle navigation and notifications
|
|
8
|
+
* without retaining a pending request.
|
|
9
|
+
*/
|
|
10
|
+
export function useEmitIntent() {
|
|
11
|
+
const shell = useShell();
|
|
12
|
+
return useCallback((name, payload, opts) => {
|
|
13
|
+
const target = resolveIntentTarget(shell, opts?.to);
|
|
14
|
+
if (target.kind === 'invalid')
|
|
15
|
+
throw new Error(`useEmitIntent: ${target.reason}`);
|
|
16
|
+
const message = intentMessage(name, payload);
|
|
17
|
+
if (target.kind === 'parent')
|
|
18
|
+
shell.parent.send(message);
|
|
19
|
+
else
|
|
20
|
+
shell.children.send(target.windowId, message);
|
|
21
|
+
}, [shell]);
|
|
22
|
+
}
|
package/dist/intents/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { useIntent } from './listen-intent.hook.js';
|
|
2
2
|
export type { IntentCtx } from './listen-intent.hook.js';
|
|
3
|
+
export { useEmitIntent } from './emit-intent.hook.js';
|
|
4
|
+
export type { EmitIntent } from './emit-intent.hook.js';
|
|
3
5
|
export { useSendIntent } from './send-intent.hook.js';
|
|
4
6
|
export type { SendIntent } from './send-intent.hook.js';
|
|
5
7
|
export type { IntentPayload, IntentReply } from './envelope.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/intents/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/intents/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/intents/index.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Shell } from '@astrale-os/shell';
|
|
2
|
+
export type IntentTarget = {
|
|
3
|
+
readonly kind: 'parent';
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: 'child';
|
|
6
|
+
readonly windowId: string;
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: 'invalid';
|
|
9
|
+
readonly reason: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function resolveIntentTarget(shell: Shell, to: string | undefined): IntentTarget;
|
|
12
|
+
//# sourceMappingURL=resolve-intent-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-intent-target.d.ts","sourceRoot":"","sources":["../../src/intents/resolve-intent-target.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAYtF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function resolveIntentTarget(shell, to) {
|
|
2
|
+
if (to === undefined) {
|
|
3
|
+
return shell.parent !== null
|
|
4
|
+
? { kind: 'parent' }
|
|
5
|
+
: { kind: 'invalid', reason: 'no target — pass opts.to (a child windowId) from a root shell' };
|
|
6
|
+
}
|
|
7
|
+
if (to === 'parent') {
|
|
8
|
+
return shell.parent !== null
|
|
9
|
+
? { kind: 'parent' }
|
|
10
|
+
: { kind: 'invalid', reason: "opts.to 'parent' but this shell has no parent channel" };
|
|
11
|
+
}
|
|
12
|
+
return { kind: 'child', windowId: to };
|
|
13
|
+
}
|
|
@@ -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,
|
|
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"}
|
|
@@ -8,19 +8,7 @@
|
|
|
8
8
|
import { useCallback, useEffect, useRef } from 'react';
|
|
9
9
|
import { useShell } from '../session/shell.hook.js';
|
|
10
10
|
import { INTENT_REPLY, NOOP, intentMessage } from './envelope.js';
|
|
11
|
-
|
|
12
|
-
if (to === undefined) {
|
|
13
|
-
return shell.parent !== null
|
|
14
|
-
? { kind: 'parent' }
|
|
15
|
-
: { kind: 'invalid', reason: 'no target — pass opts.to (a child windowId) from a root shell' };
|
|
16
|
-
}
|
|
17
|
-
if (to === 'parent') {
|
|
18
|
-
return shell.parent !== null
|
|
19
|
-
? { kind: 'parent' }
|
|
20
|
-
: { kind: 'invalid', reason: "opts.to 'parent' but this shell has no parent channel" };
|
|
21
|
-
}
|
|
22
|
-
return { kind: 'child', windowId: to };
|
|
23
|
-
}
|
|
11
|
+
import { resolveIntentTarget } from './resolve-intent-target.js';
|
|
24
12
|
export function useSendIntent() {
|
|
25
13
|
const shell = useShell();
|
|
26
14
|
// Unmount settlers for in-flight sends, so a pending reply resolves on teardown.
|
|
@@ -34,7 +22,7 @@ export function useSendIntent() {
|
|
|
34
22
|
};
|
|
35
23
|
}, []);
|
|
36
24
|
return useCallback((name, payload, opts) => {
|
|
37
|
-
const target =
|
|
25
|
+
const target = resolveIntentTarget(shell, opts?.to);
|
|
38
26
|
if (target.kind === 'invalid') {
|
|
39
27
|
return Promise.reject(new Error(`useSendIntent: ${target.reason}`));
|
|
40
28
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -117,8 +117,14 @@ export type {
|
|
|
117
117
|
} from './window/index.js'
|
|
118
118
|
|
|
119
119
|
// ─── intents (§11) ───────────────────────────────────────────────────────────
|
|
120
|
-
export { useIntent, useSendIntent } from './intents/index.js'
|
|
121
|
-
export type {
|
|
120
|
+
export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js'
|
|
121
|
+
export type {
|
|
122
|
+
EmitIntent,
|
|
123
|
+
IntentCtx,
|
|
124
|
+
IntentPayload,
|
|
125
|
+
IntentReply,
|
|
126
|
+
SendIntent,
|
|
127
|
+
} from './intents/index.js'
|
|
122
128
|
|
|
123
129
|
// ─── application — the OS plane (§12) ────────────────────────────────────────
|
|
124
130
|
export {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IntentRegistry } from '@astrale-os/shell'
|
|
2
|
+
|
|
3
|
+
import { useCallback } from 'react'
|
|
4
|
+
|
|
5
|
+
import type { IntentPayload } from './envelope.js'
|
|
6
|
+
|
|
7
|
+
import { useShell } from '../session/shell.hook.js'
|
|
8
|
+
import { intentMessage } from './envelope.js'
|
|
9
|
+
import { resolveIntentTarget } from './resolve-intent-target.js'
|
|
10
|
+
|
|
11
|
+
/** Fire-and-forget intent sender returned by {@link useEmitIntent}. */
|
|
12
|
+
export interface EmitIntent {
|
|
13
|
+
<K extends keyof IntentRegistry>(
|
|
14
|
+
name: K,
|
|
15
|
+
payload: IntentPayload<K>,
|
|
16
|
+
/** `to`: `'parent'` (reserved) or a child windowId. Default: the parent, if any. */
|
|
17
|
+
opts?: { to?: 'parent' | string },
|
|
18
|
+
): void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Return a stable sender for intents that do not need a reply. Emitted messages
|
|
23
|
+
* carry no correlation id, so listeners can handle navigation and notifications
|
|
24
|
+
* without retaining a pending request.
|
|
25
|
+
*/
|
|
26
|
+
export function useEmitIntent(): EmitIntent {
|
|
27
|
+
const shell = useShell()
|
|
28
|
+
return useCallback(
|
|
29
|
+
<K extends keyof IntentRegistry>(
|
|
30
|
+
name: K,
|
|
31
|
+
payload: IntentPayload<K>,
|
|
32
|
+
opts?: { to?: 'parent' | string },
|
|
33
|
+
): void => {
|
|
34
|
+
const target = resolveIntentTarget(shell, opts?.to)
|
|
35
|
+
if (target.kind === 'invalid') throw new Error(`useEmitIntent: ${target.reason}`)
|
|
36
|
+
const message = intentMessage(name, payload)
|
|
37
|
+
if (target.kind === 'parent') shell.parent!.send(message)
|
|
38
|
+
else shell.children.send(target.windowId, message)
|
|
39
|
+
},
|
|
40
|
+
[shell],
|
|
41
|
+
)
|
|
42
|
+
}
|
package/src/intents/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// intents — API §11 (useIntent, useSendIntent). See SHELL_REACT_API.md.
|
|
2
2
|
export { useIntent } from './listen-intent.hook.js'
|
|
3
3
|
export type { IntentCtx } from './listen-intent.hook.js'
|
|
4
|
+
export { useEmitIntent } from './emit-intent.hook.js'
|
|
5
|
+
export type { EmitIntent } from './emit-intent.hook.js'
|
|
4
6
|
export { useSendIntent } from './send-intent.hook.js'
|
|
5
7
|
export type { SendIntent } from './send-intent.hook.js'
|
|
6
8
|
export type { IntentPayload, IntentReply } from './envelope.js'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Shell } from '@astrale-os/shell'
|
|
2
|
+
|
|
3
|
+
export type IntentTarget =
|
|
4
|
+
| { readonly kind: 'parent' }
|
|
5
|
+
| { readonly kind: 'child'; readonly windowId: string }
|
|
6
|
+
| { readonly kind: 'invalid'; readonly reason: string }
|
|
7
|
+
|
|
8
|
+
export function resolveIntentTarget(shell: Shell, to: string | undefined): IntentTarget {
|
|
9
|
+
if (to === undefined) {
|
|
10
|
+
return shell.parent !== null
|
|
11
|
+
? { kind: 'parent' }
|
|
12
|
+
: { kind: 'invalid', reason: 'no target — pass opts.to (a child windowId) from a root shell' }
|
|
13
|
+
}
|
|
14
|
+
if (to === 'parent') {
|
|
15
|
+
return shell.parent !== null
|
|
16
|
+
? { kind: 'parent' }
|
|
17
|
+
: { kind: 'invalid', reason: "opts.to 'parent' but this shell has no parent channel" }
|
|
18
|
+
}
|
|
19
|
+
return { kind: 'child', windowId: to }
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IntentMessage, IntentRegistry
|
|
1
|
+
import type { IntentMessage, IntentRegistry } from '@astrale-os/shell'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* useSendIntent (API §11) — a stable typed sender. Each call attaches a
|
|
@@ -13,6 +13,7 @@ import type { IntentPayload, IntentReply } from './envelope.js'
|
|
|
13
13
|
|
|
14
14
|
import { useShell } from '../session/shell.hook.js'
|
|
15
15
|
import { INTENT_REPLY, NOOP, intentMessage } from './envelope.js'
|
|
16
|
+
import { resolveIntentTarget } from './resolve-intent-target.js'
|
|
16
17
|
|
|
17
18
|
/** The typed sender returned by {@link useSendIntent}. */
|
|
18
19
|
export interface SendIntent {
|
|
@@ -24,25 +25,6 @@ export interface SendIntent {
|
|
|
24
25
|
): Promise<IntentReply<K> | void>
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
type Target =
|
|
28
|
-
| { readonly kind: 'parent' }
|
|
29
|
-
| { readonly kind: 'child'; readonly windowId: string }
|
|
30
|
-
| { readonly kind: 'invalid'; readonly reason: string }
|
|
31
|
-
|
|
32
|
-
function resolveTarget(shell: Shell, to: string | undefined): Target {
|
|
33
|
-
if (to === undefined) {
|
|
34
|
-
return shell.parent !== null
|
|
35
|
-
? { kind: 'parent' }
|
|
36
|
-
: { kind: 'invalid', reason: 'no target — pass opts.to (a child windowId) from a root shell' }
|
|
37
|
-
}
|
|
38
|
-
if (to === 'parent') {
|
|
39
|
-
return shell.parent !== null
|
|
40
|
-
? { kind: 'parent' }
|
|
41
|
-
: { kind: 'invalid', reason: "opts.to 'parent' but this shell has no parent channel" }
|
|
42
|
-
}
|
|
43
|
-
return { kind: 'child', windowId: to }
|
|
44
|
-
}
|
|
45
|
-
|
|
46
28
|
export function useSendIntent(): SendIntent {
|
|
47
29
|
const shell = useShell()
|
|
48
30
|
// Unmount settlers for in-flight sends, so a pending reply resolves on teardown.
|
|
@@ -61,7 +43,7 @@ export function useSendIntent(): SendIntent {
|
|
|
61
43
|
payload: IntentPayload<K>,
|
|
62
44
|
opts?: { to?: 'parent' | string },
|
|
63
45
|
): Promise<IntentReply<K> | void> => {
|
|
64
|
-
const target =
|
|
46
|
+
const target = resolveIntentTarget(shell, opts?.to)
|
|
65
47
|
if (target.kind === 'invalid') {
|
|
66
48
|
return Promise.reject(new Error(`useSendIntent: ${target.reason}`))
|
|
67
49
|
}
|