@astrale-os/shell-react 0.2.10-beta.3 → 0.3.1

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.
Files changed (115) hide show
  1. package/dist/application/apps/app-host.d.ts +5 -5
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +18 -39
  4. package/dist/application/apps/apps.hook.d.ts +4 -11
  5. package/dist/application/apps/apps.hook.d.ts.map +1 -1
  6. package/dist/application/apps/apps.hook.js +9 -49
  7. package/dist/application/apps/open-app.hook.d.ts +4 -7
  8. package/dist/application/apps/open-app.hook.d.ts.map +1 -1
  9. package/dist/application/apps/open-app.hook.js +2 -2
  10. package/dist/application/index.d.ts +1 -3
  11. package/dist/application/index.d.ts.map +1 -1
  12. package/dist/application/index.js +1 -2
  13. package/dist/application/spaces/space.hook.d.ts.map +1 -1
  14. package/dist/application/spaces/space.hook.js +4 -1
  15. package/dist/auth/act-as.context.d.ts +1 -1
  16. package/dist/auth/act-as.context.d.ts.map +1 -1
  17. package/dist/auth/auth.hook.d.ts +1 -1
  18. package/dist/auth/auth.hook.d.ts.map +1 -1
  19. package/dist/auth/can.hook.d.ts +2 -2
  20. package/dist/auth/can.hook.d.ts.map +1 -1
  21. package/dist/auth/self.hook.d.ts +1 -1
  22. package/dist/auth/self.hook.d.ts.map +1 -1
  23. package/dist/components/can.d.ts +2 -2
  24. package/dist/components/can.d.ts.map +1 -1
  25. package/dist/graph/call/call.hook.d.ts +2 -2
  26. package/dist/graph/call/call.hook.d.ts.map +1 -1
  27. package/dist/graph/call/stream.hook.d.ts +2 -2
  28. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  29. package/dist/graph/graph.context.d.ts +1 -1
  30. package/dist/graph/graph.context.d.ts.map +1 -1
  31. package/dist/graph/guards.error.d.ts +4 -4
  32. package/dist/graph/guards.error.d.ts.map +1 -1
  33. package/dist/graph/guards.error.js +4 -4
  34. package/dist/graph/query-definition.hook.d.ts +1 -2
  35. package/dist/graph/query-definition.hook.d.ts.map +1 -1
  36. package/dist/graph/query-definition.hook.js +4 -10
  37. package/dist/graph/resource.d.ts +1 -1
  38. package/dist/graph/resource.d.ts.map +1 -1
  39. package/dist/graph/store.d.ts +2 -2
  40. package/dist/graph/store.d.ts.map +1 -1
  41. package/dist/graph/store.js +1 -1
  42. package/dist/index.d.ts +5 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +1 -1
  45. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  46. package/dist/navigation/adapters/url.adapter.js +2 -5
  47. package/dist/navigation/codec.d.ts.map +1 -1
  48. package/dist/navigation/codec.js +1 -7
  49. package/dist/navigation/link.js +1 -1
  50. package/dist/navigation/scope.context.d.ts +1 -1
  51. package/dist/navigation/scope.context.d.ts.map +1 -1
  52. package/dist/navigation/scope.context.js +3 -6
  53. package/dist/navigation/snapshot.d.ts +1 -1
  54. package/dist/navigation/snapshot.d.ts.map +1 -1
  55. package/dist/navigation/snapshot.js +2 -8
  56. package/dist/navigation/view-key.d.ts +3 -0
  57. package/dist/navigation/view-key.d.ts.map +1 -0
  58. package/dist/navigation/view-key.js +8 -0
  59. package/dist/schema/action.hook.d.ts +11 -7
  60. package/dist/schema/action.hook.d.ts.map +1 -1
  61. package/dist/schema/action.hook.js +11 -6
  62. package/dist/schema/domain.hook.js +12 -13
  63. package/dist/schema/kernel.hook.d.ts +1 -1
  64. package/dist/schema/kernel.hook.d.ts.map +1 -1
  65. package/dist/schema/kernel.hook.js +1 -1
  66. package/dist/schema/mutation.hook.d.ts +2 -2
  67. package/dist/schema/mutation.hook.d.ts.map +1 -1
  68. package/dist/schema/mutation.hook.js +6 -5
  69. package/dist/schema/object.hook.d.ts +3 -6
  70. package/dist/schema/object.hook.d.ts.map +1 -1
  71. package/dist/schema/object.hook.js +4 -5
  72. package/dist/schema/relation.hook.d.ts +29 -19
  73. package/dist/schema/relation.hook.d.ts.map +1 -1
  74. package/dist/schema/relation.hook.js +45 -63
  75. package/dist/selection/live.d.ts.map +1 -1
  76. package/dist/selection/live.js +1 -2
  77. package/dist/session/session.context.d.ts +3 -4
  78. package/dist/session/session.context.d.ts.map +1 -1
  79. package/package.json +4 -14
  80. package/src/application/apps/app-host.tsx +22 -52
  81. package/src/application/apps/apps.hook.ts +14 -64
  82. package/src/application/apps/open-app.hook.ts +5 -10
  83. package/src/application/index.ts +2 -12
  84. package/src/application/spaces/space.hook.ts +6 -1
  85. package/src/auth/act-as.context.tsx +1 -1
  86. package/src/auth/auth.hook.ts +1 -1
  87. package/src/auth/can.hook.ts +3 -3
  88. package/src/auth/self.hook.ts +1 -1
  89. package/src/components/can.tsx +2 -2
  90. package/src/graph/call/call.hook.ts +2 -2
  91. package/src/graph/call/stream.hook.ts +2 -2
  92. package/src/graph/graph.context.ts +1 -1
  93. package/src/graph/guards.error.ts +4 -4
  94. package/src/graph/query-definition.hook.ts +13 -23
  95. package/src/graph/resource.ts +1 -1
  96. package/src/graph/store.ts +3 -3
  97. package/src/index.ts +3 -7
  98. package/src/navigation/adapters/url.adapter.ts +3 -4
  99. package/src/navigation/codec.ts +1 -7
  100. package/src/navigation/link.tsx +1 -1
  101. package/src/navigation/scope.context.tsx +5 -6
  102. package/src/navigation/snapshot.ts +4 -9
  103. package/src/navigation/view-key.ts +11 -0
  104. package/src/schema/action.hook.ts +45 -28
  105. package/src/schema/domain.hook.ts +9 -10
  106. package/src/schema/kernel.hook.ts +1 -1
  107. package/src/schema/mutation.hook.ts +13 -9
  108. package/src/schema/object.hook.ts +10 -18
  109. package/src/schema/relation.hook.ts +127 -145
  110. package/src/selection/live.ts +1 -2
  111. package/src/session/session.context.ts +3 -4
  112. package/dist/application/apps/domains.hook.d.ts +0 -7
  113. package/dist/application/apps/domains.hook.d.ts.map +0 -1
  114. package/dist/application/apps/domains.hook.js +0 -18
  115. package/src/application/apps/domains.hook.ts +0 -37
@@ -1 +1 @@
1
- {"version":3,"file":"relation.hook.d.ts","sourceRoot":"","sources":["../../src/schema/relation.hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relation.hook.d.ts","sourceRoot":"","sources":["../../src/schema/relation.hook.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { NodeId } from '@astrale-os/sdk/graph/node';
2
1
  import { Path } from '@astrale-os/sdk/graph/path';
3
2
  import { Query } from '@astrale-os/sdk/query';
3
+ import { ClassKey } from '@astrale-os/sdk/schema';
4
4
  import { useCallback, useMemo } from 'react';
5
5
  import { useStoreResource } from '../graph/resource.js';
6
6
  import { bindingFor } from './domain.hook.js';
@@ -13,28 +13,23 @@ export class RelationUnavailableError extends Error {
13
13
  this.name = 'RelationUnavailableError';
14
14
  }
15
15
  }
16
- /** Traverse one exact rich Edge definition with endpoint and cardinality inference. */
17
- export function useRelation(definition, source, options) {
18
- const binding = bindingFor(definition);
19
- if (source !== null && source !== undefined) {
20
- admitSource(binding, definition, options.from, source);
21
- }
22
- admitRelatedDefinition(binding, definition, options.from, options.to);
23
- const path = source === null || source === undefined ? null : Path.id(NodeId(source.id));
16
+ /** Traverse one directed resolved Edge Class and bind the selected opposite Nodes. */
17
+ export function useRelation(relation, source, options) {
18
+ const binding = bindingFor(relation);
19
+ if (source !== null && source !== undefined)
20
+ admitSource(binding, relation, options.from, source);
21
+ admitRelatedDefinition(binding, relation, options.from, options.to);
22
+ const path = source === null || source === undefined ? null : Path.id(source.id);
24
23
  const query = useMemo(() => {
25
24
  if (path === null)
26
25
  return null;
27
- const root = Query.from({ kind: 'node', paths: [path], binding: 'relation_source' });
28
- const admitted = root.filter({ satisfies: source.$.definition.schemaRef });
29
- const expanded = admitted.expand({
30
- via: [definition.schemaRef],
26
+ const expanded = Query.from({ nodes: [path] }).expand({
27
+ via: [relation],
31
28
  direction: options.from === 'source' ? 'outgoing' : 'incoming',
32
29
  });
33
- return expanded
34
- .filter({ satisfies: options.to.schemaRef })
35
- .select({ kind: 'graph', binding: expanded.node });
36
- }, [definition, options.from, options.to, path?.raw, source]);
37
- const cardinality = effectiveCardinality(binding, definition, options.from, options.to);
30
+ return expanded.filter({ class: options.to }).select({ kind: 'graph', binding: expanded.node });
31
+ }, [relation, options.from, options.to, path?.raw]);
32
+ const cardinality = effectiveCardinality(binding, relation, options.from, options.to);
38
33
  const project = useCallback((response) => {
39
34
  const result = response.result;
40
35
  if (result.kind !== 'graph' || result.selection.kind !== 'node') {
@@ -47,10 +42,7 @@ export function useRelation(definition, source, options) {
47
42
  const byId = new Map(result.graph.nodes.map((node) => [node.id, node]));
48
43
  const values = result.selection.ids.flatMap((id) => {
49
44
  const node = byId.get(id);
50
- if (node === undefined)
51
- return [];
52
- const bind = binding.$.bind;
53
- return [bind(options.to, node)];
45
+ return node === undefined ? [] : [binding.wrapNode(options.to, node)];
54
46
  });
55
47
  if (cardinality === '0..1')
56
48
  return values[0] ?? null;
@@ -59,16 +51,12 @@ export function useRelation(definition, source, options) {
59
51
  if (cardinality === '1..*' && values.length === 0)
60
52
  return undefined;
61
53
  return Object.freeze(values);
62
- }, [binding, cardinality, options.to, query]);
54
+ }, [binding, cardinality, options.to]);
63
55
  const resource = useStoreResource(query, options.page?.size ?? 50, project);
64
- const unavailable = (cardinality === '1' &&
56
+ const unavailable = (cardinality === '1' || cardinality === '1..*') &&
65
57
  resource.data === undefined &&
66
58
  resource.state !== 'idle' &&
67
- resource.state !== 'loading') ||
68
- (cardinality === '1..*' &&
69
- resource.data === undefined &&
70
- resource.state !== 'idle' &&
71
- resource.state !== 'loading')
59
+ resource.state !== 'loading'
72
60
  ? Object.freeze({ kind: 'required-hidden-or-invalid', cardinality })
73
61
  : undefined;
74
62
  const require = () => {
@@ -87,50 +75,44 @@ export function useRelation(definition, source, options) {
87
75
  });
88
76
  }
89
77
  function admitSource(binding, relation, from, source) {
90
- const accepted = edgeEndpoints(relation)[from].accepts;
91
- const matches = accepted.some((ref) => {
92
- const candidate = binding.$.inspect(ref);
93
- return source.$.definition.satisfies(candidate);
94
- });
78
+ const exact = binding.domain.definition(ClassKey.ref(ClassKey(source.class)));
79
+ const matches = exact?.ref.kind === 'class' &&
80
+ exact.kind === 'node' &&
81
+ edgeEndpoints(relation)[from].accepts.some((ref) => {
82
+ const accepted = binding.domain.definition(ref);
83
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && exact.satisfies(accepted);
84
+ });
95
85
  if (!matches)
96
86
  throw new TypeError('Relation source does not satisfy the selected endpoint.');
97
87
  }
98
- function endpointCardinality(definition, side) {
99
- const endpoint = edgeEndpoints(definition)[side];
100
- const cardinality = side === 'source' ? endpoint.outgoing : endpoint.incoming;
101
- if (cardinality === undefined) {
102
- throw new TypeError(`Relation ${side} endpoint does not expose its traversal cardinality.`);
88
+ function admitRelatedDefinition(binding, relation, from, to) {
89
+ const opposite = from === 'source' ? 'target' : 'source';
90
+ const matches = edgeEndpoints(relation)[opposite].accepts.some((ref) => {
91
+ const accepted = binding.domain.definition(ref);
92
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && to.satisfies(accepted);
93
+ });
94
+ if (!matches) {
95
+ throw new TypeError('Relation target Class is not admitted by the opposite endpoint.');
103
96
  }
104
- return cardinality;
105
97
  }
106
98
  function effectiveCardinality(binding, relation, from, to) {
107
- const base = endpointCardinality(relation, from);
108
- if (base !== '1' && base !== '1..*') {
99
+ const endpoint = edgeEndpoints(relation)[from];
100
+ const base = from === 'source' ? endpoint.outgoing : endpoint.incoming;
101
+ if (base === undefined)
102
+ throw new TypeError(`Relation ${from} cardinality is absent.`);
103
+ if (base !== '1' && base !== '1..*')
109
104
  return base;
110
- }
111
- const opposite = from === 'source' ? 'target' : 'source';
112
- const coversEndpoint = edgeEndpoints(relation)[opposite].accepts.every((ref) => {
113
- const candidate = binding.$.inspect(ref);
114
- return candidate.satisfies(to);
115
- });
116
- return (coversEndpoint ? base : base === '1' ? '0..1' : '0..*');
117
- }
118
- function admitRelatedDefinition(binding, relation, from, to) {
119
105
  const opposite = from === 'source' ? 'target' : 'source';
120
- const accepted = edgeEndpoints(relation)[opposite].accepts;
121
- const matches = accepted.some((ref) => {
122
- const candidate = binding.$.inspect(ref);
123
- return to.satisfies(candidate);
106
+ const covers = edgeEndpoints(relation)[opposite].accepts.every((ref) => {
107
+ const accepted = binding.domain.definition(ref);
108
+ return accepted?.ref.kind === 'class' && accepted.kind === 'node' && accepted.satisfies(to);
124
109
  });
125
- if (!matches)
126
- throw new TypeError('Relation target definition is not admitted by the opposite endpoint.');
110
+ return covers ? base : base === '1' ? '0..1' : '0..*';
127
111
  }
128
112
  function edgeEndpoints(relation) {
129
- const declaration = relation.definition;
130
- const source = declaration.endpoints?.source;
131
- const target = declaration.endpoints?.target;
132
- if (declaration.family !== 'edge' || source === undefined || target === undefined) {
133
- throw new TypeError('Relation definition does not expose admitted Edge endpoints.');
113
+ const definition = relation.definition;
114
+ if (definition.orientation !== 'directed') {
115
+ throw new TypeError('useRelation currently requires a directed Edge Class.');
134
116
  }
135
- return Object.freeze({ source, target });
117
+ return definition.endpoints;
136
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/selection/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAO9D,MAAM,MAAM,aAAa,GAAG,IAAI,CAAA;AAChC,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAUD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAgEjF"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/selection/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAM9D,MAAM,MAAM,aAAa,GAAG,IAAI,CAAA;AAChC,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAUD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAgEjF"}
@@ -1,4 +1,3 @@
1
- import { Path } from '@astrale-os/sdk/graph/path';
2
1
  import { useCallback, useEffect, useRef, useState } from 'react';
3
2
  import { useSessionKernel } from '../auth/session-kernel.js';
4
3
  /** Resolve selected identities through the authenticated GraphApi; no fake live subscription. */
@@ -34,7 +33,7 @@ export function useResolvedNodes(orderedIds) {
34
33
  }
35
34
  setState({ key: currentKey, aliveIds: ids, nodes: [], pending: true, error: undefined });
36
35
  try {
37
- const values = await Promise.all(ids.map((nodeId) => graph.get(Path.id(nodeId))));
36
+ const values = await Promise.all(ids.map((nodeId) => graph.get(nodeId)));
38
37
  if (!alive.current || id !== generation.current)
39
38
  return;
40
39
  const aliveIds = [];
@@ -1,10 +1,9 @@
1
- import type { GraphStore } from '@astrale-os/kernel-client/store';
1
+ import type { GraphStore } from '@astrale-os/sdk/client/store';
2
2
  import type { KernelClient, Shell } from '@astrale-os/shell';
3
3
  import type { GraphStoreScope } from '../graph/store.js';
4
4
  /**
5
- * whoami's node type, derived from the auth surface so shell-react needs no
6
- * direct `@astrale-os/kernel-core` dependency (`Node` is not yet re-exported by
7
- * kernel-client — API §14 G8). Swap for the blessed re-export when it lands.
5
+ * whoami's node type, derived from the SDK auth surface so this package does
6
+ * not duplicate the canonical Client node projection.
8
7
  */
9
8
  export type SelfNode = Awaited<ReturnType<KernelClient['auth']['whoami']>>;
10
9
  /** The live shell for a provider subtree (and, later, an `<ActAs>` subtree). */
@@ -1 +1 @@
1
- {"version":3,"file":"session.context.d.ts","sourceRoot":"","sources":["../../src/session/session.context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAS5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AAE1E,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AACD,eAAO,MAAM,YAAY,8CAA2C,CAAA"}
1
+ {"version":3,"file":"session.context.d.ts","sourceRoot":"","sources":["../../src/session/session.context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAS5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AAE1E,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AACD,eAAO,MAAM,YAAY,8CAA2C,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/shell-react",
3
- "version": "0.2.10-beta.3",
3
+ "version": "0.3.1",
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": {
@@ -29,12 +29,7 @@
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "@astrale-os/kernel-client": ">=0.6.0-beta.8 <1.0.0",
33
- "@astrale-os/kernel-core": ">=0.9.0-beta.7 <1.0.0",
34
- "@astrale-os/kernel-dsl": ">=0.2.0-beta.5 <1.0.0",
35
- "@astrale-os/kernel-protocol": ">=0.5.0-beta.7 <1.0.0",
36
- "@astrale-os/kernel-server": ">=0.5.0-beta.8 <1.0.0",
37
- "@astrale-os/sdk": ">=0.5.0-beta.14 <1.0.0",
32
+ "@astrale-os/sdk": ">=0.5.0-beta.17 <1.0.0",
38
33
  "@testing-library/dom": "^10.4.0",
39
34
  "@testing-library/react": "^16.3.0",
40
35
  "@types/node": "^26.0.0",
@@ -48,15 +43,10 @@
48
43
  "typescript": "~6.0.1-rc",
49
44
  "vite": "^7.3.6",
50
45
  "vitest": "^3.2.4",
51
- "@astrale-os/shell": "0.3.8-beta.3"
46
+ "@astrale-os/shell": "0.4.1"
52
47
  },
53
48
  "peerDependencies": {
54
- "@astrale-os/kernel-client": ">=0.6.0-beta.8 <1.0.0",
55
- "@astrale-os/kernel-core": ">=0.9.0-beta.7 <1.0.0",
56
- "@astrale-os/kernel-dsl": ">=0.2.0-beta.5 <1.0.0",
57
- "@astrale-os/kernel-protocol": ">=0.5.0-beta.7 <1.0.0",
58
- "@astrale-os/kernel-server": ">=0.5.0-beta.8 <1.0.0",
59
- "@astrale-os/sdk": ">=0.5.0-beta.14 <1.0.0",
49
+ "@astrale-os/sdk": ">=0.5.0-beta.17 <1.0.0",
60
50
  "@astrale-os/shell": ">=0.3.8-beta.3 <1.0.0",
61
51
  "react": ">=18",
62
52
  "react-dom": ">=18"
@@ -1,87 +1,57 @@
1
- import type {
2
- ApplicationNode,
3
- AppSession,
4
- HostCapabilities,
5
- NodeTarget,
6
- ResolvedView,
7
- } from '@astrale-os/shell'
1
+ import type { Key } from '@astrale-os/sdk/schema'
2
+ import type { App, HostCapabilities, ResolvedView } from '@astrale-os/shell'
8
3
  import type { CSSProperties, ReactElement, ReactNode } from 'react'
9
4
 
10
- /**
11
- * AppHost (API §12.2) = useOpenApp + ViewHost. Opens the app's `AppSession`,
12
- * mounts its entry view with the session credential, and DISPOSES the session
13
- * with the window (unmount, or an app change). `opening` renders while the
14
- * session opens; `no-view` when the app pins no entrypoint; every mounted-frame
15
- * phase is the window module's `WindowState`.
16
- */
17
5
  import { forwardRef, useEffect, useRef, useState } from 'react'
18
6
 
19
7
  import type { SandboxPolicy, ViewHostHandle } from '../../window/host.js'
20
8
  import type { WindowState } from '../../window/lifecycle/states.js'
21
9
 
22
10
  import { ViewHost } from '../../window/host.js'
23
- import { toRef } from './apps.hook.js'
24
11
  import { useOpenApp } from './open-app.hook.js'
25
12
 
26
- /** The states `AppHost`'s fallback answers — the frame's, plus the two OS phases. */
27
13
  export type AppHostFallbackState =
28
14
  | WindowState
29
15
  | { readonly phase: 'opening' }
30
16
  | { readonly phase: 'no-view' }
31
17
 
32
18
  export interface AppHostProps {
33
- app: ApplicationNode | NodeTarget
34
- /** Override the entry View while keeping the application's delegated session alive. */
19
+ app: App | Key.Origin
20
+ /** Override the installed Domain entry View. */
35
21
  view?: ResolvedView
36
22
  capabilities?: HostCapabilities
37
23
  sandbox?: SandboxPolicy
38
24
  fallback?: (state: AppHostFallbackState) => ReactNode
39
- onSession?: (session: AppSession) => void
40
25
  className?: string
41
26
  style?: CSSProperties
42
27
  }
43
28
 
29
+ /** Resolve and mount an installed Domain through the ordinary Shell View lifecycle. */
44
30
  export const AppHost = forwardRef<ViewHostHandle, AppHostProps>(
45
31
  function AppHost(props, ref): ReactElement {
46
32
  const open = useOpenApp()
47
- const [session, setSession] = useState<AppSession | null>(null)
33
+ const [opened, setOpened] = useState<ResolvedView | null | undefined>(undefined)
48
34
  const [error, setError] = useState<unknown>(undefined)
49
-
50
- const appKey = toRef(props.app)
35
+ const origin = typeof props.app === 'string' ? props.app : props.app.origin
51
36
  const openRef = useRef(open)
52
37
  openRef.current = open
53
- const appRef = useRef(props.app)
54
- appRef.current = props.app
55
- const onSessionRef = useRef(props.onSession)
56
- onSessionRef.current = props.onSession
57
38
 
58
- // Open (re)opens the session per app; the cleanup disposes it — so the session
59
- // is torn down with the window (unmount) and swapped on an app change.
60
39
  useEffect(() => {
61
- let cancelled = false
62
- let opened: AppSession | null = null
63
- setSession(null)
40
+ let active = true
41
+ setOpened(undefined)
64
42
  setError(undefined)
65
- void openRef.current(appRef.current).then(
66
- (s) => {
67
- if (cancelled) {
68
- s.dispose()
69
- return
70
- }
71
- opened = s
72
- setSession(s)
73
- onSessionRef.current?.(s)
43
+ void openRef.current(origin).then(
44
+ (view) => {
45
+ if (active) setOpened(view)
74
46
  },
75
- (e: unknown) => {
76
- if (!cancelled) setError(e)
47
+ (cause: unknown) => {
48
+ if (active) setError(cause)
77
49
  },
78
50
  )
79
51
  return () => {
80
- cancelled = true
81
- opened?.dispose()
52
+ active = false
82
53
  }
83
- // eslint-disable-next-line react-hooks/exhaustive-deps
84
- }, [appKey])
54
+ }, [origin])
85
55
 
86
56
  const { fallback, className, style } = props
87
57
  const box = (children: ReactNode): ReactElement => (
@@ -90,20 +60,20 @@ export const AppHost = forwardRef<ViewHostHandle, AppHostProps>(
90
60
  </div>
91
61
  )
92
62
 
93
- // A session-open failure has no window yet — `windowId` is honestly absent (§10).
94
63
  if (error !== undefined) return box(fallback?.({ phase: 'crashed', error }) ?? null)
95
- if (session === null) return box(fallback?.({ phase: 'opening' }) ?? null)
96
- const view = props.view ?? session.view
97
- if (view === null) return box(fallback?.({ phase: 'no-view' }) ?? null)
64
+ if (opened === undefined && props.view === undefined) {
65
+ return box(fallback?.({ phase: 'opening' }) ?? null)
66
+ }
67
+ const view = props.view ?? opened
68
+ if (view === null || view === undefined) return box(fallback?.({ phase: 'no-view' }) ?? null)
98
69
 
99
70
  return (
100
71
  <ViewHost
101
72
  ref={ref}
102
73
  view={view}
103
- credential={session.credential}
104
74
  capabilities={props.capabilities}
105
75
  sandbox={props.sandbox}
106
- fallback={fallback ? (s: WindowState) => fallback(s) : undefined}
76
+ fallback={fallback ? (state: WindowState) => fallback(state) : undefined}
107
77
  className={className}
108
78
  style={style}
109
79
  />
@@ -1,88 +1,38 @@
1
- import type { PathLike } from '@astrale-os/sdk/graph/path'
2
- import type { ApplicationNode, NodeTarget, SpaceNode } from '@astrale-os/shell'
1
+ import type { App } from '@astrale-os/shell'
3
2
 
4
- import { Path } from '@astrale-os/sdk/graph/path'
5
- /**
6
- * useApps(space?) (API §12.2) — the apps installed in a space (`installed_in`
7
- * in-edges). No arg targets the CURRENT space (shared store, so a switch anywhere
8
- * swaps the dock) and is IDLE while none is selected (§1.3); an explicit `null`
9
- * stays idle; OS plane unavailable → fully idle. Also `toRef`, the app/space
10
- * subject normalizer the apps hooks share.
11
- */
12
- import { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'
3
+ import { useMemo } from 'react'
13
4
 
14
5
  import type { ReadState } from '../../graph/memory/read/envelope.js'
15
- import type { CurrentSpaceSnapshot } from '../spaces/current-space.store.js'
16
6
 
17
7
  import { useAsyncResource } from '../../graph/async.js'
18
8
  import { useShell } from '../../session/shell.hook.js'
19
- import { currentSpaceStore } from '../spaces/current-space.store.js'
20
9
  import { isOsPlaneAvailable } from '../user/user.store.js'
21
10
 
22
- const NO_APPS: readonly ApplicationNode[] = []
23
- const IDLE_CURRENT: CurrentSpaceSnapshot = { space: null, pending: false, error: undefined }
11
+ const NO_APPS: readonly App[] = []
24
12
 
25
13
  export interface AppsResult extends ReadState {
26
- readonly apps: readonly ApplicationNode[]
14
+ readonly apps: readonly App[]
27
15
  }
28
16
 
29
- export function useApps(space?: SpaceNode | NodeTarget | null): AppsResult {
17
+ /** Read the installed Domain applications available to the current Shell session. */
18
+ export function useApps(): AppsResult {
30
19
  const shell = useShell()
31
20
  const available = isOsPlaneAvailable(shell)
32
-
33
- // No arg → the CURRENT space, read through the shared store so a switch in any
34
- // window swaps the dock here (§12.2). An explicit `null` stays idle; an explicit
35
- // space bypasses the store entirely (no needless currentSpace fetch). OS plane
36
- // unavailable (§12.2) → fully idle.
37
- const useCurrent = space === undefined
38
- const store = currentSpaceStore(shell)
39
- useEffect(() => {
40
- if (useCurrent && available) store.ensure()
41
- }, [store, useCurrent, available])
42
- const subscribe = useCallback(
43
- (cb: () => void) => (useCurrent && available ? store.subscribe(cb) : () => {}),
44
- [store, useCurrent, available],
45
- )
46
- const getSnapshot = useCallback(
47
- (): CurrentSpaceSnapshot => (useCurrent && available ? store.getSnapshot() : IDLE_CURRENT),
48
- [store, useCurrent, available],
49
- )
50
- const currentSnap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
51
-
52
- const effective = useCurrent ? currentSnap.space : (space ?? null)
53
- const effRef = effective === null ? null : toRef(effective)
54
- const appsRes = useAsyncResource<readonly ApplicationNode[]>(
55
- !available || effRef === null ? null : () => shell.apps.in(effRef),
21
+ const result = useAsyncResource<readonly App[]>(
22
+ available ? () => shell.apps.list() : null,
56
23
  NO_APPS,
57
- [shell, effRef, available],
24
+ [shell, available],
58
25
  )
59
26
 
60
27
  return useMemo<AppsResult>(
61
28
  () => ({
62
- apps: appsRes.data,
63
- pending: (useCurrent && currentSnap.pending) || appsRes.pending,
64
- error: (useCurrent ? currentSnap.error : undefined) ?? appsRes.error,
29
+ apps: result.data,
30
+ pending: result.pending,
31
+ error: result.error,
65
32
  live: false,
66
33
  seq: 0,
67
- refetch: appsRes.refetch,
34
+ refetch: result.refetch,
68
35
  }),
69
- [appsRes.data, appsRes.pending, appsRes.error, appsRes.refetch, useCurrent, currentSnap],
36
+ [result.data, result.pending, result.error, result.refetch],
70
37
  )
71
38
  }
72
-
73
- /** A bound-node-ish subject carries a graph id. */
74
- function hasId(x: unknown): x is { readonly id: string } {
75
- return typeof x === 'object' && x !== null && 'id' in x
76
- }
77
-
78
- /** An `@id` ref for a bound node, else the normalized ref of a raw subject. */
79
- export function toRef(x: NodeTarget | { readonly id: string }): NodeTarget {
80
- return hasId(x) ? x.id : x
81
- }
82
-
83
- /** Stable dependency identity for one Shell node target. */
84
- export function targetKey(x: NodeTarget | { readonly id: string }): string {
85
- if (hasId(x)) return `id:${x.id}`
86
- if (typeof x === 'string') return `text:${x}`
87
- return `path:${Path.from(x as PathLike).raw}`
88
- }
@@ -1,17 +1,12 @@
1
- /**
2
- * useOpenApp (API §12.2) — the Action that opens an `AppSession` (the three-call
3
- * app-open protocol lives in the shell package). Resolves to the session; disposal
4
- * is the caller's (AppHost disposes it with the window).
5
- */
6
- import type { ApplicationNode, AppSession, NodeTarget } from '@astrale-os/shell'
1
+ import type { Key } from '@astrale-os/sdk/schema'
2
+ import type { App, ResolvedView } from '@astrale-os/shell'
7
3
 
8
4
  import type { Action } from '../../graph/action.js'
9
5
 
10
6
  import { useAction } from '../../graph/action.js'
11
7
  import { useShell } from '../../session/shell.hook.js'
12
- import { toRef } from './apps.hook.js'
13
-
14
- export function useOpenApp(): Action<[ApplicationNode | NodeTarget], AppSession> {
8
+ /** Resolve one installed Domain's ordinary entry View. */
9
+ export function useOpenApp(): Action<[App | Key.Origin], ResolvedView | null> {
15
10
  const shell = useShell()
16
- return useAction((app: ApplicationNode | NodeTarget) => shell.apps.open(toRef(app)))
11
+ return useAction((app: App | Key.Origin) => shell.apps.open(app))
17
12
  }
@@ -1,6 +1,6 @@
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, useInstalledDomains, useOpenApp,
3
+ // useCurrentSpace, useSpace, useApps, useOpenApp,
4
4
  // AppHost, AppLogo.
5
5
  export { useUser } from './user/user.hook.js'
6
6
  export { useSpaces } from './spaces/spaces.hook.js'
@@ -11,20 +11,10 @@ export { useSpace } from './spaces/space.hook.js'
11
11
  export type { SpaceResult } from './spaces/space.hook.js'
12
12
  export { useApps } from './apps/apps.hook.js'
13
13
  export type { AppsResult } from './apps/apps.hook.js'
14
- export { useInstalledDomains } from './apps/domains.hook.js'
15
- export type { DomainsResult } from './apps/domains.hook.js'
16
14
  export { useOpenApp } from './apps/open-app.hook.js'
17
15
  export { AppHost } from './apps/app-host.js'
18
16
  export type { AppHostFallbackState, AppHostProps } from './apps/app-host.js'
19
17
  export { AppLogo } from './apps/app-logo.js'
20
18
  export type { AppLogoProps } from './apps/app-logo.js'
21
19
  // The OS node/session types (from the shell package, single import surface).
22
- export type {
23
- ApplicationNode,
24
- AppSession,
25
- DomainSearchResult,
26
- NodeTarget,
27
- ResolvedView,
28
- SpaceNode,
29
- UserNode,
30
- } from '@astrale-os/shell'
20
+ export type { App, NodeTarget, ResolvedView, SpaceNode, UserNode } from '@astrale-os/shell'
@@ -1,5 +1,7 @@
1
+ import type { PathLike } from '@astrale-os/sdk/graph/path'
1
2
  import type { NodeTarget, SpaceNode } from '@astrale-os/shell'
2
3
 
4
+ import { Path } from '@astrale-os/sdk/graph/path'
3
5
  /**
4
6
  * useSpace(ref) (API §12.2) — a single space by ref; `null`/`undefined` (or an
5
7
  * unavailable OS plane) is idle (§1.3). One-shot today (§12 flag).
@@ -11,7 +13,6 @@ import type { CurrentSpaceResult } from './current-space.hook.js'
11
13
  import { useAsyncResource } from '../../graph/async.js'
12
14
  import { isIdleInput } from '../../graph/memory/read/idle.js'
13
15
  import { useShell } from '../../session/shell.hook.js'
14
- import { targetKey } from '../apps/apps.hook.js'
15
16
  import { isOsPlaneAvailable } from '../user/user.store.js'
16
17
 
17
18
  export type SpaceResult = CurrentSpaceResult
@@ -38,3 +39,7 @@ export function useSpace(ref: NodeTarget | null | undefined): SpaceResult {
38
39
  [idle, res],
39
40
  )
40
41
  }
42
+
43
+ function targetKey(input: NodeTarget): string {
44
+ return typeof input === 'string' ? `text:${input}` : `path:${Path.from(input as PathLike).raw}`
45
+ }
@@ -1,4 +1,4 @@
1
- import type { Identity } from '@astrale-os/kernel-client/auth'
1
+ import type { Identity } from '@astrale-os/sdk/auth'
2
2
  import type { KernelClient } from '@astrale-os/shell'
3
3
  import type { ReactElement, ReactNode } from 'react'
4
4
 
@@ -1,4 +1,4 @@
1
- import type { AuthApi } from '@astrale-os/kernel-client/auth'
1
+ import type { AuthApi } from '@astrale-os/sdk/auth'
2
2
 
3
3
  import { useIdentityBinding } from './act-as.context.js'
4
4
 
@@ -1,6 +1,6 @@
1
1
  import type { NodeId } from '@astrale-os/sdk/graph/node'
2
2
  import type { PathLike } from '@astrale-os/sdk/graph/path'
3
- import type { schema } from '@astrale-os/sdk/schema'
3
+ import type { PolicyRef } from '@astrale-os/sdk/schema'
4
4
 
5
5
  import { Path } from '@astrale-os/sdk/graph/path'
6
6
  import { useEffect, useState } from 'react'
@@ -14,7 +14,7 @@ export type PolicyObject = NodeId | { readonly id: NodeId }
14
14
  * invoked callable remains the authorization enforcement point.
15
15
  */
16
16
  export function useCan(
17
- policy: PathLike | schema.PolicyRef | null | undefined,
17
+ policy: PathLike | PolicyRef | null | undefined,
18
18
  object: PolicyObject | null | undefined,
19
19
  ): boolean | undefined {
20
20
  const { kernel } = useIdentityBinding()
@@ -45,7 +45,7 @@ export function useCan(
45
45
  return decision
46
46
  }
47
47
 
48
- function policyPath(policy: PathLike | schema.PolicyRef | null | undefined) {
48
+ function policyPath(policy: PathLike | PolicyRef | null | undefined) {
49
49
  if (policy === null || policy === undefined) return null
50
50
  return policy instanceof Path || typeof policy === 'string'
51
51
  ? Path.from(policy).raw
@@ -1,4 +1,4 @@
1
- import type { Identity } from '@astrale-os/kernel-client/auth'
1
+ import type { Identity } from '@astrale-os/sdk/auth'
2
2
 
3
3
  import { useIdentityBinding } from './act-as.context.js'
4
4