mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(gateway): type portal open credentials
This commit is contained in:
@@ -19277,10 +19277,10 @@ public struct PortalSummary: Codable, Sendable {
|
||||
public struct PortalListParams: Codable, Sendable {}
|
||||
|
||||
public struct PortalListResult: Codable, Sendable {
|
||||
public let portals: [PortalOpenResult]
|
||||
public let portals: [PortalSummary]
|
||||
|
||||
public init(
|
||||
portals: [PortalOpenResult])
|
||||
portals: [PortalSummary])
|
||||
{
|
||||
self.portals = portals
|
||||
}
|
||||
@@ -19321,8 +19321,8 @@ public struct PortalOpenResult: Codable, Sendable {
|
||||
public let title: String
|
||||
public let port: Int
|
||||
public let listenport: Int
|
||||
public let tokenquery: String?
|
||||
public let url: String?
|
||||
public let tokenquery: String
|
||||
public let url: String
|
||||
public let publicurl: String
|
||||
public let path: String?
|
||||
public let description: String?
|
||||
@@ -19333,8 +19333,8 @@ public struct PortalOpenResult: Codable, Sendable {
|
||||
title: String,
|
||||
port: Int,
|
||||
listenport: Int,
|
||||
tokenquery: String? = nil,
|
||||
url: String? = nil,
|
||||
tokenquery: String,
|
||||
url: String,
|
||||
publicurl: String,
|
||||
path: String? = nil,
|
||||
description: String? = nil,
|
||||
@@ -19395,10 +19395,10 @@ public struct PortalCloseResult: Codable, Sendable {
|
||||
}
|
||||
|
||||
public struct PortalChangedEvent: Codable, Sendable {
|
||||
public let portals: [PortalOpenResult]
|
||||
public let portals: [PortalSummary]
|
||||
|
||||
public init(
|
||||
portals: [PortalOpenResult])
|
||||
portals: [PortalSummary])
|
||||
{
|
||||
self.portals = portals
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ describe("portal protocol schemas", () => {
|
||||
expect(Value.Check(PortalListResultSchema, { portals: [portal] })).toBe(true);
|
||||
const { tokenQuery: _tokenQuery, url: _url, ...redactedPortal } = portal;
|
||||
expect(Value.Check(PortalSummarySchema, redactedPortal)).toBe(true);
|
||||
expect(Value.Check(PortalOpenResultSchema, redactedPortal)).toBe(false);
|
||||
expect(Value.Check(PortalCloseResultSchema, { closed: true })).toBe(true);
|
||||
expect(Value.Check(PortalChangedEventSchema, { portals: [portal] })).toBe(true);
|
||||
const { publicUrl: _publicUrl, ...missingPublicUrl } = portal;
|
||||
|
||||
@@ -2,17 +2,25 @@ import { Type, type Static } from "typebox";
|
||||
import { closedObject } from "./closed-object.js";
|
||||
import { NonEmptyString } from "./primitives.js";
|
||||
|
||||
export const PortalSummarySchema = closedObject({
|
||||
const PortalSummaryIdentityFields = {
|
||||
id: NonEmptyString,
|
||||
title: NonEmptyString,
|
||||
port: Type.Integer({ minimum: 1, maximum: 65_535 }),
|
||||
listenPort: Type.Integer({ minimum: 1, maximum: 65_535 }),
|
||||
tokenQuery: Type.Optional(NonEmptyString),
|
||||
url: Type.Optional(NonEmptyString),
|
||||
};
|
||||
|
||||
const PortalSummaryMetadataFields = {
|
||||
publicUrl: NonEmptyString,
|
||||
path: Type.Optional(Type.String({ pattern: "^/" })),
|
||||
description: Type.Optional(Type.String()),
|
||||
createdAtMs: Type.Integer({ minimum: 0 }),
|
||||
};
|
||||
|
||||
export const PortalSummarySchema = closedObject({
|
||||
...PortalSummaryIdentityFields,
|
||||
tokenQuery: Type.Optional(NonEmptyString),
|
||||
url: Type.Optional(NonEmptyString),
|
||||
...PortalSummaryMetadataFields,
|
||||
});
|
||||
|
||||
export const PortalListParamsSchema = closedObject({});
|
||||
@@ -26,7 +34,12 @@ export const PortalOpenParamsSchema = closedObject({
|
||||
description: Type.Optional(Type.String()),
|
||||
path: Type.Optional(Type.String({ pattern: "^/" })),
|
||||
});
|
||||
export const PortalOpenResultSchema = PortalSummarySchema;
|
||||
export const PortalOpenResultSchema = closedObject({
|
||||
...PortalSummaryIdentityFields,
|
||||
tokenQuery: NonEmptyString,
|
||||
url: NonEmptyString,
|
||||
...PortalSummaryMetadataFields,
|
||||
});
|
||||
|
||||
export const PortalCloseParamsSchema = closedObject({ id: NonEmptyString });
|
||||
export const PortalCloseResultSchema = closedObject({ closed: Type.Boolean() });
|
||||
|
||||
@@ -4,7 +4,10 @@ import { createServer as createHttpsServer } from "node:https";
|
||||
import type { AddressInfo } from "node:net";
|
||||
import type { Duplex } from "node:stream";
|
||||
import type { TlsOptions } from "node:tls";
|
||||
import type { PortalSummary } from "../../../packages/gateway-protocol/src/index.js";
|
||||
import type {
|
||||
PortalOpenResult,
|
||||
PortalSummary,
|
||||
} from "../../../packages/gateway-protocol/src/index.js";
|
||||
import { listenGatewayHttpServer } from "../server/http-listen.js";
|
||||
import { handlePortalProxyRequest, handlePortalProxyUpgrade } from "./portal-http-proxy.js";
|
||||
|
||||
@@ -33,7 +36,7 @@ type GatewayPortalOpenParams = {
|
||||
};
|
||||
|
||||
export type GatewayPortalService = {
|
||||
open: (params: GatewayPortalOpenParams) => Promise<PortalSummary>;
|
||||
open: (params: GatewayPortalOpenParams) => Promise<PortalOpenResult>;
|
||||
list: () => PortalSummary[];
|
||||
close: (id: string) => Promise<void>;
|
||||
closeAll: () => Promise<void>;
|
||||
@@ -79,7 +82,7 @@ export function createGatewayPortalService(params: {
|
||||
const operations = new Map<string, Promise<void>>();
|
||||
let closed = false;
|
||||
|
||||
const summarize = (portal: PortalEntry): PortalSummary => {
|
||||
const summarize = (portal: PortalEntry): PortalOpenResult => {
|
||||
const host = params.httpBindHosts[0];
|
||||
if (!host) {
|
||||
throw new Error("Gateway listener must start before opening a portal");
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { PortalSummary } from "../../../packages/gateway-protocol/src/index.js";
|
||||
import type {
|
||||
PortalOpenResult,
|
||||
PortalSummary,
|
||||
} from "../../../packages/gateway-protocol/src/index.js";
|
||||
import { resolveCoreOperatorGatewayMethodScope } from "../methods/core-descriptors.js";
|
||||
import type { GatewayPortalService } from "../portals/portal-service.js";
|
||||
import { createGatewayBroadcaster } from "../server-broadcast.js";
|
||||
import type { GatewayWsClient } from "../server/ws-types.js";
|
||||
import { portalHandlers } from "./portals.js";
|
||||
|
||||
const portal: PortalSummary = {
|
||||
const portal = {
|
||||
id: "p3000",
|
||||
title: "App",
|
||||
port: 3000,
|
||||
@@ -15,7 +18,7 @@ const portal: PortalSummary = {
|
||||
url: `http://127.0.0.1:43123/?openclaw_portal=${"a".repeat(64)}`,
|
||||
publicUrl: "http://127.0.0.1:43123/",
|
||||
createdAtMs: 1,
|
||||
};
|
||||
} satisfies PortalOpenResult;
|
||||
|
||||
function harness(service?: GatewayPortalService, scopes = ["operator.write"]) {
|
||||
const broadcast = vi.fn();
|
||||
|
||||
@@ -17,7 +17,7 @@ type PortalsPageTestElement = HTMLElement & {
|
||||
updateComplete: Promise<boolean>;
|
||||
};
|
||||
|
||||
const portal: PortalSummary = {
|
||||
const portal = {
|
||||
id: "p3000",
|
||||
title: "Seeded app",
|
||||
port: 3000,
|
||||
@@ -28,7 +28,7 @@ const portal: PortalSummary = {
|
||||
path: "/app",
|
||||
description: "Use the seeded test account.",
|
||||
createdAtMs: 1_000,
|
||||
};
|
||||
} satisfies PortalSummary;
|
||||
|
||||
function createContext(
|
||||
methods: string[],
|
||||
|
||||
Reference in New Issue
Block a user