feat: add native module realtime transport
This commit is contained in:
@@ -40,6 +40,7 @@ const inventoryPayload = {
|
||||
api: { baseUrl: "/api/v1/modules/example" },
|
||||
id: "example",
|
||||
permissions: ["example.records.read"],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/example" },
|
||||
ui: { url: "/api/v1/module-ui/example/0.1.0" },
|
||||
version: "0.1.0",
|
||||
},
|
||||
@@ -50,6 +51,7 @@ const calendarDescriptor: HostModuleUiDescriptor = {
|
||||
apiBaseUrl: "/api/v1/modules/calendar",
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/calendar",
|
||||
uiUrl: "/api/v1/module-ui/calendar/2.0.0",
|
||||
version: "2.0.0",
|
||||
};
|
||||
@@ -69,6 +71,7 @@ const navigationPayload = {
|
||||
api: { baseUrl: "/api/v1/modules/calendar" },
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtime: { baseUrl: "/api/v1/module-realtime/calendar" },
|
||||
ui: { url: "/api/v1/module-ui/calendar/2.0.0" },
|
||||
version: "2.0.0",
|
||||
},
|
||||
@@ -81,6 +84,7 @@ const exampleDescriptor: HostModuleUiDescriptor = {
|
||||
apiBaseUrl: "/api/v1/modules/example",
|
||||
id: "example",
|
||||
permissions: ["example.records.read"],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/example",
|
||||
uiUrl: "/api/v1/module-ui/example/0.1.0",
|
||||
version: "0.1.0",
|
||||
};
|
||||
@@ -103,14 +107,18 @@ describe("host protocol — descriptor validation", () => {
|
||||
{ id: "example", version: "0.1.0" },
|
||||
{ ...base, ui: {} },
|
||||
{ ...base, api: { baseUrl: "" } },
|
||||
{ ...base, realtime: {} },
|
||||
{ ...base, permissions: "example.records.read" },
|
||||
{ ...base, permissions: [42] },
|
||||
// Both URLs must be root-relative, so a value that would resolve against another origin is
|
||||
// Every URL must be root-relative, so a value that would resolve against another origin is
|
||||
// refused rather than silently used to fetch browser code.
|
||||
{ ...base, ui: { url: "https://evil.example.test/x.js" } },
|
||||
{ ...base, ui: { url: "//evil.example.test/x.js" } },
|
||||
{ ...base, ui: { url: "relative/x.js" } },
|
||||
{ ...base, api: { baseUrl: "https://evil.example.test/api" } },
|
||||
{ ...base, realtime: { baseUrl: "https://evil.example.test/live" } },
|
||||
{ ...base, realtime: { baseUrl: "//evil.example.test/live" } },
|
||||
{ ...base, realtime: { baseUrl: "/\\evil.example.test/live" } },
|
||||
];
|
||||
for (const module of malformed) {
|
||||
expect(
|
||||
@@ -366,6 +374,7 @@ describe("module UI host context", () => {
|
||||
apiBaseUrl: "/api/v1/modules/calendar",
|
||||
id: "calendar",
|
||||
permissions: [],
|
||||
realtimeBaseUrl: "/api/v1/module-realtime/calendar",
|
||||
uiUrl: "/api/v1/module-ui/calendar/2.0.0",
|
||||
version: "2.0.0",
|
||||
};
|
||||
@@ -392,12 +401,18 @@ describe("module UI host context", () => {
|
||||
expect(none.has("core.authorization.grants.manage")).toBe(false);
|
||||
});
|
||||
|
||||
it("exposes exactly the four contract members and the browser principal", () => {
|
||||
it("exposes exactly the five contract members and the browser principal", () => {
|
||||
const { implementation } = recordingFetch();
|
||||
|
||||
const context = contextFor(implementation);
|
||||
|
||||
expect(Object.keys(context).sort()).toEqual(["api", "moduleId", "permissions", "principal"]);
|
||||
expect(Object.keys(context).sort()).toEqual([
|
||||
"api",
|
||||
"moduleId",
|
||||
"permissions",
|
||||
"principal",
|
||||
"realtime",
|
||||
]);
|
||||
expect(context.moduleId).toBe("example");
|
||||
expect(context.principal).toEqual({ kind: "authenticated", userId: "user-1" });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user