feat: expose canonical module display URLs
This commit is contained in:
@@ -52,6 +52,7 @@ function descriptorPayload(
|
||||
api: { baseUrl: `/api/v1/modules/${id}` },
|
||||
display: { url: `/api/v1/module-ui/${id}/${version}/display` },
|
||||
id,
|
||||
page: { url: `/display/${id}` },
|
||||
permissions: [`${id}.slideshow.view`],
|
||||
realtime: { baseUrl: `/api/v1/module-realtime/${id}` },
|
||||
version,
|
||||
@@ -240,6 +241,7 @@ describe("display host — full-viewport boundary", () => {
|
||||
expect(Object.keys(seenContext ?? {}).sort()).toEqual([
|
||||
"api",
|
||||
"contributions",
|
||||
"display",
|
||||
"moduleId",
|
||||
"permissions",
|
||||
"principal",
|
||||
@@ -334,6 +336,7 @@ describe("display host — full-viewport boundary", () => {
|
||||
module: {
|
||||
contributions: [],
|
||||
api: { baseUrl: "/api/v1/modules/announcements" },
|
||||
display: { url: "/display/announcements" },
|
||||
id: "announcements",
|
||||
permissions: ["announcements.slideshow.view"],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/announcements" },
|
||||
|
||||
@@ -22,6 +22,7 @@ function displayPayload(overrides: Record<string, unknown> = {}): {
|
||||
api: { baseUrl: "/api/v1/modules/announcements" },
|
||||
display: { url: "/api/v1/module-ui/announcements/1.2.0/display" },
|
||||
id: "announcements",
|
||||
page: { url: "/display/announcements" },
|
||||
permissions: ["announcements.slideshow.view"],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/announcements" },
|
||||
version: "1.2.0",
|
||||
@@ -45,6 +46,7 @@ describe("display host protocol — strict descriptor", () => {
|
||||
module: {
|
||||
apiBaseUrl: "/api/v1/modules/announcements",
|
||||
contributions: [],
|
||||
displayPageUrl: "/display/announcements",
|
||||
id: "announcements",
|
||||
permissions: ["announcements.slideshow.view"],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/announcements",
|
||||
|
||||
@@ -43,6 +43,7 @@ function entry(id: string, name: string, version = "0.1.0", permissions: readonl
|
||||
module: {
|
||||
contributions: [],
|
||||
api: { baseUrl: `/api/v1/modules/${id}` },
|
||||
display: null,
|
||||
id,
|
||||
permissions,
|
||||
realtime: { baseUrl: `/api/v1/module-realtime/${id}` },
|
||||
|
||||
@@ -39,6 +39,7 @@ const inventoryPayload = {
|
||||
{
|
||||
contributions: [],
|
||||
api: { baseUrl: "/api/v1/modules/example" },
|
||||
display: { url: "/display/example" },
|
||||
id: "example",
|
||||
permissions: ["example.records.read"],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/example" },
|
||||
@@ -51,6 +52,7 @@ const inventoryPayload = {
|
||||
const calendarDescriptor: HostModuleUiDescriptor = {
|
||||
contributions: [],
|
||||
apiBaseUrl: "/api/v1/modules/calendar",
|
||||
displayPageUrl: undefined,
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/calendar",
|
||||
@@ -72,6 +74,7 @@ const navigationPayload = {
|
||||
module: {
|
||||
contributions: [],
|
||||
api: { baseUrl: "/api/v1/modules/calendar" },
|
||||
display: null,
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/calendar" },
|
||||
@@ -86,6 +89,7 @@ const navigationPayload = {
|
||||
const exampleDescriptor: HostModuleUiDescriptor = {
|
||||
contributions: [],
|
||||
apiBaseUrl: "/api/v1/modules/example",
|
||||
displayPageUrl: "/display/example",
|
||||
id: "example",
|
||||
permissions: ["example.records.read"],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/example",
|
||||
@@ -409,6 +413,7 @@ describe("module UI host context", () => {
|
||||
const calendar: HostModuleUiDescriptor = {
|
||||
contributions: [],
|
||||
apiBaseUrl: "/api/v1/modules/calendar",
|
||||
displayPageUrl: undefined,
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/calendar",
|
||||
@@ -438,7 +443,18 @@ describe("module UI host context", () => {
|
||||
expect(none.has("core.authorization.grants.manage")).toBe(false);
|
||||
});
|
||||
|
||||
it("exposes exactly the six contract members and the browser principal", () => {
|
||||
it("exposes the host-owned display page at the API origin in split-origin deployments", () => {
|
||||
const { implementation } = recordingFetch();
|
||||
const context = createModuleUiContext({
|
||||
config: { apiBaseUrl: "https://api.example.test", fetch: implementation },
|
||||
descriptor: exampleDescriptor,
|
||||
principal: { kind: "authenticated", userId: "user-1" },
|
||||
});
|
||||
|
||||
expect(context.display?.url).toBe("https://api.example.test/display/example");
|
||||
});
|
||||
|
||||
it("exposes exactly the seven contract members and the browser principal", () => {
|
||||
const { implementation } = recordingFetch();
|
||||
|
||||
const context = contextFor(implementation);
|
||||
@@ -446,6 +462,7 @@ describe("module UI host context", () => {
|
||||
expect(Object.keys(context).sort()).toEqual([
|
||||
"api",
|
||||
"contributions",
|
||||
"display",
|
||||
"moduleId",
|
||||
"permissions",
|
||||
"principal",
|
||||
|
||||
@@ -139,6 +139,7 @@ function descriptor(overrides: Partial<HostModuleUiDescriptor> = {}): HostModule
|
||||
version: "1.0.0",
|
||||
},
|
||||
],
|
||||
displayPageUrl: "/display/signage",
|
||||
id: "signage",
|
||||
permissions: [],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/signage",
|
||||
|
||||
@@ -12,6 +12,7 @@ const apiBaseUrl = "https://ekklesia.example.test";
|
||||
const exampleDescriptor: HostModuleUiDescriptor = {
|
||||
contributions: [],
|
||||
apiBaseUrl: "/api/v1/modules/example",
|
||||
displayPageUrl: undefined,
|
||||
id: "example",
|
||||
permissions: ["example.state.read"],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/example",
|
||||
|
||||
Reference in New Issue
Block a user