diff --git a/package.json b/package.json index b71a832..b6f5a16 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,10 @@ ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" + }, + "./rpc": { + "types": "./dist/rpc.d.ts", + "default": "./dist/rpc.js" } }, "scripts": { @@ -23,5 +27,8 @@ "devDependencies": { "@types/node": "^24", "typescript": "^5.9.3" + }, + "dependencies": { + "zod": "^4.3.6" } } diff --git a/src/index.ts b/src/index.ts index 1fe1d1e..b87a6c0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,7 @@ +import z from "zod"; + +export * from "./rpc.js"; + export const CONTROL_PLANE_DEFAULT_HOST = "127.0.0.1"; export const CONTROL_PLANE_DEFAULT_PORT = 6246; export const CONTROL_PLANE_DEFAULT_URL = `http://${CONTROL_PLANE_DEFAULT_HOST}:${CONTROL_PLANE_DEFAULT_PORT}`; @@ -29,2113 +33,935 @@ export const CONTROL_PLANE_ROUTES = { browserSocket: "/ws", } as const; -export type ControlPlaneRunRequest = { - target: string; -}; - -export type ControlPlaneCheckRequest = { - packageName: string; - rev: string; -}; - -export type ControlPlaneCutoverRequest = { - targets: string[]; -}; - -export type ControlPlaneClearStateRequest = { - packageName: string; - recursive?: boolean; -}; - -export type ControlPlaneDescribeRequest = { - packageName: string; - rev: string; -}; - -export type ControlPlaneLogsRequest = { - packageName: string; - tail?: number; - stream?: "stdout" | "stderr" | "all"; -}; - -export type ControlPlaneErrorsRequest = { - packageName?: string; - stateContextId?: string; - tail?: number; - acknowledge?: boolean; -}; - -export type ControlPlaneReplEvalRequest = { - sessionId?: string; - code: string; - autoClose?: boolean; - defaultStateContextId?: string | null; -}; - -export type ControlPlaneReplCloseRequest = { - sessionId: string; -}; - -export type ControlPlaneDeviceTarget = { - packageName: string; - stateContextId: string; - surfaceId: string; - requestFullscreen?: boolean; -}; - -export type ControlPlaneDeviceViewport = { - width: number; - height: number; - pixelRatio: number | null; -}; - -export type ControlPlaneDevice = { - deviceId: string; - name: string | null; - createdAt: string; - lastSeenAt: string | null; - connected: boolean; - assignment: ControlPlaneDeviceTarget | null; - configuredAssignment: ControlPlaneDeviceTarget | null; - identifyUntil: string | null; - lastUserAgent: string | null; - viewport: ControlPlaneDeviceViewport | null; -}; - -export type ControlPlaneDevicesResponse = { - devices: ControlPlaneDevice[]; -}; - -export type ControlPlaneDeviceAssignRequest = { - deviceId: string; - target: ControlPlaneDeviceTarget | null; -}; - -export type ControlPlaneDeviceRenameRequest = { - deviceId: string; - name: string | null; -}; - -export type ControlPlaneDeviceRemoveRequest = { - deviceId: string; -}; - -export type ControlPlaneDeviceIdentifyRequest = { - deviceId: string; - durationMs?: number; -}; - -export type ControlPlaneDeviceSessionRequest = { - deviceId: string; - sessionToken: string; - requestedTarget?: ControlPlaneDeviceTarget | null; - userAgent?: string | null; - viewport?: ControlPlaneDeviceViewport | null; -}; - -export type ControlPlaneDeviceSessionResponse = { - device: ControlPlaneDevice; -}; - -export type ControlPlanePublicAccessTarget = - | { - kind: "device"; - target?: ControlPlaneDeviceTarget | null; - } - | { - kind: "browser-surface"; - packageName?: string; - stateContextId: string; - surfaceId: string; - requestFullscreen?: boolean; - } - | { - kind: "remote-dom"; - packageName?: string; - stateContextId: string; - }; - -export type ControlPlanePublicAuthGrantRequest = { - target: ControlPlanePublicAccessTarget; -}; - -export type ControlPlanePublicAuthGrantResponse = { - authGrant: string; - target: ControlPlanePublicAccessTarget; -}; - -export type ControlPlanePublicAuthGrantRevokeRequest = { - authGrant: string; -}; - -export type ControlPlanePublicAuthGrantRevokeResponse = { - revoked: boolean; -}; - -export type ControlPlanePublicSessionRequest = { - authGrant: string; -}; - -export type ControlPlanePublicSessionResponse = { - sessionToken: string; - target: ControlPlanePublicAccessTarget; - expiresAt: string; -}; - -export type ControlPlaneSurfaceSessionRequest = { - target: Extract< - ControlPlanePublicAccessTarget, - { kind: "browser-surface" | "remote-dom" } - >; -}; - -export type ControlPlaneSurfaceSessionResponse = { - sessionToken: string; - target: ControlPlaneSurfaceSessionRequest["target"]; - expiresAt: string; -}; - -export type ControlPlaneWorkspacePackage = { - packageName: string; - headCommit: string; - ignored: boolean; -}; - -export type ControlPlaneStateContext = { - id: string; - packageName: string; - packageRef: string; - createdAt: string; - parentStateContextId: string | null; - namespace: string | null; - kind: "root" | "derived"; -}; - -export type ControlPlaneBrowserAuthMessage = { - type: "auth"; - secret: string; -}; - -export type ControlPlaneBrowserOpenRootContextParams = { - target: string; -}; - -export type ControlPlaneBrowserOpenDerivedContextParams = { - target: string; - targetPackageName?: string; - callerStateContextId: string; - contextNamespace?: string | null; -}; - -export type ControlPlaneBrowserCloseStateContextParams = { - stateContextId: string; -}; - -export type ControlPlaneBrowserCallParams = { - target: string; - functionName: string; - params: unknown; - stateContextId: string; -}; - -export type ControlPlaneBrowserValueGetParams = { - target: string; - valueName: string; - params: unknown; - stateContextId: string; -}; - -export type ControlPlaneBrowserSubscribeParams = { - target: string; - resourceName: string; - params: unknown; - stateContextId: string; - subscriptionNamespace?: string | null; -}; - -export type ControlPlaneBrowserUnsubscribeParams = { - subscriptionId: string; -}; - -export type ControlPlaneBrowserSubscriptionReadyParams = { - subscriptionId: string; -}; - -export type ControlPlaneBrowserRequestMessage = - | { - type: "request"; - requestId: string; - method: "open-root-context"; - params: ControlPlaneBrowserOpenRootContextParams; - } - | { - type: "request"; - requestId: string; - method: "open-derived-context"; - params: ControlPlaneBrowserOpenDerivedContextParams; - } - | { - type: "request"; - requestId: string; - method: "close-state-context"; - params: ControlPlaneBrowserCloseStateContextParams; - } - | { - type: "request"; - requestId: string; - method: "call"; - params: ControlPlaneBrowserCallParams; - } - | { - type: "request"; - requestId: string; - method: "value-get"; - params: ControlPlaneBrowserValueGetParams; - } - | { - type: "request"; - requestId: string; - method: "event-subscribe"; - params: ControlPlaneBrowserSubscribeParams; - } - | { - type: "request"; - requestId: string; - method: "value-watch"; - params: ControlPlaneBrowserSubscribeParams; - } - | { - type: "request"; - requestId: string; - method: "unsubscribe"; - params: ControlPlaneBrowserUnsubscribeParams; - } - | { - type: "request"; - requestId: string; - method: "subscription-ready"; - params: ControlPlaneBrowserSubscriptionReadyParams; - }; - -export type ControlPlaneBrowserClientMessage = - | ControlPlaneBrowserAuthMessage - | ControlPlaneBrowserRequestMessage; - -export type ControlPlaneBrowserResponseMessage = { - type: "response"; - requestId: string; - ok: boolean; - result?: unknown; - error?: string; -}; - -export type ControlPlaneBrowserSubscriptionDataMessage = { - type: "subscription-data"; - subscriptionId: string; - data: unknown; -}; - -export type ControlPlaneBrowserAuthAckMessage = { - type: "auth-ack"; -}; - -export type ControlPlaneBrowserStatusInvalidatedMessage = { - type: "status-invalidated"; - reason: - | "state-context-opened" - | "state-context-closed" - | "running-packages-changed" - | "repl-sessions-changed" - | "runtime-errors-changed" - | "devices-changed"; -}; - -export type ControlPlaneDeviceSocketConnectMessage = { - type: "device-connect"; - deviceId: string; - sessionToken: string; - requestedTarget?: ControlPlaneDeviceTarget | null; - userAgent?: string | null; - viewport?: ControlPlaneDeviceViewport | null; -}; - -export type ControlPlaneDeviceSocketUpdateMessage = { - type: "device-update"; - viewport?: ControlPlaneDeviceViewport | null; -}; - -export type ControlPlaneDeviceSocketClientMessage = - | ControlPlaneDeviceSocketConnectMessage - | ControlPlaneDeviceSocketUpdateMessage; - -export type ControlPlaneDeviceSocketReadyMessage = { - type: "device-ready"; - device: ControlPlaneDevice; -}; - -export type ControlPlaneDeviceSocketStateMessage = { - type: "device-state"; - device: ControlPlaneDevice; -}; - -export type ControlPlaneDeviceSocketRemovedMessage = { - type: "device-removed"; - deviceId: string; -}; - -export type ControlPlaneDeviceSocketServerMessage = - | ControlPlaneDeviceSocketReadyMessage - | ControlPlaneDeviceSocketStateMessage - | ControlPlaneDeviceSocketRemovedMessage; - -export type ControlPlanePackageLogEntry = { - id: string; - createdAt: string; - packageName: string; - label: string; - processId: number | null; - stream: "stdout" | "stderr"; - text: string; -}; - -export type ControlPlaneRuntimeErrorPhase = - | "on-create" - | "on-destroy" - | "on-context-open" - | "on-context-close" - | "browser-surface" - | "function" - | "event-subscribe" - | "event-cleanup" - | "value-get" - | "value-watch" - | "value-cleanup" - | "subscription-publish" - | "internal"; - -export type ControlPlanePackageErrorEntry = { - id: string; - createdAt: string; - packageName: string; - label: string | null; - processId: number | null; - stateContextId: string | null; - phase: ControlPlaneRuntimeErrorPhase; - functionName: string | null; - resourceKind: "event" | "value" | null; - resourceName: string | null; - surfaceId: string | null; - hostSessionId: string | null; - message: string; - stack: string | null; - acknowledgedAt: string | null; -}; - -export type ControlPlaneLogsResponse = { - packageName: string; - entries: ControlPlanePackageLogEntry[]; -}; - -export type ControlPlaneErrorsResponse = { - entries: ControlPlanePackageErrorEntry[]; - acknowledgedCount: number; -}; - -export type ControlPlaneReplSession = { - sessionId: string; - createdAt: string; - lastActivityAt: string; - ownedStateContextIds: string[]; - borrowedStateContextIds: string[]; - subscriptionCount: number; - tempDirectory: string; -}; - -export type ControlPlaneBrowserServerMessage = - | ControlPlaneBrowserAuthAckMessage - | ControlPlaneBrowserStatusInvalidatedMessage - | ControlPlaneBrowserResponseMessage - | ControlPlaneBrowserSubscriptionDataMessage; - -export type ControlPlaneDependencyInput = { - inputName: string; - targetNodeId: string; -}; - -export type ControlPlaneDependencyNode = { - nodeId: string; - label: string; - originalRef: string | null; - lockedRef: string | null; - version: string | null; - inputs: ControlPlaneDependencyInput[]; -}; - -export type ControlPlaneDependencyGraph = { - rootNodeId: string; - nodes: ControlPlaneDependencyNode[]; -}; - -export type ControlPlaneRunningPackage = { - key: string; - label: string; - packageName: string; - flakeRef: string; - requestedRef: string | null; - connected: boolean; - processId: number | null; - openedStateContextIds: string[]; - rootStateContextIds: string[]; - resolvedRef: string | null; - version: string | null; - unreadErrorCount: number; - lastErrorAt: string | null; - dependencyGraph: ControlPlaneDependencyGraph | null; - dependencyGraphError: string | null; -}; - -export type ControlPlaneCheckStatus = "running" | "passed" | "failed"; - -export type ControlPlaneCheckResult = { - packageName: string; - rev: string; - status: ControlPlaneCheckStatus; - startedAt: string; - finishedAt: string | null; - summary: string | null; - logExcerpt: string | null; -}; - -export type ControlPlaneSchemaResourceDescription = { - name: string; - description: string | null; - annotations: Array & { type: string }>; - takesParams: boolean; - inputDescription: string | null; - inputJsonSchema: Record | null; - outputDescription: string | null; - outputJsonSchema: Record | null; - paramsDescription: string | null; - paramsJsonSchema: Record | null; - dataDescription: string | null; - dataJsonSchema: Record | null; - history?: boolean; - payloadMode: string | null; -}; - -export type ControlPlanePackageSchemaDescription = { - packageName: string; - schemaPackageName: string; - description: string | null; - annotations: Array & { type: string }>; - functions: ControlPlaneSchemaResourceDescription[]; - events: ControlPlaneSchemaResourceDescription[]; - values: ControlPlaneSchemaResourceDescription[]; -}; - -export type ControlPlaneSchemaDescriptionResult = { - packageName: string; - rev: string; - generatedAt: string; - status: "available" | "unavailable"; - data: ControlPlanePackageSchemaDescription | null; - error: string | null; -}; - -export type ControlPlaneRunResponse = { - stateContextId: string; - package: ControlPlaneRunningPackage; -}; - -export type ControlPlaneClearStateResponse = { - packageNames: string[]; - clearedDirectories: string[]; - packages: ControlPlaneRunningPackage[]; -}; - -export type ControlPlaneReplLogEntry = { - level: "log" | "info" | "warn" | "error"; - text: string; -}; - -export type ControlPlaneReplEvalResponse = { - session: ControlPlaneReplSession; - created: boolean; - closed: boolean; - ok: boolean; - result: string | null; - logs: ControlPlaneReplLogEntry[]; - error: string | null; -}; - -export type ControlPlaneReplCloseResponse = { - sessionId: string; - closed: boolean; -}; - -export type ControlPlaneRemoteDomPayload = { - protocol: string; - revision: number; - baseRevision: number | null; - fromEmpty: boolean; - mutations: unknown[]; -}; - -export type ControlPlaneStatusResponse = { - generatedAt: string; - workspacePackages: ControlPlaneWorkspacePackage[]; - stateContexts: ControlPlaneStateContext[]; - replSessions: ControlPlaneReplSession[]; - devices: ControlPlaneDevice[]; - packages: ControlPlaneRunningPackage[]; - checks: ControlPlaneCheckResult[]; - descriptions: ControlPlaneSchemaDescriptionResult[]; -}; - -export type ControlPlaneCutoverResponse = { - packages: ControlPlaneRunningPackage[]; -}; - -const isRecord = (value: unknown): value is Record => - typeof value === "object" && value !== null; - -const isString = (value: unknown): value is string => typeof value === "string"; - -const isNonEmptyString = (value: unknown): value is string => - typeof value === "string" && value.length > 0; - -const isNullableString = (value: unknown): value is string | null => - value === null || typeof value === "string"; - -const isNullableRecord = ( +const nonEmptyString = z.string().min(1); +const nullableString = z.string().nullable(); +const optionalNullableStringAsNull = z + .string() + .nullable() + .optional() + .transform((value) => value ?? null); +const jsonRecord = z.record(z.string(), z.unknown()); +const positiveNumber = z.number().finite().positive(); +const positiveInteger = z.number().int().positive(); + +const parseWith = ( + schema: Schema, value: unknown, -): value is Record | null => - value === null || isRecord(value); - -const isPositiveInteger = (value: unknown): value is number => - typeof value === "number" && Number.isInteger(value) && value > 0; - -const isRuntimeErrorPhase = ( - value: unknown, -): value is ControlPlaneRuntimeErrorPhase => - value === "on-create" || - value === "on-destroy" || - value === "on-context-open" || - value === "on-context-close" || - value === "browser-surface" || - value === "function" || - value === "event-subscribe" || - value === "event-cleanup" || - value === "value-get" || - value === "value-watch" || - value === "value-cleanup" || - value === "subscription-publish" || - value === "internal"; - -const isSchemaAnnotation = ( - value: unknown, -): value is Record & { type: string } => - isRecord(value) && isString(value.type); - -const isSchemaAnnotationArray = ( - value: unknown, -): value is Array & { type: string }> => - Array.isArray(value) && value.every((item) => isSchemaAnnotation(item)); - -const isStringArray = (value: unknown): value is string[] => - Array.isArray(value) && value.every((item) => typeof item === "string"); - -const isCheckStatus = (value: unknown): value is ControlPlaneCheckStatus => - value === "running" || value === "passed" || value === "failed"; - -const isPositiveNumber = (value: unknown): value is number => - typeof value === "number" && Number.isFinite(value) && value > 0; - -const parseControlPlaneDeviceViewport = ( - value: unknown, -): ControlPlaneDeviceViewport | null => { - if ( - !isRecord(value) || - !isPositiveNumber(value.width) || - !isPositiveNumber(value.height) || - !( - value.pixelRatio === undefined || - value.pixelRatio === null || - isPositiveNumber(value.pixelRatio) - ) - ) { - return null; - } - return { - width: value.width, - height: value.height, - pixelRatio: value.pixelRatio ?? null, - }; +): z.output | null => { + const parsed = schema.safeParse(value); + return parsed.success ? parsed.data : null; }; -export const parseControlPlaneDeviceTarget = ( - value: unknown, -): ControlPlaneDeviceTarget | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.packageName) || - !isNonEmptyString(value.stateContextId) || - !isNonEmptyString(value.surfaceId) || - !( - value.requestFullscreen === undefined || - typeof value.requestFullscreen === "boolean" - ) - ) { - return null; - } - return { - packageName: value.packageName, - stateContextId: value.stateContextId, - surfaceId: value.surfaceId, - requestFullscreen: value.requestFullscreen, - }; -}; +export const ControlPlaneRunRequestSchema = z.object({ + target: nonEmptyString, +}); -export const parseControlPlanePublicAccessTarget = ( - value: unknown, -): ControlPlanePublicAccessTarget | null => { - if (!isRecord(value) || !isNonEmptyString(value.kind)) { - return null; - } - if (value.kind === "device") { - const target = - value.target === undefined - ? undefined - : value.target === null - ? null - : parseControlPlaneDeviceTarget(value.target); - if (value.target !== undefined && value.target !== null && !target) { - return null; - } - return { - kind: "device", - ...(target !== undefined ? { target } : {}), - }; - } - if (value.kind === "browser-surface") { - if ( - !isNonEmptyString(value.stateContextId) || - !isNonEmptyString(value.surfaceId) || - !(value.packageName === undefined || isNonEmptyString(value.packageName)) || - !( - value.requestFullscreen === undefined || - typeof value.requestFullscreen === "boolean" - ) - ) { - return null; - } - return { - kind: "browser-surface", - ...(value.packageName ? { packageName: value.packageName } : {}), - stateContextId: value.stateContextId, - surfaceId: value.surfaceId, - ...(value.requestFullscreen !== undefined - ? { requestFullscreen: value.requestFullscreen } - : {}), - }; - } - if (value.kind === "remote-dom") { - if ( - !isNonEmptyString(value.stateContextId) || - !(value.packageName === undefined || isNonEmptyString(value.packageName)) - ) { - return null; - } - return { - kind: "remote-dom", - ...(value.packageName ? { packageName: value.packageName } : {}), - stateContextId: value.stateContextId, - }; - } - return null; -}; +export const ControlPlaneCheckRequestSchema = z.object({ + packageName: nonEmptyString, + rev: nonEmptyString, +}); -export const parseControlPlaneDevice = ( - value: unknown, -): ControlPlaneDevice | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.deviceId) || - !isNullableString(value.name) || - !isString(value.createdAt) || - !isNullableString(value.lastSeenAt) || - typeof value.connected !== "boolean" || - !isNullableString(value.identifyUntil) || - !isNullableString(value.lastUserAgent) - ) { - return null; - } - const assignment = - value.assignment === undefined || value.assignment === null - ? null - : parseControlPlaneDeviceTarget(value.assignment); - if (value.assignment !== undefined && value.assignment !== null && !assignment) { - return null; - } - const configuredAssignment = - value.configuredAssignment === undefined || value.configuredAssignment === null - ? null - : parseControlPlaneDeviceTarget(value.configuredAssignment); - if ( - value.configuredAssignment !== undefined && - value.configuredAssignment !== null && - !configuredAssignment - ) { - return null; - } - const viewport = - value.viewport === undefined || value.viewport === null - ? null - : parseControlPlaneDeviceViewport(value.viewport); - if (value.viewport !== undefined && value.viewport !== null && !viewport) { - return null; - } - return { - deviceId: value.deviceId, - name: value.name, - createdAt: value.createdAt, - lastSeenAt: value.lastSeenAt, - connected: value.connected, - assignment, - configuredAssignment, - identifyUntil: value.identifyUntil, - lastUserAgent: value.lastUserAgent, - viewport, - }; -}; +export const ControlPlaneCutoverRequestSchema = z.object({ + targets: z.array(nonEmptyString), +}); -export const parseControlPlaneRunRequest = ( - value: unknown, -): ControlPlaneRunRequest | null => { - if (!isRecord(value) || !isString(value.target) || value.target.length === 0) { - return null; - } - return { - target: value.target, - }; -}; +export const ControlPlaneClearStateRequestSchema = z.object({ + packageName: nonEmptyString, + recursive: z.boolean().optional(), +}); -export const parseControlPlaneCheckRequest = ( - value: unknown, -): ControlPlaneCheckRequest | null => { - if ( - !isRecord(value) || - !isString(value.packageName) || - value.packageName.length === 0 || - !isString(value.rev) || - value.rev.length === 0 - ) { - return null; - } - return { - packageName: value.packageName, - rev: value.rev, - }; -}; +export const ControlPlaneDescribeRequestSchema = + ControlPlaneCheckRequestSchema; -export const parseControlPlaneCutoverRequest = ( - value: unknown, -): ControlPlaneCutoverRequest | null => { - if ( - !isRecord(value) || - !Array.isArray(value.targets) || - !value.targets.every( - (target) => typeof target === "string" && target.length > 0, - ) - ) { - return null; - } - return { - targets: value.targets, - }; -}; +export const ControlPlaneLogsRequestSchema = z.object({ + packageName: nonEmptyString, + tail: positiveInteger.nullable().optional().transform((value) => value ?? undefined), + stream: z.enum(["stdout", "stderr", "all"]).optional(), +}); -export const parseControlPlaneClearStateRequest = ( - value: unknown, -): ControlPlaneClearStateRequest | null => { - if (!isRecord(value) || !isString(value.packageName)) { - return null; - } - if ( - value.recursive !== undefined && - typeof value.recursive !== "boolean" - ) { - return null; - } - return { - packageName: value.packageName, - recursive: value.recursive, - }; -}; +export const ControlPlaneErrorsRequestSchema = z.object({ + packageName: z.string().nullable().optional().transform((value) => value ?? undefined), + stateContextId: z.string().nullable().optional().transform((value) => value ?? undefined), + tail: positiveInteger.nullable().optional().transform((value) => value ?? undefined), + acknowledge: z.boolean().optional(), +}); -export const parseControlPlaneDescribeRequest = ( - value: unknown, -): ControlPlaneDescribeRequest | null => { - if ( - !isRecord(value) || - !isString(value.packageName) || - value.packageName.length === 0 || - !isString(value.rev) || - value.rev.length === 0 - ) { - return null; - } - return { - packageName: value.packageName, - rev: value.rev, - }; -}; +export const ControlPlaneReplEvalRequestSchema = z.object({ + sessionId: nonEmptyString.optional(), + code: nonEmptyString, + autoClose: z.boolean().optional(), + defaultStateContextId: nonEmptyString.nullable().optional().transform( + (value) => value ?? null, + ), +}); -export const parseControlPlaneLogsRequest = ( - value: unknown, -): ControlPlaneLogsRequest | null => { - if (!isRecord(value) || !isString(value.packageName)) { - return null; - } - if ( - !( - value.tail === undefined || - value.tail === null || - isPositiveInteger(value.tail) - ) || - !( - value.stream === undefined || - value.stream === "stdout" || - value.stream === "stderr" || - value.stream === "all" - ) - ) { - return null; - } - return { - packageName: value.packageName, - tail: value.tail ?? undefined, - stream: value.stream ?? undefined, - }; -}; +export const ControlPlaneReplCloseRequestSchema = z.object({ + sessionId: nonEmptyString, +}); -export const parseControlPlaneErrorsRequest = ( - value: unknown, -): ControlPlaneErrorsRequest | null => { - if (!isRecord(value)) { - return null; - } - if ( - !( - value.packageName === undefined || - value.packageName === null || - isString(value.packageName) - ) || - !( - value.stateContextId === undefined || - value.stateContextId === null || - isString(value.stateContextId) - ) || - !( - value.tail === undefined || - value.tail === null || - isPositiveInteger(value.tail) - ) || - !( - value.acknowledge === undefined || - typeof value.acknowledge === "boolean" - ) - ) { - return null; - } - return { - packageName: value.packageName ?? undefined, - stateContextId: value.stateContextId ?? undefined, - tail: value.tail ?? undefined, - acknowledge: value.acknowledge ?? undefined, - }; -}; +export const ControlPlaneDeviceViewportSchema = z.object({ + width: positiveNumber, + height: positiveNumber, + pixelRatio: positiveNumber.nullable().optional().transform( + (value) => value ?? null, + ), +}); -export const parseControlPlaneDeviceAssignRequest = ( - value: unknown, -): ControlPlaneDeviceAssignRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.deviceId)) { - return null; - } - const target = - value.target === undefined || value.target === null - ? null - : parseControlPlaneDeviceTarget(value.target); - if (value.target !== undefined && value.target !== null && !target) { - return null; - } - return { - deviceId: value.deviceId, - target, - }; -}; +export const ControlPlaneDeviceTargetSchema = z.object({ + packageName: nonEmptyString, + stateContextId: nonEmptyString, + surfaceId: nonEmptyString, + requestFullscreen: z.boolean().optional(), +}); -export const parseControlPlaneDeviceRenameRequest = ( - value: unknown, -): ControlPlaneDeviceRenameRequest | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.deviceId) || - !( - value.name === undefined || - value.name === null || - typeof value.name === "string" - ) - ) { - return null; - } - return { - deviceId: value.deviceId, - name: value.name ?? null, - }; -}; +const nullableDeviceTargetAsNull = ControlPlaneDeviceTargetSchema.nullable() + .optional() + .transform((value) => value ?? null); -export const parseControlPlaneDeviceRemoveRequest = ( - value: unknown, -): ControlPlaneDeviceRemoveRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.deviceId)) { - return null; - } - return { - deviceId: value.deviceId, - }; -}; +export const ControlPlaneDeviceSchema = z.object({ + deviceId: nonEmptyString, + name: nullableString, + createdAt: z.string(), + lastSeenAt: nullableString, + connected: z.boolean(), + assignment: nullableDeviceTargetAsNull, + configuredAssignment: nullableDeviceTargetAsNull, + identifyUntil: nullableString, + lastUserAgent: nullableString, + viewport: ControlPlaneDeviceViewportSchema.nullable() + .optional() + .transform((value) => value ?? null), +}); -export const parseControlPlaneDeviceIdentifyRequest = ( - value: unknown, -): ControlPlaneDeviceIdentifyRequest | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.deviceId) || - !( - value.durationMs === undefined || - (typeof value.durationMs === "number" && - Number.isInteger(value.durationMs) && - value.durationMs > 0) - ) - ) { - return null; - } - return { - deviceId: value.deviceId, - durationMs: value.durationMs, - }; -}; +export const ControlPlaneDevicesResponseSchema = z.object({ + devices: z.array(ControlPlaneDeviceSchema), +}); -export const parseControlPlaneDeviceSessionRequest = ( - value: unknown, -): ControlPlaneDeviceSessionRequest | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.deviceId) || - !isNonEmptyString(value.sessionToken) || - !( - value.userAgent === undefined || - value.userAgent === null || - typeof value.userAgent === "string" - ) - ) { - return null; - } - const requestedTarget = - value.requestedTarget === undefined - ? undefined - : value.requestedTarget === null - ? null - : parseControlPlaneDeviceTarget(value.requestedTarget); - if ( - value.requestedTarget !== undefined && - value.requestedTarget !== null && - !requestedTarget - ) { - return null; - } - const viewport = - value.viewport === undefined || value.viewport === null - ? null - : parseControlPlaneDeviceViewport(value.viewport); - if (value.viewport !== undefined && value.viewport !== null && !viewport) { - return null; - } - return { - deviceId: value.deviceId, - sessionToken: value.sessionToken, - ...(requestedTarget !== undefined ? { requestedTarget } : {}), - userAgent: value.userAgent ?? null, - viewport, - }; -}; +export const ControlPlaneDeviceAssignRequestSchema = z.object({ + deviceId: nonEmptyString, + target: nullableDeviceTargetAsNull, +}); -export const parseControlPlanePublicAuthGrantRequest = ( - value: unknown, -): ControlPlanePublicAuthGrantRequest | null => { - if (!isRecord(value)) { - return null; - } - const target = parseControlPlanePublicAccessTarget(value.target); - return target ? { target } : null; -}; +export const ControlPlaneDeviceRenameRequestSchema = z.object({ + deviceId: nonEmptyString, + name: z.string().nullable().optional().transform((value) => value ?? null), +}); -export const parseControlPlanePublicSessionRequest = ( - value: unknown, -): ControlPlanePublicSessionRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.authGrant)) { - return null; - } - return { authGrant: value.authGrant }; -}; +export const ControlPlaneDeviceRemoveRequestSchema = z.object({ + deviceId: nonEmptyString, +}); -export const parseControlPlanePublicAuthGrantRevokeRequest = ( - value: unknown, -): ControlPlanePublicAuthGrantRevokeRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.authGrant)) { - return null; - } - return { authGrant: value.authGrant }; -}; +export const ControlPlaneDeviceIdentifyRequestSchema = z.object({ + deviceId: nonEmptyString, + durationMs: positiveInteger.optional(), +}); -export const parseControlPlaneSurfaceSessionRequest = ( - value: unknown, -): ControlPlaneSurfaceSessionRequest | null => { - if (!isRecord(value)) { - return null; - } - const target = parseControlPlanePublicAccessTarget(value.target); - if (!target || target.kind === "device") { - return null; - } - return { target }; -}; +export const ControlPlaneDeviceSessionRequestSchema = z.object({ + deviceId: nonEmptyString, + sessionToken: nonEmptyString, + requestedTarget: ControlPlaneDeviceTargetSchema.nullable().optional(), + userAgent: z.string().nullable().optional().transform((value) => value ?? null), + viewport: ControlPlaneDeviceViewportSchema.nullable() + .optional() + .transform((value) => value ?? null), +}); -export const parseControlPlaneReplEvalRequest = ( - value: unknown, -): ControlPlaneReplEvalRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.code)) { - return null; - } - if ( - !( - value.sessionId === undefined || - isNonEmptyString(value.sessionId) - ) || - !( - value.autoClose === undefined || - typeof value.autoClose === "boolean" - ) || - !( - value.defaultStateContextId === undefined || - value.defaultStateContextId === null || - isNonEmptyString(value.defaultStateContextId) - ) - ) { - return null; - } - return { - sessionId: value.sessionId, - code: value.code, - autoClose: value.autoClose, - defaultStateContextId: value.defaultStateContextId ?? null, - }; -}; +export const ControlPlaneDeviceSessionResponseSchema = z.object({ + device: ControlPlaneDeviceSchema, +}); -export const parseControlPlaneReplCloseRequest = ( - value: unknown, -): ControlPlaneReplCloseRequest | null => { - if (!isRecord(value) || !isNonEmptyString(value.sessionId)) { - return null; - } - return { - sessionId: value.sessionId, - }; -}; +export const ControlPlaneDevicePublicAccessTargetSchema = z.object({ + kind: z.literal("device"), + target: ControlPlaneDeviceTargetSchema.nullable().optional(), +}); -const parseBrowserSubscribeParams = ( - value: unknown, -): ControlPlaneBrowserSubscribeParams | null => { - if ( - !isRecord(value) || - !isNonEmptyString(value.target) || - !isNonEmptyString(value.resourceName) || - !isNonEmptyString(value.stateContextId) || - !( - value.subscriptionNamespace === undefined || - value.subscriptionNamespace === null || - typeof value.subscriptionNamespace === "string" - ) - ) { - return null; - } - return { - target: value.target, - resourceName: value.resourceName, - params: value.params, - stateContextId: value.stateContextId, - subscriptionNamespace: value.subscriptionNamespace ?? null, - }; -}; +export const ControlPlaneBrowserSurfacePublicAccessTargetSchema = z.object({ + kind: z.literal("browser-surface"), + packageName: nonEmptyString.optional(), + stateContextId: nonEmptyString, + surfaceId: nonEmptyString, + requestFullscreen: z.boolean().optional(), +}); -export const parseControlPlaneDeviceSocketClientMessage = ( - value: unknown, -): ControlPlaneDeviceSocketClientMessage | null => { - if (!isRecord(value) || !isNonEmptyString(value.type)) { - return null; - } - if (value.type === "device-connect") { - const parsed = parseControlPlaneDeviceSessionRequest(value); - if (!parsed) { - return null; - } - return { - type: "device-connect", - deviceId: parsed.deviceId, - sessionToken: parsed.sessionToken, - ...(parsed.requestedTarget !== undefined - ? { requestedTarget: parsed.requestedTarget } - : {}), - ...(parsed.userAgent !== undefined ? { userAgent: parsed.userAgent } : {}), - ...(parsed.viewport !== undefined ? { viewport: parsed.viewport } : {}), - }; - } - if (value.type === "device-update") { - const viewport = - value.viewport === undefined || value.viewport === null - ? value.viewport - : parseControlPlaneDeviceViewport(value.viewport); - if (value.viewport !== undefined && value.viewport !== null && !viewport) { - return null; - } - return { - type: "device-update", - ...(value.viewport !== undefined ? { viewport: viewport ?? null } : {}), - }; - } - return null; -}; +export const ControlPlaneRemoteDomPublicAccessTargetSchema = z.object({ + kind: z.literal("remote-dom"), + packageName: nonEmptyString.optional(), + stateContextId: nonEmptyString, +}); -export const parseControlPlaneDeviceSocketServerMessage = ( - value: unknown, -): ControlPlaneDeviceSocketServerMessage | null => { - if (!isRecord(value) || !isNonEmptyString(value.type)) { - return null; - } - if (value.type === "device-removed") { - if (!isNonEmptyString(value.deviceId)) { - return null; - } - return { - type: "device-removed", - deviceId: value.deviceId, - }; - } - if (value.type !== "device-ready" && value.type !== "device-state") { - return null; - } - const device = parseControlPlaneDevice(value.device); - if (!device) { - return null; - } - return { - type: value.type, - device, - }; -}; +export const ControlPlanePublicAccessTargetSchema = z.discriminatedUnion( + "kind", + [ + ControlPlaneDevicePublicAccessTargetSchema, + ControlPlaneBrowserSurfacePublicAccessTargetSchema, + ControlPlaneRemoteDomPublicAccessTargetSchema, + ], +); -export const parseControlPlaneBrowserClientMessage = ( - value: unknown, -): ControlPlaneBrowserClientMessage | null => { - if (!isRecord(value) || !isNonEmptyString(value.type)) { - return null; - } +export const ControlPlaneSurfaceAccessTargetSchema = z.discriminatedUnion( + "kind", + [ + ControlPlaneBrowserSurfacePublicAccessTargetSchema, + ControlPlaneRemoteDomPublicAccessTargetSchema, + ], +); - if (value.type === "auth") { - if (!isNonEmptyString(value.secret)) { - return null; - } - return { - type: "auth", - secret: value.secret, - }; - } +export const ControlPlanePublicAuthGrantRequestSchema = z.object({ + target: ControlPlanePublicAccessTargetSchema, +}); - if (value.type !== "request") { - return null; - } - if (!isNonEmptyString(value.requestId) || !isNonEmptyString(value.method)) { - return null; - } +export const ControlPlanePublicAuthGrantResponseSchema = z.object({ + authGrant: nonEmptyString, + target: ControlPlanePublicAccessTargetSchema, +}); - switch (value.method) { - case "open-root-context": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.target) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "open-root-context", - params: { - target: value.params.target, - }, - }; - case "open-derived-context": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.target) || - !isNonEmptyString(value.params.callerStateContextId) || - !( - value.params.targetPackageName === undefined || - isNonEmptyString(value.params.targetPackageName) - ) || - !( - value.params.contextNamespace === undefined || - value.params.contextNamespace === null || - isNonEmptyString(value.params.contextNamespace) - ) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "open-derived-context", - params: { - target: value.params.target, - targetPackageName: value.params.targetPackageName, - callerStateContextId: value.params.callerStateContextId, - contextNamespace: value.params.contextNamespace ?? null, - }, - }; - case "close-state-context": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.stateContextId) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "close-state-context", - params: { - stateContextId: value.params.stateContextId, - }, - }; - case "call": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.target) || - !isNonEmptyString(value.params.functionName) || - !isNonEmptyString(value.params.stateContextId) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "call", - params: { - target: value.params.target, - functionName: value.params.functionName, - params: value.params.params, - stateContextId: value.params.stateContextId, - }, - }; - case "value-get": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.target) || - !isNonEmptyString(value.params.valueName) || - !isNonEmptyString(value.params.stateContextId) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "value-get", - params: { - target: value.params.target, - valueName: value.params.valueName, - params: value.params.params, - stateContextId: value.params.stateContextId, - }, - }; - case "event-subscribe": { - const params = parseBrowserSubscribeParams(value.params); - if (!params) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "event-subscribe", - params, - }; - } - case "value-watch": { - const params = parseBrowserSubscribeParams(value.params); - if (!params) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "value-watch", - params, - }; - } - case "unsubscribe": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.subscriptionId) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "unsubscribe", - params: { - subscriptionId: value.params.subscriptionId, - }, - }; - case "subscription-ready": - if ( - !isRecord(value.params) || - !isNonEmptyString(value.params.subscriptionId) - ) { - return null; - } - return { - type: "request", - requestId: value.requestId, - method: "subscription-ready", - params: { - subscriptionId: value.params.subscriptionId, - }, - }; - default: - return null; - } -}; +export const ControlPlanePublicAuthGrantRevokeRequestSchema = z.object({ + authGrant: nonEmptyString, +}); -const parseDependencyInput = ( - value: unknown, -): ControlPlaneDependencyInput | null => { - if (!isRecord(value)) { - return null; - } - if (!isString(value.inputName) || !isString(value.targetNodeId)) { - return null; - } - return { - inputName: value.inputName, - targetNodeId: value.targetNodeId, - }; -}; +export const ControlPlanePublicAuthGrantRevokeResponseSchema = z.object({ + revoked: z.boolean(), +}); -const parseDependencyNode = ( - value: unknown, -): ControlPlaneDependencyNode | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.nodeId) || - !isString(value.label) || - !isNullableString(value.originalRef) || - !isNullableString(value.lockedRef) || - !isNullableString(value.version) || - !Array.isArray(value.inputs) - ) { - return null; - } +export const ControlPlanePublicSessionRequestSchema = z.object({ + authGrant: nonEmptyString, +}); - const inputs = value.inputs - .map((input) => parseDependencyInput(input)) - .filter((input): input is ControlPlaneDependencyInput => input !== null); - if (inputs.length !== value.inputs.length) { - return null; - } +export const ControlPlanePublicSessionResponseSchema = z.object({ + sessionToken: nonEmptyString, + target: ControlPlanePublicAccessTargetSchema, + expiresAt: z.string(), +}); - return { - nodeId: value.nodeId, - label: value.label, - originalRef: value.originalRef, - lockedRef: value.lockedRef, - version: value.version, - inputs, - }; -}; +export const ControlPlaneSurfaceSessionRequestSchema = z.object({ + target: ControlPlaneSurfaceAccessTargetSchema, +}); -const parseControlPlaneWorkspacePackage = ( - value: unknown, -): ControlPlaneWorkspacePackage | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.packageName) || - !isString(value.headCommit) || - typeof value.ignored !== "boolean" - ) { - return null; - } - return { - packageName: value.packageName, - headCommit: value.headCommit, - ignored: value.ignored, - }; -}; +export const ControlPlaneSurfaceSessionResponseSchema = z.object({ + sessionToken: nonEmptyString, + target: ControlPlaneSurfaceAccessTargetSchema, + expiresAt: z.string(), +}); -const parseControlPlaneReplLogEntry = ( - value: unknown, -): ControlPlaneReplLogEntry | null => { - if ( - !isRecord(value) || - !( - value.level === "log" || - value.level === "info" || - value.level === "warn" || - value.level === "error" - ) || - !isString(value.text) - ) { - return null; - } - return { - level: value.level, - text: value.text, - }; -}; +export const ControlPlaneWorkspacePackageSchema = z.object({ + packageName: z.string(), + headCommit: z.string(), + ignored: z.boolean(), +}); -export const parseControlPlaneReplSession = ( - value: unknown, -): ControlPlaneReplSession | null => { - if ( - !isRecord(value) || - !isString(value.sessionId) || - !isString(value.createdAt) || - !isString(value.lastActivityAt) || - !isStringArray(value.ownedStateContextIds) || - !isStringArray(value.borrowedStateContextIds) || - typeof value.subscriptionCount !== "number" || - !isString(value.tempDirectory) - ) { - return null; - } - return { - sessionId: value.sessionId, - createdAt: value.createdAt, - lastActivityAt: value.lastActivityAt, - ownedStateContextIds: value.ownedStateContextIds, - borrowedStateContextIds: value.borrowedStateContextIds, - subscriptionCount: value.subscriptionCount, - tempDirectory: value.tempDirectory, - }; -}; +export const ControlPlaneStateContextSchema = z.object({ + id: z.string(), + packageName: z.string(), + packageRef: z.string(), + createdAt: z.string(), + parentStateContextId: nullableString, + namespace: nullableString, + kind: z.enum(["root", "derived"]), +}); -const parseDependencyGraph = ( - value: unknown, -): ControlPlaneDependencyGraph | null => { - if (!isRecord(value)) { - return null; - } - if (!isString(value.rootNodeId) || !Array.isArray(value.nodes)) { - return null; - } - const nodes = value.nodes - .map((node) => parseDependencyNode(node)) - .filter((node): node is ControlPlaneDependencyNode => node !== null); - if (nodes.length !== value.nodes.length) { - return null; - } - return { - rootNodeId: value.rootNodeId, - nodes, - }; -}; +export const ControlPlaneBrowserAuthMessageSchema = z.object({ + type: z.literal("auth"), + secret: nonEmptyString, +}); -export const parseControlPlaneRunningPackage = ( - value: unknown, -): ControlPlaneRunningPackage | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.key) || - !isString(value.label) || - !isString(value.packageName) || - !isString(value.flakeRef) || - !isNullableString(value.requestedRef) || - typeof value.connected !== "boolean" || - !(typeof value.processId === "number" || value.processId === null) || - !isStringArray(value.openedStateContextIds) || - !isStringArray(value.rootStateContextIds) || - !isNullableString(value.resolvedRef) || - !isNullableString(value.version) || - !( - typeof value.unreadErrorCount === "number" && - Number.isInteger(value.unreadErrorCount) && - value.unreadErrorCount >= 0 - ) || - !isNullableString(value.lastErrorAt) || - !isNullableString(value.dependencyGraphError) - ) { - return null; - } +export const ControlPlaneBrowserOpenRootContextParamsSchema = z.object({ + target: nonEmptyString, +}); - const dependencyGraph = - value.dependencyGraph === null - ? null - : parseDependencyGraph(value.dependencyGraph); - if (value.dependencyGraph !== null && !dependencyGraph) { - return null; - } +export const ControlPlaneBrowserOpenDerivedContextParamsSchema = z.object({ + target: nonEmptyString, + targetPackageName: nonEmptyString.optional(), + callerStateContextId: nonEmptyString, + contextNamespace: nonEmptyString.nullable().optional().transform( + (value) => value ?? null, + ), +}); - return { - key: value.key, - label: value.label, - packageName: value.packageName, - flakeRef: value.flakeRef, - requestedRef: value.requestedRef, - connected: value.connected, - processId: value.processId, - openedStateContextIds: value.openedStateContextIds, - rootStateContextIds: value.rootStateContextIds, - resolvedRef: value.resolvedRef, - version: value.version, - unreadErrorCount: value.unreadErrorCount, - lastErrorAt: value.lastErrorAt, - dependencyGraph, - dependencyGraphError: value.dependencyGraphError, - }; -}; +export const ControlPlaneBrowserCloseStateContextParamsSchema = z.object({ + stateContextId: nonEmptyString, +}); -export const parseControlPlanePackageLogEntry = ( - value: unknown, -): ControlPlanePackageLogEntry | null => { - if ( - !isRecord(value) || - !isString(value.id) || - !isString(value.createdAt) || - !isString(value.packageName) || - !isString(value.label) || - !(typeof value.processId === "number" || value.processId === null) || - !(value.stream === "stdout" || value.stream === "stderr") || - !isString(value.text) - ) { - return null; - } - return { - id: value.id, - createdAt: value.createdAt, - packageName: value.packageName, - label: value.label, - processId: value.processId, - stream: value.stream, - text: value.text, - }; -}; +export const ControlPlaneBrowserCallParamsSchema = z.object({ + target: nonEmptyString, + functionName: nonEmptyString, + params: z.unknown(), + stateContextId: nonEmptyString, +}); -export const parseControlPlanePackageErrorEntry = ( - value: unknown, -): ControlPlanePackageErrorEntry | null => { - if ( - !isRecord(value) || - !isString(value.id) || - !isString(value.createdAt) || - !isString(value.packageName) || - !isNullableString(value.label) || - !(typeof value.processId === "number" || value.processId === null) || - !isNullableString(value.stateContextId) || - !isRuntimeErrorPhase(value.phase) || - !isNullableString(value.functionName) || - !( - value.resourceKind === "event" || - value.resourceKind === "value" || - value.resourceKind === null - ) || - !isNullableString(value.resourceName) || - !( - value.surfaceId === undefined || - isNullableString(value.surfaceId) - ) || - !( - value.hostSessionId === undefined || - isNullableString(value.hostSessionId) - ) || - !isString(value.message) || - !isNullableString(value.stack) || - !isNullableString(value.acknowledgedAt) - ) { - return null; - } - return { - id: value.id, - createdAt: value.createdAt, - packageName: value.packageName, - label: value.label, - processId: value.processId, - stateContextId: value.stateContextId, - phase: value.phase, - functionName: value.functionName, - resourceKind: value.resourceKind, - resourceName: value.resourceName, - surfaceId: value.surfaceId ?? null, - hostSessionId: value.hostSessionId ?? null, - message: value.message, - stack: value.stack, - acknowledgedAt: value.acknowledgedAt, - }; -}; +export const ControlPlaneBrowserValueGetParamsSchema = z.object({ + target: nonEmptyString, + valueName: nonEmptyString, + params: z.unknown(), + stateContextId: nonEmptyString, +}); -export const parseControlPlaneStateContext = ( - value: unknown, -): ControlPlaneStateContext | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.id) || - !isString(value.packageName) || - !isString(value.packageRef) || - !isString(value.createdAt) || - !isNullableString(value.parentStateContextId) || - !isNullableString(value.namespace) || - !(value.kind === "root" || value.kind === "derived") - ) { - return null; - } - return { - id: value.id, - packageName: value.packageName, - packageRef: value.packageRef, - createdAt: value.createdAt, - parentStateContextId: value.parentStateContextId, - namespace: value.namespace, - kind: value.kind, - }; -}; +export const ControlPlaneBrowserSubscribeParamsSchema = z.object({ + target: nonEmptyString, + resourceName: nonEmptyString, + params: z.unknown(), + stateContextId: nonEmptyString, + subscriptionNamespace: nonEmptyString.nullable().optional().transform( + (value) => value ?? null, + ), +}); -export const parseControlPlaneCheckResult = ( - value: unknown, -): ControlPlaneCheckResult | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.packageName) || - !isString(value.rev) || - !isCheckStatus(value.status) || - !isString(value.startedAt) || - !isNullableString(value.finishedAt) || - !isNullableString(value.summary) || - !isNullableString(value.logExcerpt) - ) { - return null; - } - return { - packageName: value.packageName, - rev: value.rev, - status: value.status, - startedAt: value.startedAt, - finishedAt: value.finishedAt, - summary: value.summary, - logExcerpt: value.logExcerpt, - }; -}; +export const ControlPlaneBrowserUnsubscribeParamsSchema = z.object({ + subscriptionId: nonEmptyString, +}); -const parseControlPlaneSchemaResourceDescription = ( - value: unknown, -): ControlPlaneSchemaResourceDescription | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.name) || - !isNullableString(value.description) || - !(value.annotations === undefined || isSchemaAnnotationArray(value.annotations)) || - typeof value.takesParams !== "boolean" || - !isNullableString(value.inputDescription) || - !(value.inputJsonSchema === undefined || isNullableRecord(value.inputJsonSchema)) || - !isNullableString(value.outputDescription) || - !(value.outputJsonSchema === undefined || isNullableRecord(value.outputJsonSchema)) || - !isNullableString(value.paramsDescription) || - !(value.paramsJsonSchema === undefined || isNullableRecord(value.paramsJsonSchema)) || - !isNullableString(value.dataDescription) || - !(value.dataJsonSchema === undefined || isNullableRecord(value.dataJsonSchema)) || - !(typeof value.history === "boolean" || value.history === undefined) || - !isNullableString(value.payloadMode) - ) { - return null; - } - return { - name: value.name, - description: value.description, - annotations: value.annotations ?? [], - takesParams: value.takesParams, - inputDescription: value.inputDescription, - inputJsonSchema: value.inputJsonSchema ?? null, - outputDescription: value.outputDescription, - outputJsonSchema: value.outputJsonSchema ?? null, - paramsDescription: value.paramsDescription, - paramsJsonSchema: value.paramsJsonSchema ?? null, - dataDescription: value.dataDescription, - dataJsonSchema: value.dataJsonSchema ?? null, - history: value.history, - payloadMode: value.payloadMode, - }; -}; +export const ControlPlaneBrowserSubscriptionReadyParamsSchema = + ControlPlaneBrowserUnsubscribeParamsSchema; -const parseControlPlanePackageSchemaDescription = ( - value: unknown, -): ControlPlanePackageSchemaDescription | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.packageName) || - !isString(value.schemaPackageName) || - !isNullableString(value.description) || - !(value.annotations === undefined || isSchemaAnnotationArray(value.annotations)) || - !Array.isArray(value.functions) || - !Array.isArray(value.events) || - !Array.isArray(value.values) - ) { - return null; - } - const functions = value.functions - .map((entry) => parseControlPlaneSchemaResourceDescription(entry)) - .filter( - (entry): entry is ControlPlaneSchemaResourceDescription => entry !== null, - ); - const events = value.events - .map((entry) => parseControlPlaneSchemaResourceDescription(entry)) - .filter( - (entry): entry is ControlPlaneSchemaResourceDescription => entry !== null, - ); - const values = value.values - .map((entry) => parseControlPlaneSchemaResourceDescription(entry)) - .filter( - (entry): entry is ControlPlaneSchemaResourceDescription => entry !== null, - ); - if ( - functions.length !== value.functions.length || - events.length !== value.events.length || - values.length !== value.values.length - ) { - return null; - } - return { - packageName: value.packageName, - schemaPackageName: value.schemaPackageName, - description: value.description, - annotations: value.annotations ?? [], - functions, - events, - values, - }; -}; +const browserRequest = ( + method: Method, + params: Params, +) => + z.object({ + type: z.literal("request"), + requestId: nonEmptyString, + method: z.literal(method), + params, + }); -export const parseControlPlaneSchemaDescriptionResult = ( - value: unknown, -): ControlPlaneSchemaDescriptionResult | null => { - if (!isRecord(value)) { - return null; - } - if ( - !isString(value.packageName) || - !isString(value.rev) || - !isString(value.generatedAt) || - !(value.status === "available" || value.status === "unavailable") || - !isNullableString(value.error) - ) { - return null; - } - const data = - value.data === null ? null : parseControlPlanePackageSchemaDescription(value.data); - if (value.data !== null && !data) { - return null; - } - return { - packageName: value.packageName, - rev: value.rev, - generatedAt: value.generatedAt, - status: value.status, - data, - error: value.error, - }; -}; +export const ControlPlaneBrowserRequestMessageSchema = z.discriminatedUnion( + "method", + [ + browserRequest( + "open-root-context", + ControlPlaneBrowserOpenRootContextParamsSchema, + ), + browserRequest( + "open-derived-context", + ControlPlaneBrowserOpenDerivedContextParamsSchema, + ), + browserRequest( + "close-state-context", + ControlPlaneBrowserCloseStateContextParamsSchema, + ), + browserRequest("call", ControlPlaneBrowserCallParamsSchema), + browserRequest("value-get", ControlPlaneBrowserValueGetParamsSchema), + browserRequest("event-subscribe", ControlPlaneBrowserSubscribeParamsSchema), + browserRequest("value-watch", ControlPlaneBrowserSubscribeParamsSchema), + browserRequest("unsubscribe", ControlPlaneBrowserUnsubscribeParamsSchema), + browserRequest( + "subscription-ready", + ControlPlaneBrowserSubscriptionReadyParamsSchema, + ), + ], +); -export const parseControlPlaneRunResponse = ( - value: unknown, -): ControlPlaneRunResponse | null => { - if (!isRecord(value) || !isString(value.stateContextId)) { - return null; - } - const parsedPackage = parseControlPlaneRunningPackage(value.package); - if (!parsedPackage) { - return null; - } - return { - stateContextId: value.stateContextId, - package: parsedPackage, - }; -}; +export const ControlPlaneBrowserClientMessageSchema = z.union([ + ControlPlaneBrowserAuthMessageSchema, + ControlPlaneBrowserRequestMessageSchema, +]); -export const parseControlPlaneStatusResponse = ( - value: unknown, -): ControlPlaneStatusResponse | null => { - if ( - !isRecord(value) || - !isString(value.generatedAt) || - !( - value.workspacePackages === undefined || - Array.isArray(value.workspacePackages) - ) || - !( - value.stateContexts === undefined || - Array.isArray(value.stateContexts) - ) || - !( - value.replSessions === undefined || - Array.isArray(value.replSessions) - ) || - !( - value.devices === undefined || - Array.isArray(value.devices) - ) || - !Array.isArray(value.packages) || - !Array.isArray(value.checks) || - !Array.isArray(value.descriptions) - ) { - return null; - } - const workspacePackages = (value.workspacePackages ?? []) - .map((pkg) => parseControlPlaneWorkspacePackage(pkg)) - .filter((pkg): pkg is ControlPlaneWorkspacePackage => pkg !== null); - if (workspacePackages.length !== (value.workspacePackages ?? []).length) { - return null; - } - const stateContexts = (value.stateContexts ?? []) - .map((context) => parseControlPlaneStateContext(context)) - .filter((context): context is ControlPlaneStateContext => context !== null); - if (stateContexts.length !== (value.stateContexts ?? []).length) { - return null; - } - const replSessions = (value.replSessions ?? []) - .map((session) => parseControlPlaneReplSession(session)) - .filter((session): session is ControlPlaneReplSession => session !== null); - if (replSessions.length !== (value.replSessions ?? []).length) { - return null; - } - const devices = (value.devices ?? []) - .map((device) => parseControlPlaneDevice(device)) - .filter((device): device is ControlPlaneDevice => device !== null); - if (devices.length !== (value.devices ?? []).length) { - return null; - } - const packages = value.packages - .map((pkg) => parseControlPlaneRunningPackage(pkg)) - .filter((pkg): pkg is ControlPlaneRunningPackage => pkg !== null); - if (packages.length !== value.packages.length) { - return null; - } - const checks = value.checks - .map((result) => parseControlPlaneCheckResult(result)) - .filter((result): result is ControlPlaneCheckResult => result !== null); - if (checks.length !== value.checks.length) { - return null; - } - const descriptions = value.descriptions - .map((entry) => parseControlPlaneSchemaDescriptionResult(entry)) - .filter( - (entry): entry is ControlPlaneSchemaDescriptionResult => entry !== null, - ); - if (descriptions.length !== value.descriptions.length) { - return null; - } - return { - generatedAt: value.generatedAt, - workspacePackages, - stateContexts, - replSessions, - devices, - packages, - checks, - descriptions, - }; -}; +export const ControlPlaneBrowserResponseMessageSchema = z.union([ + z.object({ + type: z.literal("response"), + requestId: nonEmptyString, + ok: z.literal(true), + result: z.unknown().optional(), + }), + z.object({ + type: z.literal("response"), + requestId: nonEmptyString, + ok: z.literal(false), + error: z.string(), + }), +]); -export const parseControlPlaneCutoverResponse = ( - value: unknown, -): ControlPlaneCutoverResponse | null => { - if (!isRecord(value) || !Array.isArray(value.packages)) { - return null; - } - const packages = value.packages - .map((pkg) => parseControlPlaneRunningPackage(pkg)) - .filter((pkg): pkg is ControlPlaneRunningPackage => pkg !== null); - if (packages.length !== value.packages.length) { - return null; - } - return { - packages, - }; -}; +export const ControlPlaneBrowserSubscriptionDataMessageSchema = z.object({ + type: z.literal("subscription-data"), + subscriptionId: nonEmptyString, + data: z.unknown(), +}); -export const parseControlPlaneDevicesResponse = ( - value: unknown, -): ControlPlaneDevicesResponse | null => { - if (!isRecord(value) || !Array.isArray(value.devices)) { - return null; - } - const devices = value.devices - .map((device) => parseControlPlaneDevice(device)) - .filter((device): device is ControlPlaneDevice => device !== null); - if (devices.length !== value.devices.length) { - return null; - } - return { devices }; -}; +export const ControlPlaneBrowserAuthAckMessageSchema = z.object({ + type: z.literal("auth-ack"), +}); -export const parseControlPlaneDeviceSessionResponse = ( - value: unknown, -): ControlPlaneDeviceSessionResponse | null => { - if (!isRecord(value)) { - return null; - } - const device = parseControlPlaneDevice(value.device); - if (!device) { - return null; - } - return { device }; -}; +export const ControlPlaneBrowserStatusInvalidatedMessageSchema = z.object({ + type: z.literal("status-invalidated"), + reason: z.enum([ + "state-context-opened", + "state-context-closed", + "running-packages-changed", + "repl-sessions-changed", + "runtime-errors-changed", + "devices-changed", + ]), +}); -export const parseControlPlaneReplEvalResponse = ( - value: unknown, -): ControlPlaneReplEvalResponse | null => { - if ( - !isRecord(value) || - typeof value.created !== "boolean" || - typeof value.closed !== "boolean" || - typeof value.ok !== "boolean" || - !isNullableString(value.result) || - !Array.isArray(value.logs) || - !isNullableString(value.error) - ) { - return null; - } - const session = parseControlPlaneReplSession(value.session); - if (!session) { - return null; - } - const logs = value.logs - .map((entry) => parseControlPlaneReplLogEntry(entry)) - .filter((entry): entry is ControlPlaneReplLogEntry => entry !== null); - if (logs.length !== value.logs.length) { - return null; - } - return { - session, - created: value.created, - closed: value.closed, - ok: value.ok, - result: value.result, - logs, - error: value.error, - }; -}; +export const ControlPlaneBrowserServerMessageSchema = z.union([ + ControlPlaneBrowserAuthAckMessageSchema, + ControlPlaneBrowserStatusInvalidatedMessageSchema, + ControlPlaneBrowserResponseMessageSchema, + ControlPlaneBrowserSubscriptionDataMessageSchema, +]); -export const parseControlPlaneReplCloseResponse = ( - value: unknown, -): ControlPlaneReplCloseResponse | null => { - if ( - !isRecord(value) || - !isString(value.sessionId) || - typeof value.closed !== "boolean" - ) { - return null; - } - return { - sessionId: value.sessionId, - closed: value.closed, - }; -}; +export const ControlPlaneDeviceSocketConnectMessageSchema = z.object({ + type: z.literal("device-connect"), + deviceId: nonEmptyString, + sessionToken: nonEmptyString, + requestedTarget: ControlPlaneDeviceTargetSchema.nullable().optional(), + userAgent: z.string().nullable().optional(), + viewport: ControlPlaneDeviceViewportSchema.nullable().optional(), +}); -export const parseControlPlaneLogsResponse = ( - value: unknown, -): ControlPlaneLogsResponse | null => { - if (!isRecord(value) || !isString(value.packageName) || !Array.isArray(value.entries)) { - return null; - } - const entries = value.entries - .map((entry) => parseControlPlanePackageLogEntry(entry)) - .filter((entry): entry is ControlPlanePackageLogEntry => entry !== null); - if (entries.length !== value.entries.length) { - return null; - } - return { - packageName: value.packageName, - entries, - }; -}; +export const ControlPlaneDeviceSocketUpdateMessageSchema = z.object({ + type: z.literal("device-update"), + viewport: ControlPlaneDeviceViewportSchema.nullable().optional(), +}); -export const parseControlPlaneErrorsResponse = ( - value: unknown, -): ControlPlaneErrorsResponse | null => { - if ( - !isRecord(value) || - !Array.isArray(value.entries) || - !( - typeof value.acknowledgedCount === "number" && - Number.isInteger(value.acknowledgedCount) && - value.acknowledgedCount >= 0 - ) - ) { - return null; - } - const entries = value.entries - .map((entry) => parseControlPlanePackageErrorEntry(entry)) - .filter((entry): entry is ControlPlanePackageErrorEntry => entry !== null); - if (entries.length !== value.entries.length) { - return null; - } - return { - entries, - acknowledgedCount: value.acknowledgedCount, - }; -}; +export const ControlPlaneDeviceSocketClientMessageSchema = + z.discriminatedUnion("type", [ + ControlPlaneDeviceSocketConnectMessageSchema, + ControlPlaneDeviceSocketUpdateMessageSchema, + ]); -export const parseControlPlaneClearStateResponse = ( - value: unknown, -): ControlPlaneClearStateResponse | null => { - if ( - !isRecord(value) || - !isStringArray(value.packageNames) || - !isStringArray(value.clearedDirectories) || - !Array.isArray(value.packages) - ) { - return null; - } - const packages = value.packages - .map((pkg) => parseControlPlaneRunningPackage(pkg)) - .filter((pkg): pkg is ControlPlaneRunningPackage => pkg !== null); - if (packages.length !== value.packages.length) { - return null; - } - return { - packageNames: value.packageNames, - clearedDirectories: value.clearedDirectories, - packages, - }; -}; +export const ControlPlaneDeviceSocketReadyMessageSchema = z.object({ + type: z.literal("device-ready"), + device: ControlPlaneDeviceSchema, +}); + +export const ControlPlaneDeviceSocketStateMessageSchema = z.object({ + type: z.literal("device-state"), + device: ControlPlaneDeviceSchema, +}); + +export const ControlPlaneDeviceSocketRemovedMessageSchema = z.object({ + type: z.literal("device-removed"), + deviceId: nonEmptyString, +}); + +export const ControlPlaneDeviceSocketServerMessageSchema = + z.discriminatedUnion("type", [ + ControlPlaneDeviceSocketReadyMessageSchema, + ControlPlaneDeviceSocketStateMessageSchema, + ControlPlaneDeviceSocketRemovedMessageSchema, + ]); + +export const ControlPlanePackageLogEntrySchema = z.object({ + id: z.string(), + createdAt: z.string(), + packageName: z.string(), + label: z.string(), + processId: z.number().nullable(), + stream: z.enum(["stdout", "stderr"]), + text: z.string(), +}); + +export const ControlPlaneRuntimeErrorPhaseSchema = z.enum([ + "on-create", + "on-destroy", + "on-context-open", + "on-context-close", + "browser-surface", + "function", + "event-subscribe", + "event-cleanup", + "value-get", + "value-watch", + "value-cleanup", + "subscription-publish", + "internal", +]); + +export const ControlPlanePackageErrorEntrySchema = z.object({ + id: z.string(), + createdAt: z.string(), + packageName: z.string(), + label: nullableString, + processId: z.number().nullable(), + stateContextId: nullableString, + phase: ControlPlaneRuntimeErrorPhaseSchema, + functionName: nullableString, + resourceKind: z.enum(["event", "value"]).nullable(), + resourceName: nullableString, + surfaceId: optionalNullableStringAsNull, + hostSessionId: optionalNullableStringAsNull, + message: z.string(), + stack: nullableString, + acknowledgedAt: nullableString, +}); + +export const ControlPlaneLogsResponseSchema = z.object({ + packageName: z.string(), + entries: z.array(ControlPlanePackageLogEntrySchema), +}); + +export const ControlPlaneErrorsResponseSchema = z.object({ + entries: z.array(ControlPlanePackageErrorEntrySchema), + acknowledgedCount: z.number().int().nonnegative(), +}); + +export const ControlPlaneReplLogEntrySchema = z.object({ + level: z.enum(["log", "info", "warn", "error"]), + text: z.string(), +}); + +export const ControlPlaneReplSessionSchema = z.object({ + sessionId: z.string(), + createdAt: z.string(), + lastActivityAt: z.string(), + ownedStateContextIds: z.array(z.string()), + borrowedStateContextIds: z.array(z.string()), + subscriptionCount: z.number(), + tempDirectory: z.string(), +}); + +export const ControlPlaneReplEvalResponseSchema = z.object({ + session: ControlPlaneReplSessionSchema, + created: z.boolean(), + closed: z.boolean(), + ok: z.boolean(), + result: nullableString, + logs: z.array(ControlPlaneReplLogEntrySchema), + error: nullableString, +}); + +export const ControlPlaneReplCloseResponseSchema = z.object({ + sessionId: z.string(), + closed: z.boolean(), +}); + +export const ControlPlaneRemoteDomPayloadSchema = z.object({ + protocol: z.string(), + revision: z.number(), + baseRevision: z.number().nullable(), + fromEmpty: z.boolean(), + mutations: z.array(z.unknown()), +}); + +export const ControlPlaneDependencyInputSchema = z.object({ + inputName: z.string(), + targetNodeId: z.string(), +}); + +export const ControlPlaneDependencyNodeSchema = z.object({ + nodeId: z.string(), + label: z.string(), + originalRef: nullableString, + lockedRef: nullableString, + version: nullableString, + inputs: z.array(ControlPlaneDependencyInputSchema), +}); + +export const ControlPlaneDependencyGraphSchema = z.object({ + rootNodeId: z.string(), + nodes: z.array(ControlPlaneDependencyNodeSchema), +}); + +export const ControlPlaneRunningPackageSchema = z.object({ + key: z.string(), + label: z.string(), + packageName: z.string(), + flakeRef: z.string(), + requestedRef: nullableString, + connected: z.boolean(), + processId: z.number().nullable(), + openedStateContextIds: z.array(z.string()), + rootStateContextIds: z.array(z.string()), + resolvedRef: nullableString, + version: nullableString, + unreadErrorCount: z.number().int().nonnegative(), + lastErrorAt: nullableString, + dependencyGraph: ControlPlaneDependencyGraphSchema.nullable(), + dependencyGraphError: nullableString, +}); + +export const ControlPlaneCheckResultSchema = z.object({ + packageName: z.string(), + rev: z.string(), + status: z.enum(["running", "passed", "failed"]), + startedAt: z.string(), + finishedAt: nullableString, + summary: nullableString, + logExcerpt: nullableString, +}); + +export const ControlPlaneSchemaAnnotationSchema = z + .object({ + type: z.string(), + }) + .catchall(z.unknown()); + +export const ControlPlaneSchemaResourceDescriptionSchema = z.object({ + name: z.string(), + description: nullableString, + annotations: z.array(ControlPlaneSchemaAnnotationSchema).default([]), + takesParams: z.boolean(), + inputDescription: nullableString, + inputJsonSchema: jsonRecord.nullable().optional().transform( + (value) => value ?? null, + ), + outputDescription: nullableString, + outputJsonSchema: jsonRecord.nullable().optional().transform( + (value) => value ?? null, + ), + paramsDescription: nullableString, + paramsJsonSchema: jsonRecord.nullable().optional().transform( + (value) => value ?? null, + ), + dataDescription: nullableString, + dataJsonSchema: jsonRecord.nullable().optional().transform( + (value) => value ?? null, + ), + history: z.boolean().optional(), + payloadMode: nullableString, +}); + +export const ControlPlanePackageSchemaDescriptionSchema = z.object({ + packageName: z.string(), + schemaPackageName: z.string(), + description: nullableString, + annotations: z.array(ControlPlaneSchemaAnnotationSchema).default([]), + functions: z.array(ControlPlaneSchemaResourceDescriptionSchema), + events: z.array(ControlPlaneSchemaResourceDescriptionSchema), + values: z.array(ControlPlaneSchemaResourceDescriptionSchema), +}); + +export const ControlPlaneSchemaDescriptionResultSchema = z.object({ + packageName: z.string(), + rev: z.string(), + generatedAt: z.string(), + status: z.enum(["available", "unavailable"]), + data: ControlPlanePackageSchemaDescriptionSchema.nullable(), + error: nullableString, +}); + +export const ControlPlaneRunResponseSchema = z.object({ + stateContextId: z.string(), + package: ControlPlaneRunningPackageSchema, +}); + +export const ControlPlaneClearStateResponseSchema = z.object({ + packageNames: z.array(z.string()), + clearedDirectories: z.array(z.string()), + packages: z.array(ControlPlaneRunningPackageSchema), +}); + +export const ControlPlaneStatusResponseSchema = z.object({ + generatedAt: z.string(), + workspacePackages: z.array(ControlPlaneWorkspacePackageSchema).default([]), + stateContexts: z.array(ControlPlaneStateContextSchema).default([]), + replSessions: z.array(ControlPlaneReplSessionSchema).default([]), + devices: z.array(ControlPlaneDeviceSchema).default([]), + packages: z.array(ControlPlaneRunningPackageSchema), + checks: z.array(ControlPlaneCheckResultSchema), + descriptions: z.array(ControlPlaneSchemaDescriptionResultSchema), +}); + +export const ControlPlaneCutoverResponseSchema = z.object({ + packages: z.array(ControlPlaneRunningPackageSchema), +}); + +export type ControlPlaneRunRequest = z.output< + typeof ControlPlaneRunRequestSchema +>; +export type ControlPlaneCheckRequest = z.output< + typeof ControlPlaneCheckRequestSchema +>; +export type ControlPlaneCutoverRequest = z.output< + typeof ControlPlaneCutoverRequestSchema +>; +export type ControlPlaneClearStateRequest = z.output< + typeof ControlPlaneClearStateRequestSchema +>; +export type ControlPlaneDescribeRequest = z.output< + typeof ControlPlaneDescribeRequestSchema +>; +export type ControlPlaneLogsRequest = z.output< + typeof ControlPlaneLogsRequestSchema +>; +export type ControlPlaneErrorsRequest = z.output< + typeof ControlPlaneErrorsRequestSchema +>; +export type ControlPlaneReplEvalRequest = z.output< + typeof ControlPlaneReplEvalRequestSchema +>; +export type ControlPlaneReplCloseRequest = z.output< + typeof ControlPlaneReplCloseRequestSchema +>; +export type ControlPlaneDeviceTarget = z.output< + typeof ControlPlaneDeviceTargetSchema +>; +export type ControlPlaneDeviceViewport = z.output< + typeof ControlPlaneDeviceViewportSchema +>; +export type ControlPlaneDevice = z.output; +export type ControlPlaneDevicesResponse = z.output< + typeof ControlPlaneDevicesResponseSchema +>; +export type ControlPlaneDeviceAssignRequest = z.output< + typeof ControlPlaneDeviceAssignRequestSchema +>; +export type ControlPlaneDeviceRenameRequest = z.output< + typeof ControlPlaneDeviceRenameRequestSchema +>; +export type ControlPlaneDeviceRemoveRequest = z.output< + typeof ControlPlaneDeviceRemoveRequestSchema +>; +export type ControlPlaneDeviceIdentifyRequest = z.output< + typeof ControlPlaneDeviceIdentifyRequestSchema +>; +export type ControlPlaneDeviceSessionRequest = z.output< + typeof ControlPlaneDeviceSessionRequestSchema +>; +export type ControlPlaneDeviceSessionResponse = z.output< + typeof ControlPlaneDeviceSessionResponseSchema +>; +export type ControlPlanePublicAccessTarget = z.output< + typeof ControlPlanePublicAccessTargetSchema +>; +export type ControlPlanePublicAuthGrantRequest = z.output< + typeof ControlPlanePublicAuthGrantRequestSchema +>; +export type ControlPlanePublicAuthGrantResponse = z.output< + typeof ControlPlanePublicAuthGrantResponseSchema +>; +export type ControlPlanePublicAuthGrantRevokeRequest = z.output< + typeof ControlPlanePublicAuthGrantRevokeRequestSchema +>; +export type ControlPlanePublicAuthGrantRevokeResponse = z.output< + typeof ControlPlanePublicAuthGrantRevokeResponseSchema +>; +export type ControlPlanePublicSessionRequest = z.output< + typeof ControlPlanePublicSessionRequestSchema +>; +export type ControlPlanePublicSessionResponse = z.output< + typeof ControlPlanePublicSessionResponseSchema +>; +export type ControlPlaneSurfaceSessionRequest = z.output< + typeof ControlPlaneSurfaceSessionRequestSchema +>; +export type ControlPlaneSurfaceSessionResponse = z.output< + typeof ControlPlaneSurfaceSessionResponseSchema +>; +export type ControlPlaneWorkspacePackage = z.output< + typeof ControlPlaneWorkspacePackageSchema +>; +export type ControlPlaneStateContext = z.output< + typeof ControlPlaneStateContextSchema +>; +export type ControlPlaneBrowserAuthMessage = z.output< + typeof ControlPlaneBrowserAuthMessageSchema +>; +export type ControlPlaneBrowserOpenRootContextParams = z.output< + typeof ControlPlaneBrowserOpenRootContextParamsSchema +>; +export type ControlPlaneBrowserOpenDerivedContextParams = z.output< + typeof ControlPlaneBrowserOpenDerivedContextParamsSchema +>; +export type ControlPlaneBrowserCloseStateContextParams = z.output< + typeof ControlPlaneBrowserCloseStateContextParamsSchema +>; +export type ControlPlaneBrowserCallParams = z.output< + typeof ControlPlaneBrowserCallParamsSchema +>; +export type ControlPlaneBrowserValueGetParams = z.output< + typeof ControlPlaneBrowserValueGetParamsSchema +>; +export type ControlPlaneBrowserSubscribeParams = z.output< + typeof ControlPlaneBrowserSubscribeParamsSchema +>; +export type ControlPlaneBrowserUnsubscribeParams = z.output< + typeof ControlPlaneBrowserUnsubscribeParamsSchema +>; +export type ControlPlaneBrowserSubscriptionReadyParams = z.output< + typeof ControlPlaneBrowserSubscriptionReadyParamsSchema +>; +export type ControlPlaneBrowserRequestMessage = z.output< + typeof ControlPlaneBrowserRequestMessageSchema +>; +export type ControlPlaneBrowserClientMessage = z.output< + typeof ControlPlaneBrowserClientMessageSchema +>; +export type ControlPlaneBrowserResponseMessage = z.output< + typeof ControlPlaneBrowserResponseMessageSchema +>; +export type ControlPlaneBrowserSubscriptionDataMessage = z.output< + typeof ControlPlaneBrowserSubscriptionDataMessageSchema +>; +export type ControlPlaneBrowserAuthAckMessage = z.output< + typeof ControlPlaneBrowserAuthAckMessageSchema +>; +export type ControlPlaneBrowserStatusInvalidatedMessage = z.output< + typeof ControlPlaneBrowserStatusInvalidatedMessageSchema +>; +export type ControlPlaneBrowserServerMessage = z.output< + typeof ControlPlaneBrowserServerMessageSchema +>; +export type ControlPlaneDeviceSocketConnectMessage = z.output< + typeof ControlPlaneDeviceSocketConnectMessageSchema +>; +export type ControlPlaneDeviceSocketUpdateMessage = z.output< + typeof ControlPlaneDeviceSocketUpdateMessageSchema +>; +export type ControlPlaneDeviceSocketClientMessage = z.output< + typeof ControlPlaneDeviceSocketClientMessageSchema +>; +export type ControlPlaneDeviceSocketReadyMessage = z.output< + typeof ControlPlaneDeviceSocketReadyMessageSchema +>; +export type ControlPlaneDeviceSocketStateMessage = z.output< + typeof ControlPlaneDeviceSocketStateMessageSchema +>; +export type ControlPlaneDeviceSocketRemovedMessage = z.output< + typeof ControlPlaneDeviceSocketRemovedMessageSchema +>; +export type ControlPlaneDeviceSocketServerMessage = z.output< + typeof ControlPlaneDeviceSocketServerMessageSchema +>; +export type ControlPlanePackageLogEntry = z.output< + typeof ControlPlanePackageLogEntrySchema +>; +export type ControlPlaneRuntimeErrorPhase = z.output< + typeof ControlPlaneRuntimeErrorPhaseSchema +>; +export type ControlPlanePackageErrorEntry = z.output< + typeof ControlPlanePackageErrorEntrySchema +>; +export type ControlPlaneLogsResponse = z.output< + typeof ControlPlaneLogsResponseSchema +>; +export type ControlPlaneErrorsResponse = z.output< + typeof ControlPlaneErrorsResponseSchema +>; +export type ControlPlaneReplLogEntry = z.output< + typeof ControlPlaneReplLogEntrySchema +>; +export type ControlPlaneReplSession = z.output< + typeof ControlPlaneReplSessionSchema +>; +export type ControlPlaneReplEvalResponse = z.output< + typeof ControlPlaneReplEvalResponseSchema +>; +export type ControlPlaneReplCloseResponse = z.output< + typeof ControlPlaneReplCloseResponseSchema +>; +export type ControlPlaneRemoteDomPayload = z.output< + typeof ControlPlaneRemoteDomPayloadSchema +>; +export type ControlPlaneDependencyInput = z.output< + typeof ControlPlaneDependencyInputSchema +>; +export type ControlPlaneDependencyNode = z.output< + typeof ControlPlaneDependencyNodeSchema +>; +export type ControlPlaneDependencyGraph = z.output< + typeof ControlPlaneDependencyGraphSchema +>; +export type ControlPlaneRunningPackage = z.output< + typeof ControlPlaneRunningPackageSchema +>; +export type ControlPlaneCheckStatus = z.output< + typeof ControlPlaneCheckResultSchema +>["status"]; +export type ControlPlaneCheckResult = z.output< + typeof ControlPlaneCheckResultSchema +>; +export type ControlPlaneSchemaResourceDescription = z.output< + typeof ControlPlaneSchemaResourceDescriptionSchema +>; +export type ControlPlanePackageSchemaDescription = z.output< + typeof ControlPlanePackageSchemaDescriptionSchema +>; +export type ControlPlaneSchemaDescriptionResult = z.output< + typeof ControlPlaneSchemaDescriptionResultSchema +>; +export type ControlPlaneRunResponse = z.output< + typeof ControlPlaneRunResponseSchema +>; +export type ControlPlaneClearStateResponse = z.output< + typeof ControlPlaneClearStateResponseSchema +>; +export type ControlPlaneStatusResponse = z.output< + typeof ControlPlaneStatusResponseSchema +>; +export type ControlPlaneCutoverResponse = z.output< + typeof ControlPlaneCutoverResponseSchema +>; + +export const parseControlPlaneDeviceTarget = (value: unknown) => + parseWith(ControlPlaneDeviceTargetSchema, value); +export const parseControlPlanePublicAccessTarget = (value: unknown) => + parseWith(ControlPlanePublicAccessTargetSchema, value); +export const parseControlPlaneDevice = (value: unknown) => + parseWith(ControlPlaneDeviceSchema, value); +export const parseControlPlaneRunRequest = (value: unknown) => + parseWith(ControlPlaneRunRequestSchema, value); +export const parseControlPlaneCheckRequest = (value: unknown) => + parseWith(ControlPlaneCheckRequestSchema, value); +export const parseControlPlaneCutoverRequest = (value: unknown) => + parseWith(ControlPlaneCutoverRequestSchema, value); +export const parseControlPlaneClearStateRequest = (value: unknown) => + parseWith(ControlPlaneClearStateRequestSchema, value); +export const parseControlPlaneDescribeRequest = (value: unknown) => + parseWith(ControlPlaneDescribeRequestSchema, value); +export const parseControlPlaneLogsRequest = (value: unknown) => + parseWith(ControlPlaneLogsRequestSchema, value); +export const parseControlPlaneErrorsRequest = (value: unknown) => + parseWith(ControlPlaneErrorsRequestSchema, value); +export const parseControlPlaneDeviceAssignRequest = (value: unknown) => + parseWith(ControlPlaneDeviceAssignRequestSchema, value); +export const parseControlPlaneDeviceRenameRequest = (value: unknown) => + parseWith(ControlPlaneDeviceRenameRequestSchema, value); +export const parseControlPlaneDeviceRemoveRequest = (value: unknown) => + parseWith(ControlPlaneDeviceRemoveRequestSchema, value); +export const parseControlPlaneDeviceIdentifyRequest = (value: unknown) => + parseWith(ControlPlaneDeviceIdentifyRequestSchema, value); +export const parseControlPlaneDeviceSessionRequest = (value: unknown) => + parseWith(ControlPlaneDeviceSessionRequestSchema, value); +export const parseControlPlanePublicAuthGrantRequest = (value: unknown) => + parseWith(ControlPlanePublicAuthGrantRequestSchema, value); +export const parseControlPlanePublicSessionRequest = (value: unknown) => + parseWith(ControlPlanePublicSessionRequestSchema, value); +export const parseControlPlanePublicAuthGrantRevokeRequest = (value: unknown) => + parseWith(ControlPlanePublicAuthGrantRevokeRequestSchema, value); +export const parseControlPlaneSurfaceSessionRequest = (value: unknown) => + parseWith(ControlPlaneSurfaceSessionRequestSchema, value); +export const parseControlPlaneReplEvalRequest = (value: unknown) => + parseWith(ControlPlaneReplEvalRequestSchema, value); +export const parseControlPlaneReplCloseRequest = (value: unknown) => + parseWith(ControlPlaneReplCloseRequestSchema, value); +export const parseControlPlaneDeviceSocketClientMessage = (value: unknown) => + parseWith(ControlPlaneDeviceSocketClientMessageSchema, value); +export const parseControlPlaneDeviceSocketServerMessage = (value: unknown) => + parseWith(ControlPlaneDeviceSocketServerMessageSchema, value); +export const parseControlPlaneBrowserClientMessage = (value: unknown) => + parseWith(ControlPlaneBrowserClientMessageSchema, value); +export const parseControlPlaneReplSession = (value: unknown) => + parseWith(ControlPlaneReplSessionSchema, value); +export const parseControlPlaneRunningPackage = (value: unknown) => + parseWith(ControlPlaneRunningPackageSchema, value); +export const parseControlPlanePackageLogEntry = (value: unknown) => + parseWith(ControlPlanePackageLogEntrySchema, value); +export const parseControlPlanePackageErrorEntry = (value: unknown) => + parseWith(ControlPlanePackageErrorEntrySchema, value); +export const parseControlPlaneStateContext = (value: unknown) => + parseWith(ControlPlaneStateContextSchema, value); +export const parseControlPlaneCheckResult = (value: unknown) => + parseWith(ControlPlaneCheckResultSchema, value); +export const parseControlPlaneSchemaDescriptionResult = (value: unknown) => + parseWith(ControlPlaneSchemaDescriptionResultSchema, value); +export const parseControlPlaneRunResponse = (value: unknown) => + parseWith(ControlPlaneRunResponseSchema, value); +export const parseControlPlaneStatusResponse = (value: unknown) => + parseWith(ControlPlaneStatusResponseSchema, value); +export const parseControlPlaneCutoverResponse = (value: unknown) => + parseWith(ControlPlaneCutoverResponseSchema, value); +export const parseControlPlaneDevicesResponse = (value: unknown) => + parseWith(ControlPlaneDevicesResponseSchema, value); +export const parseControlPlaneDeviceSessionResponse = (value: unknown) => + parseWith(ControlPlaneDeviceSessionResponseSchema, value); +export const parseControlPlaneReplEvalResponse = (value: unknown) => + parseWith(ControlPlaneReplEvalResponseSchema, value); +export const parseControlPlaneReplCloseResponse = (value: unknown) => + parseWith(ControlPlaneReplCloseResponseSchema, value); +export const parseControlPlaneLogsResponse = (value: unknown) => + parseWith(ControlPlaneLogsResponseSchema, value); +export const parseControlPlaneErrorsResponse = (value: unknown) => + parseWith(ControlPlaneErrorsResponseSchema, value); +export const parseControlPlaneClearStateResponse = (value: unknown) => + parseWith(ControlPlaneClearStateResponseSchema, value); diff --git a/src/rpc.ts b/src/rpc.ts new file mode 100644 index 0000000..1fba228 --- /dev/null +++ b/src/rpc.ts @@ -0,0 +1,151 @@ +import z from "zod"; + +export const JsonRpcVersionSchema = z.literal("2.0"); + +export const JsonRpcIdSchema = z.union([ + z.string().min(1), + z.number().finite(), +]); + +export const JsonRpcIdempotencyMetadataSchema = z + .object({ + idempotencyKey: z.string().min(1).optional(), + fingerprint: z.string().min(1).optional(), + }) + .strict(); + +export const JsonRpcRequestSchema = z.object({ + jsonrpc: JsonRpcVersionSchema, + id: JsonRpcIdSchema, + method: z.string().min(1), + params: z.unknown().optional(), + meta: JsonRpcIdempotencyMetadataSchema.optional(), +}); + +export const JsonRpcNotificationSchema = z.object({ + jsonrpc: JsonRpcVersionSchema, + method: z.string().min(1), + params: z.unknown().optional(), + meta: JsonRpcIdempotencyMetadataSchema.optional(), +}); + +export const JsonRpcErrorObjectSchema = z.object({ + code: z.number().int(), + message: z.string(), + data: z.unknown().optional(), +}); + +export const JsonRpcSuccessResponseSchema = z.object({ + jsonrpc: JsonRpcVersionSchema, + id: JsonRpcIdSchema, + result: z.unknown().optional(), +}); + +export const JsonRpcErrorResponseSchema = z.object({ + jsonrpc: JsonRpcVersionSchema, + id: JsonRpcIdSchema, + error: JsonRpcErrorObjectSchema, +}); + +export const JsonRpcResponseSchema = z.union([ + JsonRpcSuccessResponseSchema, + JsonRpcErrorResponseSchema, +]); + +export const JsonRpcMessageSchema = z.union([ + JsonRpcRequestSchema, + JsonRpcNotificationSchema, + JsonRpcResponseSchema, +]); + +export const JsonRpcBatchSchema = z.array(JsonRpcMessageSchema).min(1); + +export const JsonRpcPayloadSchema = z.union([ + JsonRpcMessageSchema, + JsonRpcBatchSchema, +]); + +export type JsonRpcId = z.output; +export type JsonRpcIdempotencyMetadata = z.output< + typeof JsonRpcIdempotencyMetadataSchema +>; +export type JsonRpcRequest = z.output; +export type JsonRpcNotification = z.output; +export type JsonRpcErrorObject = z.output; +export type JsonRpcSuccessResponse = z.output< + typeof JsonRpcSuccessResponseSchema +>; +export type JsonRpcErrorResponse = z.output; +export type JsonRpcResponse = z.output; +export type JsonRpcMessage = z.output; +export type JsonRpcPayload = z.output; + +export const parseJsonRpcPayload = (value: unknown): JsonRpcPayload | null => { + const parsed = JsonRpcPayloadSchema.safeParse(value); + return parsed.success ? parsed.data : null; +}; + +export const makeJsonRpcRequest = ({ + id, + method, + params, + meta, +}: { + id: JsonRpcId; + method: string; + params?: unknown; + meta?: JsonRpcIdempotencyMetadata; +}): JsonRpcRequest => ({ + jsonrpc: "2.0", + id, + method, + ...(params === undefined ? {} : { params }), + ...(meta === undefined ? {} : { meta }), +}); + +export const makeJsonRpcNotification = ({ + method, + params, + meta, +}: { + method: string; + params?: unknown; + meta?: JsonRpcIdempotencyMetadata; +}): JsonRpcNotification => ({ + jsonrpc: "2.0", + method, + ...(params === undefined ? {} : { params }), + ...(meta === undefined ? {} : { meta }), +}); + +export const makeJsonRpcSuccessResponse = ({ + id, + result, +}: { + id: JsonRpcId; + result?: unknown; +}): JsonRpcSuccessResponse => ({ + jsonrpc: "2.0", + id, + ...(result === undefined ? {} : { result }), +}); + +export const makeJsonRpcErrorResponse = ({ + id, + code, + message, + data, +}: { + id: JsonRpcId; + code: number; + message: string; + data?: unknown; +}): JsonRpcErrorResponse => ({ + jsonrpc: "2.0", + id, + error: { + code, + message, + ...(data === undefined ? {} : { data }), + }, +}); diff --git a/yarn.lock b/yarn.lock index 5f86521..edcd319 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11,6 +11,7 @@ __metadata: dependencies: "@types/node": "npm:^24" typescript: "npm:^5.9.3" + zod: "npm:^4.3.6" languageName: unknown linkType: soft @@ -49,3 +50,10 @@ __metadata: checksum: 10c0/85a79189113a238959d7a647368e4f7c5559c3a404ebdb8fc4488145ce9426fcd82252a844a302798dfc0e37e6fb178ff481ed03bc4caf634c5757d9ef43521d languageName: node linkType: hard + +"zod@npm:^4.3.6": + version: 4.4.3 + resolution: "zod@npm:4.4.3" + checksum: 10c0/7ea31b558e88f9faf44f31dd185e2e1cbf51fed3081787fb96cc2534749b50c0acfc6da7f0922a7353ed092dd358c7d50c28ea96c94d04af64191bd33152eca3 + languageName: node + linkType: hard