@astrale-os/shell 0.3.1 → 0.3.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.
@@ -1,7 +1,7 @@
1
1
  import type { BoundNode, DefOf, NodeRefInput } from '@astrale-os/kernel-client';
2
2
  import type { KernelClient } from '../kernel/client.js';
3
3
  import type { AppSession } from './session/session.js';
4
- import type { ShellDomainView, ShellSchema } from './view.js';
4
+ import type { ShellView, ShellSchema } from './view.js';
5
5
  /** An installed `Application` node. */
6
6
  export type ApplicationNode = BoundNode<DefOf<ShellSchema, 'Application'>, ShellSchema>;
7
7
  export interface AppsNamespace {
@@ -12,7 +12,7 @@ export interface AppsNamespace {
12
12
  /** Resolve the app node and open its {@link AppSession}. */
13
13
  open(app: NodeRefInput): Promise<AppSession>;
14
14
  }
15
- export declare function createAppsNamespace(kernel: KernelClient, v: ShellDomainView, deps?: {
15
+ export declare function createAppsNamespace(kernel: KernelClient, v: ShellView, deps?: {
16
16
  readonly now?: () => number;
17
17
  }): AppsNamespace;
18
18
  //# sourceMappingURL=apps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/application/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAK/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAI7D,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,WAAW,CAAC,CAAA;AAEvF,MAAM,WAAW,aAAa;IAC5B,kFAAkF;IAClF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IACtE,+DAA+D;IAC/D,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IACnD,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAC7C;AAKD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,CAAC,EAAE,eAAe,EAClB,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE,GACrC,aAAa,CA6Bf"}
1
+ {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/application/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAK/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAIvD,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,WAAW,CAAC,CAAA;AAEvF,MAAM,WAAW,aAAa;IAC5B,kFAAkF;IAClF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IACtE,+DAA+D;IAC/D,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IACnD,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAC7C;AAKD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,CAAC,EAAE,SAAS,EACZ,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE,GACrC,aAAa,CAyBf"}
@@ -6,13 +6,9 @@ const INSTALLED_IN_EDGE = D.installed_in.path.class.raw;
6
6
  export function createAppsNamespace(kernel, v, deps) {
7
7
  return {
8
8
  async install(target, space) {
9
- const created = (await v
10
- .view()('Application')
11
- .install({
12
- target,
13
- space: normalizeRef(space),
14
- }));
15
- const app = await v.view().node('Application', `@${created.id}`);
9
+ const Application = v.get().classes.Application;
10
+ const created = await Application.install({ target, space: normalizeRef(space) });
11
+ const app = await Application.get(`@${created.id}`);
16
12
  if (!app)
17
13
  throw new Error(`Application.install: app @${created.id} is not readable`);
18
14
  return app;
@@ -26,7 +22,7 @@ export function createAppsNamespace(kernel, v, deps) {
26
22
  });
27
23
  },
28
24
  async open(app) {
29
- const node = await v.view().node('Application', app);
25
+ const node = await v.get().classes.Application.get(app);
30
26
  if (!node)
31
27
  throw new Error(`apps.open: application ${normalizeRef(app)} is not readable`);
32
28
  return openAppSession({ kernel, ...(deps?.now ? { now: deps.now } : {}) }, node.id);
@@ -1,6 +1,6 @@
1
1
  import type { BoundNode, DefOf, NodeRefInput } from '@astrale-os/kernel-client';
2
2
  import type { KernelClient } from '../kernel/client.js';
3
- import type { ShellDomainView, ShellSchema } from './view.js';
3
+ import type { ShellView, ShellSchema } from './view.js';
4
4
  /** A workspace `Space` node. */
5
5
  export type SpaceNode = BoundNode<DefOf<ShellSchema, 'Space'>, ShellSchema>;
6
6
  export interface SpacesNamespace {
@@ -13,5 +13,5 @@ export interface SpacesNamespace {
13
13
  name?: string;
14
14
  }): Promise<SpaceNode>;
15
15
  }
16
- export declare function createSpacesNamespace(kernel: KernelClient, v: ShellDomainView): SpacesNamespace;
16
+ export declare function createSpacesNamespace(kernel: KernelClient, v: ShellView): SpacesNamespace;
17
17
  //# sourceMappingURL=spaces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spaces.d.ts","sourceRoot":"","sources":["../../src/application/spaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAI/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE7D,gCAAgC;AAChC,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,CAAA;AAE3E,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAC5B,uEAAuE;IACvE,GAAG,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IACjD,2DAA2D;IAC3D,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;CACrD;AAKD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,eAAe,GAAG,eAAe,CA6B/F"}
1
+ {"version":3,"file":"spaces.d.ts","sourceRoot":"","sources":["../../src/application/spaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAI/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvD,gCAAgC;AAChC,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,CAAA;AAE3E,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAC5B,uEAAuE;IACvE,GAAG,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IACjD,2DAA2D;IAC3D,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;CACrD;AAKD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,GAAG,eAAe,CAwBzF"}
@@ -16,12 +16,9 @@ export function createSpacesNamespace(kernel, v) {
16
16
  return node ? v.bindAs('Space', node) : null;
17
17
  },
18
18
  async create(opts) {
19
- // `Space.create`'s params are all-optional, so the typed dispatch collapses
20
- // to `(opts?)`; the runtime still forwards a params object (resolveCallArgs),
21
- // so pass `{ name }` through a create-shaped view of the same thunk.
22
- const create = v.view()('Space').create;
23
- const created = await create(opts?.name !== undefined ? { name: opts.name } : undefined);
24
- const space = await v.view().node('Space', `@${created.id}`);
19
+ const Space = v.get().classes.Space;
20
+ const created = await Space.create(opts?.name !== undefined ? { name: opts.name } : undefined);
21
+ const space = await Space.get(`@${created.id}`);
25
22
  if (!space)
26
23
  throw new Error(`Space.create: created space @${created.id} is not readable`);
27
24
  return space;
@@ -1,7 +1,7 @@
1
1
  import type { BoundNode, DefOf, NodeRefInput } from '@astrale-os/kernel-client';
2
2
  import type { KernelClient } from '../kernel/client.js';
3
3
  import type { SpaceNode } from './spaces.js';
4
- import type { ShellDomainView, ShellSchema } from './view.js';
4
+ import type { ShellView, ShellSchema } from './view.js';
5
5
  /** Self as the shell-domain `User` — typed `firstName`/`lastName`/`email`. */
6
6
  export type UserNode = BoundNode<DefOf<ShellSchema, 'User'>, ShellSchema>;
7
7
  /** A `Role` a user holds. */
@@ -16,5 +16,5 @@ export interface UserNamespace {
16
16
  /** The `has_role` out-edges of self. */
17
17
  roles(): Promise<RoleNode[]>;
18
18
  }
19
- export declare function createUserNamespace(kernel: KernelClient, v: ShellDomainView): UserNamespace;
19
+ export declare function createUserNamespace(kernel: KernelClient, v: ShellView): UserNamespace;
20
20
  //# sourceMappingURL=user.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/application/user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAI/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAI7D,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAA;AACzE,6BAA6B;AAC7B,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAA;AAEzE,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAA;IACvB,yEAAyE;IACzE,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IACzC,sFAAsF;IACtF,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,wCAAwC;IACxC,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,eAAe,GAAG,aAAa,CA2B3F"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/application/user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAI/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAIvD,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAA;AACzE,6BAA6B;AAC7B,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAA;AAEzE,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAA;IACvB,yEAAyE;IACzE,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IACzC,sFAAsF;IACtF,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,wCAAwC;IACxC,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,GAAG,aAAa,CA2BrF"}
@@ -2,23 +2,23 @@ import { normalizeRef } from '@astrale-os/kernel-client';
2
2
  import { asArray } from './view.js';
3
3
  export function createUserNamespace(kernel, v) {
4
4
  async function me() {
5
- return v.view().bind('User', await kernel.auth.whoami());
5
+ return v.get().bind('User', await kernel.auth.whoami());
6
6
  }
7
7
  return {
8
8
  me,
9
9
  async currentSpace() {
10
10
  const self = await me();
11
- const first = asArray(await self.out('selected_space'))[0];
11
+ const first = asArray(await self.links.out('selected_space'))[0];
12
12
  return first ? v.bindAs('Space', first.raw) : null;
13
13
  },
14
14
  async switchSpace(ref) {
15
15
  const self = await me();
16
- await self.call.switchSpace({ space: normalizeRef(ref) });
16
+ await self.switchSpace({ space: normalizeRef(ref) });
17
17
  },
18
18
  async roles() {
19
19
  const self = await me();
20
- return asArray(await self.out('has_role')).flatMap((r) => {
21
- const role = v.bindAs('Role', r.raw);
20
+ return asArray(await self.links.out('has_role')).flatMap((node) => {
21
+ const role = v.bindAs('Role', node.raw);
22
22
  return role ? [role] : [];
23
23
  });
24
24
  },
@@ -3,18 +3,22 @@
3
3
  * shell domain (`@astrale-domains/shell-schema`). The bound view is built LAZILY
4
4
  * (first call) so the sandboxed shell's "init() first" kernel guard applies
5
5
  * uniformly — constructing namespaces touches no kernel.
6
+ *
7
+ * Typed access uses `.classes`: `get().classes.Space(ref)` dispatches without
8
+ * a read and `get().classes.Space.get(ref)` returns a bound node.
6
9
  */
7
10
  import type { BoundNode, DefOf, SchemaBoundView } from '@astrale-os/kernel-client';
8
11
  import type { Node } from '@astrale-os/kernel-core';
9
12
  import { schema } from '@astrale-domains/shell-schema';
10
13
  import type { KernelClient } from '../kernel/client.js';
11
14
  export type ShellSchema = typeof schema;
12
- export interface ShellDomainView {
13
- view(): SchemaBoundView<ShellSchema>;
15
+ /** Lazily-created schema-bound Shell client. */
16
+ export interface ShellView {
17
+ get(): SchemaBoundView<ShellSchema>;
14
18
  /** Bind `node` as `type` when its concrete class satisfies it, else `null`. */
15
19
  bindAs<T extends 'User' | 'Space' | 'Application' | 'Role'>(type: T, node: Node): BoundNode<DefOf<ShellSchema, T>, ShellSchema> | null;
16
20
  }
17
- export declare function createShellDomainView(kernel: KernelClient): ShellDomainView;
21
+ export declare function createShellDomainView(kernel: KernelClient): ShellView;
18
22
  /** Normalize a typed traversal result (single | array | null) to an array. */
19
23
  export declare function asArray<T>(result: T | readonly T[] | null): T[];
20
24
  //# sourceMappingURL=view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/application/view.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,MAAM,MAAM,WAAW,GAAG,OAAO,MAAM,CAAA;AAEvC,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,eAAe,CAAC,WAAW,CAAC,CAAA;IACpC,+EAA+E;IAC/E,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,MAAM,EACxD,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,IAAI,GACT,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,IAAI,CAAA;CACxD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAW3E;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,GAAG,CAAC,EAAE,CAG/D"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/application/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,MAAM,MAAM,WAAW,GAAG,OAAO,MAAM,CAAA;AAEvC,gDAAgD;AAChD,MAAM,WAAW,SAAS;IACxB,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAA;IACnC,+EAA+E;IAC/E,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,MAAM,EACxD,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,IAAI,GACT,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,IAAI,CAAA;CACxD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAWrE;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,GAAG,CAAC,EAAE,CAG/D"}
@@ -1,11 +1,11 @@
1
1
  import { schema } from '@astrale-domains/shell-schema';
2
2
  export function createShellDomainView(kernel) {
3
3
  let bound = null;
4
- const view = () => (bound ??= kernel.withSchema(schema));
4
+ const get = () => (bound ??= kernel.withSchema(schema));
5
5
  return {
6
- view,
6
+ get,
7
7
  bindAs(type, node) {
8
- const v = view();
8
+ const v = get();
9
9
  return v.bindAny(node).is(type) ? v.bind(type, node) : null;
10
10
  },
11
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/shell",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Astrale Shell SDK — parent/child/kernel communication",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -25,10 +25,10 @@
25
25
  "access": "public"
26
26
  },
27
27
  "dependencies": {
28
- "@astrale-domains/shell-schema": ">=0.3.1 <1.0.0",
29
- "@astrale-os/kernel-client": ">=0.4.0 <1.0.0",
30
- "@astrale-os/kernel-core": ">=0.7.1 <1.0.0",
31
- "@astrale-os/kernel-dsl": ">=0.1.3 <1.0.0",
28
+ "@astrale-domains/shell-schema": ">=0.3.2 <1.0.0",
29
+ "@astrale-os/kernel-client": ">=0.4.6 <1.0.0",
30
+ "@astrale-os/kernel-core": ">=0.7.5 <1.0.0",
31
+ "@astrale-os/kernel-dsl": ">=0.1.4 <1.0.0",
32
32
  "jose": "^6.2.3",
33
33
  "zod": "^4.3.6"
34
34
  },
@@ -5,7 +5,7 @@ import { normalizeRef } from '@astrale-os/kernel-client'
5
5
 
6
6
  import type { KernelClient } from '../kernel/client.js'
7
7
  import type { AppSession } from './session/session.js'
8
- import type { ShellDomainView, ShellSchema } from './view.js'
8
+ import type { ShellView, ShellSchema } from './view.js'
9
9
 
10
10
  import { openAppSession } from './session/open.js'
11
11
 
@@ -26,18 +26,14 @@ const INSTALLED_IN_EDGE = D.installed_in.path.class.raw
26
26
 
27
27
  export function createAppsNamespace(
28
28
  kernel: KernelClient,
29
- v: ShellDomainView,
29
+ v: ShellView,
30
30
  deps?: { readonly now?: () => number },
31
31
  ): AppsNamespace {
32
32
  return {
33
33
  async install(target, space) {
34
- const created = (await v
35
- .view()('Application')
36
- .install({
37
- target,
38
- space: normalizeRef(space),
39
- })) as { id: string }
40
- const app = await v.view().node('Application', `@${created.id}`)
34
+ const Application = v.get().classes.Application
35
+ const created = await Application.install({ target, space: normalizeRef(space) })
36
+ const app = await Application.get(`@${created.id}`)
41
37
  if (!app) throw new Error(`Application.install: app @${created.id} is not readable`)
42
38
  return app
43
39
  },
@@ -52,7 +48,7 @@ export function createAppsNamespace(
52
48
  },
53
49
 
54
50
  async open(app) {
55
- const node = await v.view().node('Application', app)
51
+ const node = await v.get().classes.Application.get(app)
56
52
  if (!node) throw new Error(`apps.open: application ${normalizeRef(app)} is not readable`)
57
53
  return openAppSession({ kernel, ...(deps?.now ? { now: deps.now } : {}) }, node.id)
58
54
  },
@@ -3,7 +3,7 @@ import type { BoundNode, DefOf, NodeRefInput } from '@astrale-os/kernel-client'
3
3
  import { normalizeRef } from '@astrale-os/kernel-client'
4
4
 
5
5
  import type { KernelClient } from '../kernel/client.js'
6
- import type { ShellDomainView, ShellSchema } from './view.js'
6
+ import type { ShellView, ShellSchema } from './view.js'
7
7
 
8
8
  /** A workspace `Space` node. */
9
9
  export type SpaceNode = BoundNode<DefOf<ShellSchema, 'Space'>, ShellSchema>
@@ -20,7 +20,7 @@ export interface SpacesNamespace {
20
20
  /** The spaces directory (mirrors the shell domain's `SPACES_DIR`). */
21
21
  const SPACES_DIR = '/spaces'
22
22
 
23
- export function createSpacesNamespace(kernel: KernelClient, v: ShellDomainView): SpacesNamespace {
23
+ export function createSpacesNamespace(kernel: KernelClient, v: ShellView): SpacesNamespace {
24
24
  return {
25
25
  async list() {
26
26
  const page = await kernel.children(SPACES_DIR)
@@ -37,14 +37,9 @@ export function createSpacesNamespace(kernel: KernelClient, v: ShellDomainView):
37
37
  },
38
38
 
39
39
  async create(opts) {
40
- // `Space.create`'s params are all-optional, so the typed dispatch collapses
41
- // to `(opts?)`; the runtime still forwards a params object (resolveCallArgs),
42
- // so pass `{ name }` through a create-shaped view of the same thunk.
43
- const create = v.view()('Space').create as (params?: {
44
- name?: string
45
- }) => Promise<{ id: string }>
46
- const created = await create(opts?.name !== undefined ? { name: opts.name } : undefined)
47
- const space = await v.view().node('Space', `@${created.id}`)
40
+ const Space = v.get().classes.Space
41
+ const created = await Space.create(opts?.name !== undefined ? { name: opts.name } : undefined)
42
+ const space = await Space.get(`@${created.id}`)
48
43
  if (!space) throw new Error(`Space.create: created space @${created.id} is not readable`)
49
44
  return space
50
45
  },
@@ -4,7 +4,7 @@ import { normalizeRef } from '@astrale-os/kernel-client'
4
4
 
5
5
  import type { KernelClient } from '../kernel/client.js'
6
6
  import type { SpaceNode } from './spaces.js'
7
- import type { ShellDomainView, ShellSchema } from './view.js'
7
+ import type { ShellView, ShellSchema } from './view.js'
8
8
 
9
9
  import { asArray } from './view.js'
10
10
 
@@ -24,9 +24,9 @@ export interface UserNamespace {
24
24
  roles(): Promise<RoleNode[]>
25
25
  }
26
26
 
27
- export function createUserNamespace(kernel: KernelClient, v: ShellDomainView): UserNamespace {
27
+ export function createUserNamespace(kernel: KernelClient, v: ShellView): UserNamespace {
28
28
  async function me(): Promise<UserNode> {
29
- return v.view().bind('User', await kernel.auth.whoami())
29
+ return v.get().bind('User', await kernel.auth.whoami())
30
30
  }
31
31
 
32
32
  return {
@@ -34,19 +34,19 @@ export function createUserNamespace(kernel: KernelClient, v: ShellDomainView): U
34
34
 
35
35
  async currentSpace() {
36
36
  const self = await me()
37
- const first = asArray(await self.out('selected_space'))[0]
37
+ const first = asArray(await self.links.out('selected_space'))[0]
38
38
  return first ? v.bindAs('Space', first.raw) : null
39
39
  },
40
40
 
41
41
  async switchSpace(ref) {
42
42
  const self = await me()
43
- await self.call.switchSpace({ space: normalizeRef(ref) })
43
+ await self.switchSpace({ space: normalizeRef(ref) })
44
44
  },
45
45
 
46
46
  async roles() {
47
47
  const self = await me()
48
- return asArray(await self.out('has_role')).flatMap((r) => {
49
- const role = v.bindAs('Role', r.raw)
48
+ return asArray(await self.links.out('has_role')).flatMap((node) => {
49
+ const role = v.bindAs('Role', node.raw)
50
50
  return role ? [role] : []
51
51
  })
52
52
  },
@@ -3,6 +3,9 @@
3
3
  * shell domain (`@astrale-domains/shell-schema`). The bound view is built LAZILY
4
4
  * (first call) so the sandboxed shell's "init() first" kernel guard applies
5
5
  * uniformly — constructing namespaces touches no kernel.
6
+ *
7
+ * Typed access uses `.classes`: `get().classes.Space(ref)` dispatches without
8
+ * a read and `get().classes.Space.get(ref)` returns a bound node.
6
9
  */
7
10
  import type { BoundNode, DefOf, SchemaBoundView } from '@astrale-os/kernel-client'
8
11
  import type { Node } from '@astrale-os/kernel-core'
@@ -13,8 +16,9 @@ import type { KernelClient } from '../kernel/client.js'
13
16
 
14
17
  export type ShellSchema = typeof schema
15
18
 
16
- export interface ShellDomainView {
17
- view(): SchemaBoundView<ShellSchema>
19
+ /** Lazily-created schema-bound Shell client. */
20
+ export interface ShellView {
21
+ get(): SchemaBoundView<ShellSchema>
18
22
  /** Bind `node` as `type` when its concrete class satisfies it, else `null`. */
19
23
  bindAs<T extends 'User' | 'Space' | 'Application' | 'Role'>(
20
24
  type: T,
@@ -22,14 +26,14 @@ export interface ShellDomainView {
22
26
  ): BoundNode<DefOf<ShellSchema, T>, ShellSchema> | null
23
27
  }
24
28
 
25
- export function createShellDomainView(kernel: KernelClient): ShellDomainView {
29
+ export function createShellDomainView(kernel: KernelClient): ShellView {
26
30
  let bound: SchemaBoundView<ShellSchema> | null = null
27
- const view = (): SchemaBoundView<ShellSchema> => (bound ??= kernel.withSchema(schema))
31
+ const get = (): SchemaBoundView<ShellSchema> => (bound ??= kernel.withSchema(schema))
28
32
 
29
33
  return {
30
- view,
34
+ get,
31
35
  bindAs(type, node) {
32
- const v = view()
36
+ const v = get()
33
37
  return v.bindAny(node).is(type) ? v.bind(type, node) : null
34
38
  },
35
39
  }