File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ import { describe , it , expect } from "vitest" ;
2+ import { getStateExpiresAt } from "@/lib/sandbox/getStateExpiresAt" ;
3+
4+ describe ( "getStateExpiresAt" , ( ) => {
5+ it ( "returns the numeric expiresAt when present" , ( ) => {
6+ expect ( getStateExpiresAt ( { type : "vercel" , expiresAt : 4_102_444_800_000 } ) ) . toBe (
7+ 4_102_444_800_000 ,
8+ ) ;
9+ } ) ;
10+
11+ it ( "returns undefined when expiresAt is not a number" , ( ) => {
12+ expect ( getStateExpiresAt ( { type : "vercel" , expiresAt : "soon" } ) ) . toBeUndefined ( ) ;
13+ expect ( getStateExpiresAt ( { type : "vercel" } ) ) . toBeUndefined ( ) ;
14+ } ) ;
15+
16+ it ( "returns undefined for null / undefined / non-object inputs" , ( ) => {
17+ expect ( getStateExpiresAt ( null ) ) . toBeUndefined ( ) ;
18+ expect ( getStateExpiresAt ( undefined ) ) . toBeUndefined ( ) ;
19+ expect ( getStateExpiresAt ( "nope" ) ) . toBeUndefined ( ) ;
20+ expect ( getStateExpiresAt ( 42 ) ) . toBeUndefined ( ) ;
21+ } ) ;
22+ } ) ;
Original file line number Diff line number Diff line change @@ -4,6 +4,7 @@ import { buildLifecycle } from "@/lib/sandbox/buildLifecycle";
44import { clearUnavailableSandboxState } from "@/lib/sandbox/clearUnavailableSandboxState" ;
55import { connectSandbox } from "@/lib/sandbox/factory" ;
66import { getSandboxExpiresAtDate } from "@/lib/sandbox/getSandboxExpiresAtDate" ;
7+ import { getStateExpiresAt } from "@/lib/sandbox/getStateExpiresAt" ;
78import { hasRuntimeSandboxState } from "@/lib/sandbox/hasRuntimeSandboxState" ;
89import { isSandboxUnavailableError } from "@/lib/sandbox/isSandboxUnavailableError" ;
910import { noSandboxResponse } from "@/lib/sandbox/noSandboxResponse" ;
@@ -21,12 +22,6 @@ interface ReconnectBody {
2122 lifecycle : ReturnType < typeof buildLifecycle > ;
2223}
2324
24- function getStateExpiresAt ( state : unknown ) : number | undefined {
25- if ( ! state || typeof state !== "object" ) return undefined ;
26- const expiresAt = ( state as { expiresAt ?: unknown } ) . expiresAt ;
27- return typeof expiresAt === "number" ? expiresAt : undefined ;
28- }
29-
3025/**
3126 * Handles `GET /api/sandbox/reconnect`. Live runtime probe — actually
3227 * runs a quick command inside the sandbox to verify it is reachable.
Original file line number Diff line number Diff line change 1+ /**
2+ * Reads the runtime `expiresAt` field (epoch ms) off a sandbox state.
3+ * Returns undefined when the input is not an object or when
4+ * `expiresAt` is missing or a non-number — so callers can treat the
5+ * absence of an expiry as "unknown" without coercing to NaN/0.
6+ *
7+ * Distinct from `getSandboxExpiresAtDate`, which formats the same
8+ * field as an ISO-8601 string for persistence to
9+ * `sessions.sandbox_expires_at`.
10+ *
11+ * @param state - The `sandbox_state` JSON value, typically from
12+ * `sandbox.getState()` or the persisted session row.
13+ * @returns Epoch ms expiry, or undefined.
14+ */
15+ export function getStateExpiresAt ( state : unknown ) : number | undefined {
16+ if ( ! state || typeof state !== "object" ) return undefined ;
17+ const expiresAt = ( state as { expiresAt ?: unknown } ) . expiresAt ;
18+ return typeof expiresAt === "number" ? expiresAt : undefined ;
19+ }
You can’t perform that action at this time.
0 commit comments