|
1 | 1 | export const RUNTIME_PROFILE_SCHEMA = "wp-codebox/runtime-profile/v1" as const |
2 | 2 | export const PREVIEW_LEASE_SCHEMA = "wp-codebox/preview-lease/v1" as const |
3 | 3 | export const BROWSER_CONTAINED_SITE_STATUS_SCHEMA = "wp-codebox/browser-contained-site-status/v1" as const |
| 4 | +export const BROWSER_CONTAINED_SITE_OPEN_SCHEMA = "wp-codebox/browser-contained-site-open/v1" as const |
4 | 5 | export const BROWSER_SESSION_PRODUCT_DTO_SCHEMA = "wp-codebox/browser-session-product-dto/v1" as const |
5 | 6 | export const BROWSER_PREVIEW_BOOT_CONFIG_SCHEMA = "wp-codebox/browser-preview-boot-config/v1" as const |
6 | 7 |
|
@@ -87,16 +88,38 @@ export interface PreviewLease { |
87 | 88 | } |
88 | 89 |
|
89 | 90 | export type PreviewLeaseLifecycleStatus = "active" | "expired" | "released" | "unknown" |
| 91 | +export type BrowserContainedSiteLifecycleStatus = "recoverable_prepared_runtime" | "current" | "live" | "materialized" | "miss" | "expired" | "blocked" | "disabled" | "incompatible" | "unknown" | (string & {}) |
| 92 | + |
| 93 | +export interface BrowserContainedSiteIdentity { |
| 94 | + schema: "wp-codebox/browser-contained-site/v1" |
| 95 | + site_id: string |
| 96 | + preview_id?: string |
| 97 | + session_id?: string |
| 98 | + status?: BrowserContainedSiteLifecycleStatus |
| 99 | + source_digest?: { |
| 100 | + algorithm: "sha256" | (string & {}) |
| 101 | + value: string |
| 102 | + } |
| 103 | + resolution?: Record<string, unknown> |
| 104 | + prepared_runtime?: Record<string, unknown> |
| 105 | + blueprint_ref?: Record<string, unknown> |
| 106 | + preview_boot?: BrowserPreviewBootConfig |
| 107 | + preview_lease?: PreviewLease |
| 108 | + session?: Record<string, unknown> |
| 109 | + recovery?: Record<string, unknown> |
| 110 | + metadata?: Record<string, unknown> |
| 111 | +} |
90 | 112 |
|
91 | 113 | export interface BrowserContainedSiteStatus { |
92 | 114 | schema: typeof BROWSER_CONTAINED_SITE_STATUS_SCHEMA |
93 | 115 | success: boolean |
94 | 116 | site_id: string |
95 | | - status: "recoverable" | "miss" | "expired" | "blocked" | "unknown" | (string & {}) |
| 117 | + status: BrowserContainedSiteLifecycleStatus |
96 | 118 | source_digest: { |
97 | 119 | algorithm: "sha256" | (string & {}) |
98 | 120 | value: string |
99 | 121 | } |
| 122 | + resolution?: Record<string, unknown> |
100 | 123 | prepared_runtime?: Record<string, unknown> |
101 | 124 | blueprint_ref?: Record<string, unknown> |
102 | 125 | metadata?: Record<string, unknown> |
@@ -138,6 +161,26 @@ export interface BrowserSessionProductDto { |
138 | 161 | error?: Record<string, unknown> |
139 | 162 | } |
140 | 163 |
|
| 164 | +export interface BrowserContainedSiteOpenEnvelope { |
| 165 | + schema: typeof BROWSER_CONTAINED_SITE_OPEN_SCHEMA |
| 166 | + success: boolean |
| 167 | + site_id: string |
| 168 | + status: BrowserContainedSiteLifecycleStatus |
| 169 | + resolution?: Record<string, unknown> |
| 170 | + contained_site?: BrowserContainedSiteIdentity |
| 171 | + source_digest?: { |
| 172 | + algorithm: "sha256" | (string & {}) |
| 173 | + value: string |
| 174 | + } |
| 175 | + prepared_runtime?: Record<string, unknown> |
| 176 | + blueprint_ref?: Record<string, unknown> |
| 177 | + preview_boot?: BrowserPreviewBootConfig |
| 178 | + preview_lease?: PreviewLease |
| 179 | + preview_session?: BrowserSessionProductDto |
| 180 | + session?: Record<string, unknown> |
| 181 | + recovery?: Record<string, unknown> |
| 182 | +} |
| 183 | + |
141 | 184 | export function runtimeProfile(input: unknown): RuntimeProfile { |
142 | 185 | const value = requireObject(input, "Runtime profile") as Partial<RuntimeProfile> |
143 | 186 | if (value.schema !== RUNTIME_PROFILE_SCHEMA) throw new Error(`Runtime profile schema must be ${RUNTIME_PROFILE_SCHEMA}.`) |
@@ -218,12 +261,109 @@ export function browserContainedSiteStatus(input: unknown): BrowserContainedSite |
218 | 261 | algorithm: optionalString(digest.algorithm, "source_digest.algorithm") ?? "sha256", |
219 | 262 | value: digestValue, |
220 | 263 | }, |
| 264 | + resolution: normalizeOptionalObject(value.resolution, "resolution"), |
221 | 265 | prepared_runtime: normalizeOptionalObject(value.prepared_runtime, "prepared_runtime"), |
222 | 266 | blueprint_ref: normalizeOptionalObject(value.blueprint_ref, "blueprint_ref"), |
223 | 267 | metadata: normalizeOptionalObject(value.metadata, "metadata"), |
224 | 268 | } |
225 | 269 | } |
226 | 270 |
|
| 271 | +export function browserContainedSiteOpenEnvelope(input: unknown): BrowserContainedSiteOpenEnvelope { |
| 272 | + const value = requireObject(input, "Browser contained site open envelope") as Partial<BrowserContainedSiteOpenEnvelope> |
| 273 | + if (value.schema !== BROWSER_CONTAINED_SITE_OPEN_SCHEMA) throw new Error(`Browser contained site open schema must be ${BROWSER_CONTAINED_SITE_OPEN_SCHEMA}.`) |
| 274 | + return { |
| 275 | + schema: BROWSER_CONTAINED_SITE_OPEN_SCHEMA, |
| 276 | + success: value.success === true, |
| 277 | + site_id: requiredIdentifier(value.site_id, "site_id"), |
| 278 | + status: requiredIdentifier(value.status, "status") as BrowserContainedSiteLifecycleStatus, |
| 279 | + resolution: normalizeOptionalObject(value.resolution, "resolution"), |
| 280 | + contained_site: value.contained_site === undefined ? undefined : normalizeContainedSiteIdentity(value.contained_site), |
| 281 | + source_digest: value.source_digest === undefined ? undefined : normalizeSourceDigest(value.source_digest), |
| 282 | + prepared_runtime: normalizeOptionalObject(value.prepared_runtime, "prepared_runtime"), |
| 283 | + blueprint_ref: normalizeOptionalObject(value.blueprint_ref, "blueprint_ref"), |
| 284 | + preview_boot: value.preview_boot === undefined ? undefined : normalizePreviewBootConfig(value.preview_boot), |
| 285 | + preview_lease: value.preview_lease === undefined ? undefined : previewLease(value.preview_lease), |
| 286 | + preview_session: value.preview_session === undefined ? undefined : normalizeBrowserSessionProductDto(value.preview_session), |
| 287 | + session: normalizeOptionalObject(value.session, "session"), |
| 288 | + recovery: normalizeOptionalObject(value.recovery, "recovery"), |
| 289 | + } |
| 290 | +} |
| 291 | + |
| 292 | +function normalizeContainedSiteIdentity(input: unknown): BrowserContainedSiteIdentity { |
| 293 | + const value = requireObject(input, "Browser contained site identity") as Partial<BrowserContainedSiteIdentity> |
| 294 | + if (value.schema !== "wp-codebox/browser-contained-site/v1") throw new Error("Browser contained site identity schema must be wp-codebox/browser-contained-site/v1.") |
| 295 | + return { |
| 296 | + schema: "wp-codebox/browser-contained-site/v1", |
| 297 | + site_id: requiredIdentifier(value.site_id, "contained_site.site_id"), |
| 298 | + preview_id: optionalString(value.preview_id, "contained_site.preview_id"), |
| 299 | + session_id: optionalString(value.session_id, "contained_site.session_id"), |
| 300 | + status: optionalString(value.status, "contained_site.status") as BrowserContainedSiteLifecycleStatus | undefined, |
| 301 | + source_digest: value.source_digest === undefined ? undefined : normalizeSourceDigest(value.source_digest), |
| 302 | + resolution: normalizeOptionalObject(value.resolution, "contained_site.resolution"), |
| 303 | + prepared_runtime: normalizeOptionalObject(value.prepared_runtime, "contained_site.prepared_runtime"), |
| 304 | + blueprint_ref: normalizeOptionalObject(value.blueprint_ref, "contained_site.blueprint_ref"), |
| 305 | + preview_boot: value.preview_boot === undefined ? undefined : normalizePreviewBootConfig(value.preview_boot), |
| 306 | + preview_lease: value.preview_lease === undefined ? undefined : previewLease(value.preview_lease), |
| 307 | + session: normalizeOptionalObject(value.session, "contained_site.session"), |
| 308 | + recovery: normalizeOptionalObject(value.recovery, "contained_site.recovery"), |
| 309 | + metadata: normalizeOptionalObject(value.metadata, "contained_site.metadata"), |
| 310 | + } |
| 311 | +} |
| 312 | + |
| 313 | +function normalizeSourceDigest(input: unknown): { algorithm: "sha256" | (string & {}); value: string } { |
| 314 | + const digest = requireObject(input, "source_digest") as { algorithm?: unknown; value?: unknown } |
| 315 | + const digestValue = optionalString(digest.value, "source_digest.value") |
| 316 | + if (!digestValue || !/^[a-f0-9]{64}$/.test(digestValue)) throw new Error("source_digest.value must be a 64-character sha256 digest.") |
| 317 | + return { |
| 318 | + algorithm: optionalString(digest.algorithm, "source_digest.algorithm") ?? "sha256", |
| 319 | + value: digestValue, |
| 320 | + } |
| 321 | +} |
| 322 | + |
| 323 | +function normalizePreviewBootConfig(input: unknown): BrowserPreviewBootConfig { |
| 324 | + const value = requireObject(input, "Browser preview boot config") as Partial<BrowserPreviewBootConfig> |
| 325 | + if (value.schema !== BROWSER_PREVIEW_BOOT_CONFIG_SCHEMA) throw new Error(`Browser preview boot config schema must be ${BROWSER_PREVIEW_BOOT_CONFIG_SCHEMA}.`) |
| 326 | + return { |
| 327 | + schema: BROWSER_PREVIEW_BOOT_CONFIG_SCHEMA, |
| 328 | + session_id: optionalString(value.session_id, "preview_boot.session_id"), |
| 329 | + scope: optionalString(value.scope, "preview_boot.scope"), |
| 330 | + client_module_url: optionalString(value.client_module_url, "preview_boot.client_module_url"), |
| 331 | + remote_url: optionalString(value.remote_url, "preview_boot.remote_url"), |
| 332 | + cors_proxy_url: optionalString(value.cors_proxy_url, "preview_boot.cors_proxy_url"), |
| 333 | + blueprint_ref: optionalString(value.blueprint_ref, "preview_boot.blueprint_ref"), |
| 334 | + blueprint_ref_dto: normalizeOptionalObject(value.blueprint_ref_dto, "preview_boot.blueprint_ref_dto"), |
| 335 | + preview: value.preview === undefined ? undefined : previewLease(value.preview), |
| 336 | + contained_site: normalizeOptionalObject(value.contained_site, "preview_boot.contained_site"), |
| 337 | + artifacts: normalizeOptionalObject(value.artifacts, "preview_boot.artifacts"), |
| 338 | + provenance: normalizeOptionalObject(value.provenance, "preview_boot.provenance"), |
| 339 | + } |
| 340 | +} |
| 341 | + |
| 342 | +function normalizeBrowserSessionProductDto(input: unknown): BrowserSessionProductDto { |
| 343 | + const value = requireObject(input, "Browser session product DTO") as Partial<BrowserSessionProductDto> |
| 344 | + if (value.schema !== BROWSER_SESSION_PRODUCT_DTO_SCHEMA) throw new Error(`Browser session product DTO schema must be ${BROWSER_SESSION_PRODUCT_DTO_SCHEMA}.`) |
| 345 | + return { |
| 346 | + schema: BROWSER_SESSION_PRODUCT_DTO_SCHEMA, |
| 347 | + source_schema: optionalString(value.source_schema, "preview_session.source_schema"), |
| 348 | + success: value.success === true, |
| 349 | + status: optionalString(value.status, "preview_session.status"), |
| 350 | + execution: optionalString(value.execution, "preview_session.execution"), |
| 351 | + execution_scope: optionalString(value.execution_scope, "preview_session.execution_scope"), |
| 352 | + permission_model: optionalString(value.permission_model, "preview_session.permission_model"), |
| 353 | + session_id: optionalString(value.session_id, "preview_session.session_id"), |
| 354 | + contained_site: normalizeOptionalObject(value.contained_site, "preview_session.contained_site"), |
| 355 | + task: optionalString(value.task, "preview_session.task"), |
| 356 | + target: normalizeOptionalObject(value.target, "preview_session.target"), |
| 357 | + agent: optionalString(value.agent, "preview_session.agent"), |
| 358 | + provider: optionalString(value.provider, "preview_session.provider"), |
| 359 | + model: optionalString(value.model, "preview_session.model"), |
| 360 | + preview_boot: value.preview_boot === undefined ? undefined : normalizePreviewBootConfig(value.preview_boot), |
| 361 | + signals: normalizeOptionalObject(value.signals, "preview_session.signals"), |
| 362 | + artifacts: normalizeOptionalObject(value.artifacts, "preview_session.artifacts"), |
| 363 | + error: normalizeOptionalObject(value.error, "preview_session.error"), |
| 364 | + } |
| 365 | +} |
| 366 | + |
227 | 367 | function normalizeDependencies(value: unknown, label: string, optional = false): RuntimeProfileDependency[] | undefined { |
228 | 368 | if (value === undefined && optional) return undefined |
229 | 369 | if (!Array.isArray(value)) throw new Error(`Runtime profile ${label} must be an array.`) |
|
0 commit comments