feat: expose canonical module display URLs
This commit is contained in:
@@ -105,6 +105,8 @@ export interface HostModuleUiDescriptor {
|
||||
/** Server-produced. The shell resolves it against `apiBaseUrl` and hands it to the generic loader
|
||||
* unchanged; it never constructs, parses, or pattern-matches this URL. */
|
||||
readonly uiUrl: string;
|
||||
/** Server-produced page for this module's display, when it publishes one. */
|
||||
readonly displayPageUrl: string | undefined;
|
||||
/** Server-produced root of this module's own HTTP API. */
|
||||
readonly apiBaseUrl: string;
|
||||
/** Server-produced root for this module's own live channels. */
|
||||
@@ -214,8 +216,24 @@ function parseDescriptor(entry: unknown): HostModuleUiDescriptor {
|
||||
const uiUrl = isRecord(entry) ? rootRelativePath(entry.ui, "url") : undefined;
|
||||
const apiBaseUrl = isRecord(entry) ? rootRelativePath(entry.api, "baseUrl") : undefined;
|
||||
const realtimeBaseUrl = isRecord(entry) ? rootRelativePath(entry.realtime, "baseUrl") : undefined;
|
||||
const displayPageUrl =
|
||||
isRecord(entry) && entry.display !== null ? rootRelativePath(entry.display, "url") : undefined;
|
||||
const permissions = isRecord(entry) ? entry.permissions : undefined;
|
||||
if (
|
||||
!hasExactKeys(entry, [
|
||||
"api",
|
||||
"contributions",
|
||||
"display",
|
||||
"id",
|
||||
"permissions",
|
||||
"realtime",
|
||||
"ui",
|
||||
"version",
|
||||
]) ||
|
||||
!hasExactKeys(entry.api, ["baseUrl"]) ||
|
||||
!hasExactKeys(entry.realtime, ["baseUrl"]) ||
|
||||
!hasExactKeys(entry.ui, ["url"]) ||
|
||||
(entry.display !== null && !hasExactKeys(entry.display, ["url"])) ||
|
||||
id === undefined ||
|
||||
version === undefined ||
|
||||
uiUrl === undefined ||
|
||||
@@ -229,6 +247,7 @@ function parseDescriptor(entry: unknown): HostModuleUiDescriptor {
|
||||
return Object.freeze({
|
||||
apiBaseUrl,
|
||||
contributions: parseContributions(isRecord(entry) ? entry.contributions : undefined),
|
||||
displayPageUrl,
|
||||
id,
|
||||
permissions: Object.freeze([...(permissions as string[])]),
|
||||
realtimeBaseUrl,
|
||||
@@ -323,12 +342,14 @@ export function parseHostModuleDisplay(payload: unknown): HostModuleDisplayRespo
|
||||
"contributions",
|
||||
"display",
|
||||
"id",
|
||||
"page",
|
||||
"permissions",
|
||||
"realtime",
|
||||
"version",
|
||||
]) ||
|
||||
!hasExactKeys(entry.api, ["baseUrl"]) ||
|
||||
!hasExactKeys(entry.display, ["url"]) ||
|
||||
!hasExactKeys(entry.page, ["url"]) ||
|
||||
!hasExactKeys(entry.realtime, ["baseUrl"])
|
||||
) {
|
||||
throw new HostProtocolError("HOST_RESPONSE_INVALID");
|
||||
@@ -338,6 +359,7 @@ export function parseHostModuleDisplay(payload: unknown): HostModuleDisplayRespo
|
||||
const version = nonEmptyString(entry.version);
|
||||
const apiBaseUrl = rootRelativePath(entry.api, "baseUrl");
|
||||
const uiUrl = rootRelativePath(entry.display, "url");
|
||||
const displayPageUrl = rootRelativePath(entry.page, "url");
|
||||
const realtimeBaseUrl = rootRelativePath(entry.realtime, "baseUrl");
|
||||
const permissions = entry.permissions;
|
||||
if (
|
||||
@@ -347,6 +369,7 @@ export function parseHostModuleDisplay(payload: unknown): HostModuleDisplayRespo
|
||||
!isSemanticVersion(version) ||
|
||||
apiBaseUrl === undefined ||
|
||||
uiUrl === undefined ||
|
||||
displayPageUrl === undefined ||
|
||||
realtimeBaseUrl === undefined ||
|
||||
!Array.isArray(permissions) ||
|
||||
permissions.some((permission) => typeof permission !== "string" || permission.length === 0) ||
|
||||
@@ -359,6 +382,7 @@ export function parseHostModuleDisplay(payload: unknown): HostModuleDisplayRespo
|
||||
module: Object.freeze({
|
||||
apiBaseUrl,
|
||||
contributions: parseContributions(entry.contributions),
|
||||
displayPageUrl,
|
||||
id,
|
||||
permissions: Object.freeze([...(permissions as string[])]),
|
||||
realtimeBaseUrl,
|
||||
|
||||
@@ -350,6 +350,10 @@ export function createModuleUiContext(options: CreateModuleUiContextOptions): Mo
|
||||
options.descriptor,
|
||||
options.importModule,
|
||||
),
|
||||
display:
|
||||
options.descriptor.displayPageUrl === undefined
|
||||
? undefined
|
||||
: Object.freeze({ url: resolveApiUrl(options.config, options.descriptor.displayPageUrl) }),
|
||||
moduleId: options.descriptor.id,
|
||||
permissions: Object.freeze({ has: (permissionId: string) => granted.has(permissionId) }),
|
||||
principal: options.principal,
|
||||
|
||||
Reference in New Issue
Block a user