@astrale-os/shell-react 0.2.10-beta.2 → 0.2.10-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/astrale.d.ts +14 -0
- package/dist/components/astrale.d.ts.map +1 -0
- package/dist/components/astrale.js +12 -0
- package/dist/components/index.d.ts +2 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +16 -5
- package/src/components/astrale.tsx +40 -0
- package/src/components/index.ts +2 -3
- package/src/index.ts +2 -7
- package/dist/components/mount-domain-frontend.d.ts +0 -22
- package/dist/components/mount-domain-frontend.d.ts.map +0 -1
- package/dist/components/mount-domain-frontend.js +0 -85
- package/dist/components/view-app.d.ts +0 -16
- package/dist/components/view-app.d.ts.map +0 -1
- package/dist/components/view-app.js +0 -16
- package/src/components/mount-domain-frontend.tsx +0 -158
- package/src/components/view-app.tsx +0 -49
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Shell, ShellConfig } from '@astrale-os/shell';
|
|
2
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import type { ShellProviderProps } from '../session/provider.js';
|
|
4
|
+
export interface AstraleProps {
|
|
5
|
+
/** Defaults to the child-side sandbox handshake; pass a Shell for an embedded host or test. */
|
|
6
|
+
readonly config?: ShellConfig | Shell;
|
|
7
|
+
readonly fallback?: ReactNode;
|
|
8
|
+
readonly errorFallback?: ShellProviderProps['errorFallback'];
|
|
9
|
+
readonly onError?: (error: unknown) => void;
|
|
10
|
+
readonly children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/** Complete Astrale runtime root without taking ownership of application routing. */
|
|
13
|
+
export declare function Astrale(props: AstraleProps): ReactElement;
|
|
14
|
+
//# sourceMappingURL=astrale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astrale.d.ts","sourceRoot":"","sources":["../../src/components/astrale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAIpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAQhE,MAAM,WAAW,YAAY;IAC3B,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAA;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAA;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B;AAED,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAgBzD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense } from 'react';
|
|
3
|
+
import { ShellProvider } from '../session/provider.js';
|
|
4
|
+
import { ViewStage } from '../window/stage.js';
|
|
5
|
+
import { defaultViewError, defaultViewLoading, ViewErrorBoundary } from './boundaries.js';
|
|
6
|
+
const SANDBOXED_SHELL = Object.freeze({ mode: 'sandboxed' });
|
|
7
|
+
/** Complete Astrale runtime root without taking ownership of application routing. */
|
|
8
|
+
export function Astrale(props) {
|
|
9
|
+
const loading = props.fallback ?? defaultViewLoading();
|
|
10
|
+
const errorFallback = props.errorFallback ?? defaultViewError;
|
|
11
|
+
return (_jsxs(ShellProvider, { config: props.config ?? SANDBOXED_SHELL, fallback: loading, errorFallback: errorFallback, onError: ({ error }) => props.onError?.(error), children: [_jsx(ViewErrorBoundary, { fallback: errorFallback, onError: props.onError, children: _jsx(Suspense, { fallback: loading, children: props.children }) }), _jsx(ViewStage, {})] }));
|
|
12
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { Can } from './can.js';
|
|
2
2
|
export { ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary, ViewErrorBoundary, ViewBoundary, } from './boundaries.js';
|
|
3
3
|
export type { ViewErrorBoundaryProps } from './boundaries.js';
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export type { MountedDomainFrontend, MountDomainFrontendOptions } from './mount-domain-frontend.js';
|
|
4
|
+
export { Astrale } from './astrale.js';
|
|
5
|
+
export type { AstraleProps } from './astrale.js';
|
|
7
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/components/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { Can } from './can.js';
|
|
2
2
|
export { ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary, ViewErrorBoundary, ViewBoundary, } from './boundaries.js';
|
|
3
|
-
export {
|
|
4
|
-
export { mountDomainFrontend } from './mount-domain-frontend.js';
|
|
3
|
+
export { Astrale } from './astrale.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -18,8 +18,8 @@ export type { ExternalOpenApi, HostDialogApi, NotifyApi, OpenViewApi, RequestAcc
|
|
|
18
18
|
export { HostCapabilityUnavailableError } from './host/index.js';
|
|
19
19
|
export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
|
|
20
20
|
export type { EmitIntent, IntentCtx, IntentPayload, IntentReply, SendIntent, } from './intents/index.js';
|
|
21
|
-
export { Can, ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary,
|
|
22
|
-
export type {
|
|
21
|
+
export { Can, ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary, Astrale, ViewBoundary, ViewErrorBoundary, } from './components/index.js';
|
|
22
|
+
export type { AstraleProps, ViewErrorBoundaryProps } from './components/index.js';
|
|
23
23
|
export { AppHost, AppLogo, useApps, useCurrentSpace, useInstalledDomains, useOpenApp, useSpace, useSpaces, useUser, } from './application/index.js';
|
|
24
24
|
export type { AppHostFallbackState, AppHostProps, AppLogoProps, AppsResult, CurrentSpaceResult, DomainsResult, SpaceResult, SpacesResult, } from './application/index.js';
|
|
25
25
|
export { NodeId } from '@astrale-os/sdk/graph/node';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
@@ -15,7 +15,7 @@ export { HostDialog, NestedView, Notify, RequestAccess, useExternalOpen, useHost
|
|
|
15
15
|
export { HostCapabilityUnavailableError } from './host/index.js';
|
|
16
16
|
export { useEmitIntent, useIntent, useSendIntent } from './intents/index.js';
|
|
17
17
|
// Headless composition kit.
|
|
18
|
-
export { Can, ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary,
|
|
18
|
+
export { Can, ConnectionBoundary, CredentialBoundary, defaultViewError, defaultViewLoading, GraphBoundary, Astrale, ViewBoundary, ViewErrorBoundary, } from './components/index.js';
|
|
19
19
|
// Shell application conveniences.
|
|
20
20
|
export { AppHost, AppLogo, useApps, useCurrentSpace, useInstalledDomains, useOpenApp, useSpace, useSpaces, useUser, } from './application/index.js';
|
|
21
21
|
// Canonical identity carriers used by View props and rich hooks.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/shell-react",
|
|
3
|
-
"version": "0.2.10-beta.
|
|
3
|
+
"version": "0.2.10-beta.3",
|
|
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": {
|
|
@@ -25,14 +25,19 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@astrale-os/kernel-client": ">=0.6.0-beta.4 <1.0.0",
|
|
29
|
-
"@astrale-os/sdk": ">=0.5.0-beta.4 <1.0.0",
|
|
30
28
|
"jose": "^6.2.3",
|
|
31
29
|
"zod": "^4.3.6"
|
|
32
30
|
},
|
|
33
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",
|
|
34
38
|
"@testing-library/dom": "^10.4.0",
|
|
35
39
|
"@testing-library/react": "^16.3.0",
|
|
40
|
+
"@types/node": "^26.0.0",
|
|
36
41
|
"@types/react": "^19.2.0",
|
|
37
42
|
"@types/react-dom": "^19.2.0",
|
|
38
43
|
"@typescript/native-preview": "latest",
|
|
@@ -43,10 +48,16 @@
|
|
|
43
48
|
"typescript": "~6.0.1-rc",
|
|
44
49
|
"vite": "^7.3.6",
|
|
45
50
|
"vitest": "^3.2.4",
|
|
46
|
-
"@astrale-os/shell": "0.3.8-beta.
|
|
51
|
+
"@astrale-os/shell": "0.3.8-beta.3"
|
|
47
52
|
},
|
|
48
53
|
"peerDependencies": {
|
|
49
|
-
"@astrale-os/
|
|
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",
|
|
60
|
+
"@astrale-os/shell": ">=0.3.8-beta.3 <1.0.0",
|
|
50
61
|
"react": ">=18",
|
|
51
62
|
"react-dom": ">=18"
|
|
52
63
|
},
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Shell, ShellConfig } from '@astrale-os/shell'
|
|
2
|
+
import type { ReactElement, ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
import { Suspense } from 'react'
|
|
5
|
+
|
|
6
|
+
import type { ShellProviderProps } from '../session/provider.js'
|
|
7
|
+
|
|
8
|
+
import { ShellProvider } from '../session/provider.js'
|
|
9
|
+
import { ViewStage } from '../window/stage.js'
|
|
10
|
+
import { defaultViewError, defaultViewLoading, ViewErrorBoundary } from './boundaries.js'
|
|
11
|
+
|
|
12
|
+
const SANDBOXED_SHELL = Object.freeze({ mode: 'sandboxed' as const })
|
|
13
|
+
|
|
14
|
+
export interface AstraleProps {
|
|
15
|
+
/** Defaults to the child-side sandbox handshake; pass a Shell for an embedded host or test. */
|
|
16
|
+
readonly config?: ShellConfig | Shell
|
|
17
|
+
readonly fallback?: ReactNode
|
|
18
|
+
readonly errorFallback?: ShellProviderProps['errorFallback']
|
|
19
|
+
readonly onError?: (error: unknown) => void
|
|
20
|
+
readonly children: ReactNode
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Complete Astrale runtime root without taking ownership of application routing. */
|
|
24
|
+
export function Astrale(props: AstraleProps): ReactElement {
|
|
25
|
+
const loading = props.fallback ?? defaultViewLoading()
|
|
26
|
+
const errorFallback = props.errorFallback ?? defaultViewError
|
|
27
|
+
return (
|
|
28
|
+
<ShellProvider
|
|
29
|
+
config={props.config ?? SANDBOXED_SHELL}
|
|
30
|
+
fallback={loading}
|
|
31
|
+
errorFallback={errorFallback}
|
|
32
|
+
onError={({ error }) => props.onError?.(error)}
|
|
33
|
+
>
|
|
34
|
+
<ViewErrorBoundary fallback={errorFallback} onError={props.onError}>
|
|
35
|
+
<Suspense fallback={loading}>{props.children}</Suspense>
|
|
36
|
+
</ViewErrorBoundary>
|
|
37
|
+
<ViewStage />
|
|
38
|
+
</ShellProvider>
|
|
39
|
+
)
|
|
40
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -9,6 +9,5 @@ export {
|
|
|
9
9
|
ViewBoundary,
|
|
10
10
|
} from './boundaries.js'
|
|
11
11
|
export type { ViewErrorBoundaryProps } from './boundaries.js'
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export type { MountedDomainFrontend, MountDomainFrontendOptions } from './mount-domain-frontend.js'
|
|
12
|
+
export { Astrale } from './astrale.js'
|
|
13
|
+
export type { AstraleProps } from './astrale.js'
|
package/src/index.ts
CHANGED
|
@@ -166,16 +166,11 @@ export {
|
|
|
166
166
|
defaultViewError,
|
|
167
167
|
defaultViewLoading,
|
|
168
168
|
GraphBoundary,
|
|
169
|
-
|
|
170
|
-
ViewApp,
|
|
169
|
+
Astrale,
|
|
171
170
|
ViewBoundary,
|
|
172
171
|
ViewErrorBoundary,
|
|
173
172
|
} from './components/index.js'
|
|
174
|
-
export type {
|
|
175
|
-
MountedDomainFrontend,
|
|
176
|
-
MountDomainFrontendOptions,
|
|
177
|
-
ViewErrorBoundaryProps,
|
|
178
|
-
} from './components/index.js'
|
|
173
|
+
export type { AstraleProps, ViewErrorBoundaryProps } from './components/index.js'
|
|
179
174
|
|
|
180
175
|
// Shell application conveniences.
|
|
181
176
|
export {
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ReactRouteModule } from '@astrale-os/sdk/react';
|
|
2
|
-
import type { schema } from '@astrale-os/sdk/schema';
|
|
3
|
-
import type { Shell, ShellConfig } from '@astrale-os/shell';
|
|
4
|
-
import type { ReactNode } from 'react';
|
|
5
|
-
type ViewName<S extends schema.DomainSchema> = Extract<keyof ReactRouteModule<S>['routes'], string>;
|
|
6
|
-
export interface MountDomainFrontendOptions<S extends schema.DomainSchema, Name extends ViewName<S>> {
|
|
7
|
-
readonly root: Element | string;
|
|
8
|
-
readonly module: ReactRouteModule<S>;
|
|
9
|
-
readonly view: Name;
|
|
10
|
-
/** Defaults to the child-side sandbox handshake. A prebuilt Shell is the full-app escape hatch. */
|
|
11
|
-
readonly config?: ShellConfig | Shell;
|
|
12
|
-
readonly fallback?: ReactNode;
|
|
13
|
-
readonly errorFallback?: (error: unknown, retry: () => void) => ReactNode;
|
|
14
|
-
readonly onError?: (error: unknown) => void;
|
|
15
|
-
}
|
|
16
|
-
export interface MountedDomainFrontend {
|
|
17
|
-
unmount(): void;
|
|
18
|
-
}
|
|
19
|
-
/** Browser bootstrap used by SDK-generated route entries and custom full React apps alike. */
|
|
20
|
-
export declare function mountDomainFrontend<const S extends schema.DomainSchema, const Name extends ViewName<S>>(options: MountDomainFrontendOptions<S, Name>): MountedDomainFrontend;
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=mount-domain-frontend.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mount-domain-frontend.d.ts","sourceRoot":"","sources":["../../src/components/mount-domain-frontend.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAmC,MAAM,uBAAuB,CAAA;AAC9F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAoD,SAAS,EAAE,MAAM,OAAO,CAAA;AAWxF,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,gBAAgB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAA;AAMnG,MAAM,WAAW,0BAA0B,CACzC,CAAC,SAAS,MAAM,CAAC,YAAY,EAC7B,IAAI,SAAS,QAAQ,CAAC,CAAC,CAAC;IAExB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,mGAAmG;IACnG,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAA;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAA;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CACjC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,EACnC,KAAK,CAAC,IAAI,SAAS,QAAQ,CAAC,CAAC,CAAC,EAC9B,OAAO,EAAE,0BAA0B,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,qBAAqB,CAgCrE"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createElement, lazy, Suspense } from 'react';
|
|
3
|
-
import { createRoot } from 'react-dom/client';
|
|
4
|
-
import { useHistoryVersion, useOptionalNavCtx } from '../navigation/scope.context.js';
|
|
5
|
-
import { useDomain } from '../schema/domain.hook.js';
|
|
6
|
-
import { useTargetPath } from '../window/hooks/target-node.hook.js';
|
|
7
|
-
import { defaultViewError, defaultViewLoading, ViewErrorBoundary } from './boundaries.js';
|
|
8
|
-
import { ViewApp } from './view-app.js';
|
|
9
|
-
/** Browser bootstrap used by SDK-generated route entries and custom full React apps alike. */
|
|
10
|
-
export function mountDomainFrontend(options) {
|
|
11
|
-
const rootElement = typeof options.root === 'string' ? document.querySelector(options.root) : options.root;
|
|
12
|
-
if (rootElement === null)
|
|
13
|
-
throw new Error(`React frontend root '${options.root}' was not found.`);
|
|
14
|
-
const route = options.module.routes[options.view];
|
|
15
|
-
if (route === undefined)
|
|
16
|
-
throw new Error(`React View '${options.view}' is not implemented.`);
|
|
17
|
-
const loading = options.fallback ?? defaultViewLoading();
|
|
18
|
-
const errorFallback = options.errorFallback ?? defaultViewError;
|
|
19
|
-
const routeRuntime = createRouteRuntime();
|
|
20
|
-
const root = createRoot(rootElement);
|
|
21
|
-
root.render(_jsx(ViewApp, { config: options.config ?? { mode: 'sandboxed' }, fallback: loading, errorFallback: errorFallback, onError: ({ error }) => options.onError?.(error), children: _jsx(ViewErrorBoundary, { fallback: errorFallback, onError: options.onError, children: (generation) => (_jsx(Suspense, { fallback: loading, children: _jsx(DomainRoute, { module: options.module, name: options.view, generation: generation, runtime: routeRuntime }) })) }) }));
|
|
22
|
-
return Object.freeze({ unmount: () => root.unmount() });
|
|
23
|
-
}
|
|
24
|
-
function DomainRoute(props) {
|
|
25
|
-
const domain = useDomain(props.module.schema);
|
|
26
|
-
const navigation = useOptionalNavCtx();
|
|
27
|
-
useHistoryVersion(navigation?.history ?? null);
|
|
28
|
-
const view = domain[props.name];
|
|
29
|
-
// Domain's schema-indexed conditional retains the exact authored View type,
|
|
30
|
-
// while the runtime member has Core's common rich Definition shape.
|
|
31
|
-
const runtimeView = view;
|
|
32
|
-
const targetPath = useTargetPath();
|
|
33
|
-
const implementation = props.module.routes[props.name];
|
|
34
|
-
const Component = props.runtime.component(props.generation, implementation);
|
|
35
|
-
const declaration = runtimeView.definition;
|
|
36
|
-
const target = declaration.target.kind === 'domain'
|
|
37
|
-
? Object.freeze({ kind: 'domain', origin: runtimeView.origin })
|
|
38
|
-
: targetPath === null
|
|
39
|
-
? missingTarget(runtimeView.name)
|
|
40
|
-
: targetPath;
|
|
41
|
-
const current = new URL(window.location.href);
|
|
42
|
-
const routeParams = navigation?.history.current?.params ?? directRouteParams(current);
|
|
43
|
-
const route = Object.freeze({
|
|
44
|
-
name: props.name,
|
|
45
|
-
href: current.href,
|
|
46
|
-
params: Object.freeze({ ...routeParams }),
|
|
47
|
-
});
|
|
48
|
-
return createElement(Component, { view, target, route });
|
|
49
|
-
}
|
|
50
|
-
function directRouteParams(url) {
|
|
51
|
-
const params = {};
|
|
52
|
-
const prefix = 'astrale.param.';
|
|
53
|
-
for (const key of new Set(url.searchParams.keys())) {
|
|
54
|
-
if (!key.startsWith(prefix))
|
|
55
|
-
continue;
|
|
56
|
-
const name = key.slice(prefix.length);
|
|
57
|
-
if (name.length === 0 || /token|credential|authorization|secret/i.test(name)) {
|
|
58
|
-
throw new TypeError(`React View route param '${name}' is invalid.`);
|
|
59
|
-
}
|
|
60
|
-
const values = url.searchParams.getAll(key);
|
|
61
|
-
if (values.length !== 1)
|
|
62
|
-
throw new TypeError(`React View route param '${name}' is duplicated.`);
|
|
63
|
-
params[name] = values[0];
|
|
64
|
-
}
|
|
65
|
-
return Object.freeze(params);
|
|
66
|
-
}
|
|
67
|
-
function createRouteRuntime() {
|
|
68
|
-
const generations = new Map();
|
|
69
|
-
return {
|
|
70
|
-
component(generation, implementation) {
|
|
71
|
-
let Component = generations.get(generation);
|
|
72
|
-
if (Component === undefined) {
|
|
73
|
-
Component = lazy(async () => {
|
|
74
|
-
const loaded = await implementation.component();
|
|
75
|
-
return { default: loaded.default };
|
|
76
|
-
});
|
|
77
|
-
generations.set(generation, Component);
|
|
78
|
-
}
|
|
79
|
-
return Component;
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function missingTarget(name) {
|
|
84
|
-
throw new Error(`React View '${name}' requires a resource target from the Shell handshake.`);
|
|
85
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Shell, ShellConfig } from '@astrale-os/shell';
|
|
2
|
-
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
-
import type { NavAdapter } from '../navigation/adapters/adapter.js';
|
|
4
|
-
import type { NavTarget } from '../navigation/snapshot.js';
|
|
5
|
-
import type { ShellProviderProps } from '../session/provider.js';
|
|
6
|
-
/** One generated/default root; custom React apps may compose the lower-level providers directly. */
|
|
7
|
-
export declare function ViewApp(props: {
|
|
8
|
-
readonly config: ShellConfig | Shell;
|
|
9
|
-
readonly navigation?: NavAdapter;
|
|
10
|
-
readonly initial?: NavTarget;
|
|
11
|
-
readonly fallback?: ReactNode;
|
|
12
|
-
readonly errorFallback?: ShellProviderProps['errorFallback'];
|
|
13
|
-
readonly onError?: ShellProviderProps['onError'];
|
|
14
|
-
readonly children: ReactNode;
|
|
15
|
-
}): ReactElement;
|
|
16
|
-
//# sourceMappingURL=view-app.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"view-app.d.ts","sourceRoot":"","sources":["../../src/components/view-app.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAShE,oGAAoG;AACpG,wBAAgB,OAAO,CAAC,KAAK,EAAE;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAA;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAA;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAA;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B,GAAG,YAAY,CAWf"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memoryAdapter } from '../navigation/adapters/memory.adapter.js';
|
|
3
|
-
import { urlAdapter } from '../navigation/adapters/url.adapter.js';
|
|
4
|
-
import { NavScope } from '../navigation/scope.context.js';
|
|
5
|
-
import { ShellProvider } from '../session/provider.js';
|
|
6
|
-
import { useShell } from '../session/shell.hook.js';
|
|
7
|
-
import { ViewStage } from '../window/stage.js';
|
|
8
|
-
/** One generated/default root; custom React apps may compose the lower-level providers directly. */
|
|
9
|
-
export function ViewApp(props) {
|
|
10
|
-
return (_jsx(ShellProvider, { config: props.config, fallback: props.fallback, errorFallback: props.errorFallback, onError: props.onError, children: _jsx(ViewAppRuntime, { ...props }) }));
|
|
11
|
-
}
|
|
12
|
-
function ViewAppRuntime(props) {
|
|
13
|
-
const shell = useShell();
|
|
14
|
-
const defaultAdapter = shell.hostCapabilities.navigation.history === 'browser' ? urlAdapter() : memoryAdapter();
|
|
15
|
-
return (_jsxs(NavScope, { adapter: props.navigation ?? defaultAdapter, initial: props.initial, children: [props.children, _jsx(ViewStage, {})] }));
|
|
16
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import type { Domain, Definition } from '@astrale-os/sdk/domain'
|
|
2
|
-
import type { ReactRouteModule, ReactViewModule, ReactViewProps } from '@astrale-os/sdk/react'
|
|
3
|
-
import type { schema } from '@astrale-os/sdk/schema'
|
|
4
|
-
import type { Shell, ShellConfig } from '@astrale-os/shell'
|
|
5
|
-
import type { ComponentType, LazyExoticComponent, ReactElement, ReactNode } from 'react'
|
|
6
|
-
|
|
7
|
-
import { createElement, lazy, Suspense } from 'react'
|
|
8
|
-
import { createRoot } from 'react-dom/client'
|
|
9
|
-
|
|
10
|
-
import { useHistoryVersion, useOptionalNavCtx } from '../navigation/scope.context.js'
|
|
11
|
-
import { useDomain } from '../schema/domain.hook.js'
|
|
12
|
-
import { useTargetPath } from '../window/hooks/target-node.hook.js'
|
|
13
|
-
import { defaultViewError, defaultViewLoading, ViewErrorBoundary } from './boundaries.js'
|
|
14
|
-
import { ViewApp } from './view-app.js'
|
|
15
|
-
|
|
16
|
-
type ViewName<S extends schema.DomainSchema> = Extract<keyof ReactRouteModule<S>['routes'], string>
|
|
17
|
-
type ViewOf<S extends schema.DomainSchema, Name extends ViewName<S>> = Extract<
|
|
18
|
-
Domain<S>[Name],
|
|
19
|
-
Definition<'view'>
|
|
20
|
-
>
|
|
21
|
-
|
|
22
|
-
export interface MountDomainFrontendOptions<
|
|
23
|
-
S extends schema.DomainSchema,
|
|
24
|
-
Name extends ViewName<S>,
|
|
25
|
-
> {
|
|
26
|
-
readonly root: Element | string
|
|
27
|
-
readonly module: ReactRouteModule<S>
|
|
28
|
-
readonly view: Name
|
|
29
|
-
/** Defaults to the child-side sandbox handshake. A prebuilt Shell is the full-app escape hatch. */
|
|
30
|
-
readonly config?: ShellConfig | Shell
|
|
31
|
-
readonly fallback?: ReactNode
|
|
32
|
-
readonly errorFallback?: (error: unknown, retry: () => void) => ReactNode
|
|
33
|
-
readonly onError?: (error: unknown) => void
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface MountedDomainFrontend {
|
|
37
|
-
unmount(): void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Browser bootstrap used by SDK-generated route entries and custom full React apps alike. */
|
|
41
|
-
export function mountDomainFrontend<
|
|
42
|
-
const S extends schema.DomainSchema,
|
|
43
|
-
const Name extends ViewName<S>,
|
|
44
|
-
>(options: MountDomainFrontendOptions<S, Name>): MountedDomainFrontend {
|
|
45
|
-
const rootElement =
|
|
46
|
-
typeof options.root === 'string' ? document.querySelector(options.root) : options.root
|
|
47
|
-
if (rootElement === null) throw new Error(`React frontend root '${options.root}' was not found.`)
|
|
48
|
-
const route = options.module.routes[options.view]
|
|
49
|
-
if (route === undefined) throw new Error(`React View '${options.view}' is not implemented.`)
|
|
50
|
-
const loading = options.fallback ?? defaultViewLoading()
|
|
51
|
-
const errorFallback = options.errorFallback ?? defaultViewError
|
|
52
|
-
const routeRuntime = createRouteRuntime()
|
|
53
|
-
const root = createRoot(rootElement)
|
|
54
|
-
root.render(
|
|
55
|
-
<ViewApp
|
|
56
|
-
config={options.config ?? { mode: 'sandboxed' }}
|
|
57
|
-
fallback={loading}
|
|
58
|
-
errorFallback={errorFallback}
|
|
59
|
-
onError={({ error }) => options.onError?.(error)}
|
|
60
|
-
>
|
|
61
|
-
<ViewErrorBoundary fallback={errorFallback} onError={options.onError}>
|
|
62
|
-
{(generation) => (
|
|
63
|
-
<Suspense fallback={loading}>
|
|
64
|
-
<DomainRoute
|
|
65
|
-
module={options.module}
|
|
66
|
-
name={options.view}
|
|
67
|
-
generation={generation}
|
|
68
|
-
runtime={routeRuntime}
|
|
69
|
-
/>
|
|
70
|
-
</Suspense>
|
|
71
|
-
)}
|
|
72
|
-
</ViewErrorBoundary>
|
|
73
|
-
</ViewApp>,
|
|
74
|
-
)
|
|
75
|
-
return Object.freeze({ unmount: () => root.unmount() })
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function DomainRoute<S extends schema.DomainSchema, Name extends ViewName<S>>(props: {
|
|
79
|
-
readonly module: ReactRouteModule<S>
|
|
80
|
-
readonly name: Name
|
|
81
|
-
readonly generation: number
|
|
82
|
-
readonly runtime: RouteRuntime
|
|
83
|
-
}): ReactElement {
|
|
84
|
-
const domain = useDomain(props.module.schema)
|
|
85
|
-
const navigation = useOptionalNavCtx()
|
|
86
|
-
useHistoryVersion(navigation?.history ?? null)
|
|
87
|
-
const view = domain[props.name] as ViewOf<S, Name>
|
|
88
|
-
// Domain's schema-indexed conditional retains the exact authored View type,
|
|
89
|
-
// while the runtime member has Core's common rich Definition shape.
|
|
90
|
-
const runtimeView = view as unknown as Definition<'view'>
|
|
91
|
-
const targetPath = useTargetPath()
|
|
92
|
-
const implementation = props.module.routes[props.name]!
|
|
93
|
-
const Component = props.runtime.component<ViewOf<S, Name>>(props.generation, implementation)
|
|
94
|
-
const declaration = runtimeView.definition as { readonly target: { readonly kind: string } }
|
|
95
|
-
const target =
|
|
96
|
-
declaration.target.kind === 'domain'
|
|
97
|
-
? Object.freeze({ kind: 'domain' as const, origin: runtimeView.origin })
|
|
98
|
-
: targetPath === null
|
|
99
|
-
? missingTarget(runtimeView.name)
|
|
100
|
-
: targetPath
|
|
101
|
-
const current = new URL(window.location.href)
|
|
102
|
-
const routeParams = navigation?.history.current?.params ?? directRouteParams(current)
|
|
103
|
-
const route = Object.freeze({
|
|
104
|
-
name: props.name,
|
|
105
|
-
href: current.href,
|
|
106
|
-
params: Object.freeze({ ...routeParams }),
|
|
107
|
-
})
|
|
108
|
-
return createElement(Component, { view, target, route } as unknown as ReactViewProps<
|
|
109
|
-
ViewOf<S, Name>
|
|
110
|
-
>)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function directRouteParams(url: URL): Readonly<Record<string, string>> {
|
|
114
|
-
const params: Record<string, string> = {}
|
|
115
|
-
const prefix = 'astrale.param.'
|
|
116
|
-
for (const key of new Set(url.searchParams.keys())) {
|
|
117
|
-
if (!key.startsWith(prefix)) continue
|
|
118
|
-
const name = key.slice(prefix.length)
|
|
119
|
-
if (name.length === 0 || /token|credential|authorization|secret/i.test(name)) {
|
|
120
|
-
throw new TypeError(`React View route param '${name}' is invalid.`)
|
|
121
|
-
}
|
|
122
|
-
const values = url.searchParams.getAll(key)
|
|
123
|
-
if (values.length !== 1) throw new TypeError(`React View route param '${name}' is duplicated.`)
|
|
124
|
-
params[name] = values[0]!
|
|
125
|
-
}
|
|
126
|
-
return Object.freeze(params)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
interface RouteRuntime {
|
|
130
|
-
component<View extends Definition<'view'>>(
|
|
131
|
-
generation: number,
|
|
132
|
-
implementation: { readonly component: () => Promise<ReactViewModule<View>> },
|
|
133
|
-
): ComponentType<ReactViewProps<View>>
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function createRouteRuntime(): RouteRuntime {
|
|
137
|
-
const generations = new Map<number, LazyExoticComponent<ComponentType<ReactViewProps<never>>>>()
|
|
138
|
-
return {
|
|
139
|
-
component<View extends Definition<'view'>>(
|
|
140
|
-
generation: number,
|
|
141
|
-
implementation: { readonly component: () => Promise<ReactViewModule<View>> },
|
|
142
|
-
): ComponentType<ReactViewProps<View>> {
|
|
143
|
-
let Component = generations.get(generation)
|
|
144
|
-
if (Component === undefined) {
|
|
145
|
-
Component = lazy(async () => {
|
|
146
|
-
const loaded = await implementation.component()
|
|
147
|
-
return { default: loaded.default as ComponentType<ReactViewProps<never>> }
|
|
148
|
-
})
|
|
149
|
-
generations.set(generation, Component)
|
|
150
|
-
}
|
|
151
|
-
return Component as unknown as ComponentType<ReactViewProps<View>>
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function missingTarget(name: string): never {
|
|
157
|
-
throw new Error(`React View '${name}' requires a resource target from the Shell handshake.`)
|
|
158
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { Shell, ShellConfig } from '@astrale-os/shell'
|
|
2
|
-
import type { ReactElement, ReactNode } from 'react'
|
|
3
|
-
|
|
4
|
-
import type { NavAdapter } from '../navigation/adapters/adapter.js'
|
|
5
|
-
import type { NavTarget } from '../navigation/snapshot.js'
|
|
6
|
-
import type { ShellProviderProps } from '../session/provider.js'
|
|
7
|
-
|
|
8
|
-
import { memoryAdapter } from '../navigation/adapters/memory.adapter.js'
|
|
9
|
-
import { urlAdapter } from '../navigation/adapters/url.adapter.js'
|
|
10
|
-
import { NavScope } from '../navigation/scope.context.js'
|
|
11
|
-
import { ShellProvider } from '../session/provider.js'
|
|
12
|
-
import { useShell } from '../session/shell.hook.js'
|
|
13
|
-
import { ViewStage } from '../window/stage.js'
|
|
14
|
-
|
|
15
|
-
/** One generated/default root; custom React apps may compose the lower-level providers directly. */
|
|
16
|
-
export function ViewApp(props: {
|
|
17
|
-
readonly config: ShellConfig | Shell
|
|
18
|
-
readonly navigation?: NavAdapter
|
|
19
|
-
readonly initial?: NavTarget
|
|
20
|
-
readonly fallback?: ReactNode
|
|
21
|
-
readonly errorFallback?: ShellProviderProps['errorFallback']
|
|
22
|
-
readonly onError?: ShellProviderProps['onError']
|
|
23
|
-
readonly children: ReactNode
|
|
24
|
-
}): ReactElement {
|
|
25
|
-
return (
|
|
26
|
-
<ShellProvider
|
|
27
|
-
config={props.config}
|
|
28
|
-
fallback={props.fallback}
|
|
29
|
-
errorFallback={props.errorFallback}
|
|
30
|
-
onError={props.onError}
|
|
31
|
-
>
|
|
32
|
-
<ViewAppRuntime {...props} />
|
|
33
|
-
</ShellProvider>
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function ViewAppRuntime(
|
|
38
|
-
props: Omit<Parameters<typeof ViewApp>[0], 'config' | 'fallback'>,
|
|
39
|
-
): ReactElement {
|
|
40
|
-
const shell = useShell()
|
|
41
|
-
const defaultAdapter =
|
|
42
|
-
shell.hostCapabilities.navigation.history === 'browser' ? urlAdapter() : memoryAdapter()
|
|
43
|
-
return (
|
|
44
|
-
<NavScope adapter={props.navigation ?? defaultAdapter} initial={props.initial}>
|
|
45
|
-
{props.children}
|
|
46
|
-
<ViewStage />
|
|
47
|
-
</NavScope>
|
|
48
|
-
)
|
|
49
|
-
}
|