Skip to content

Commit 491d13d

Browse files
authored
feat: support for creating sessions (#32)
* feat: add support for creating sessions * support autoConnect and createReadOnly
1 parent 0e5f742 commit 491d13d

File tree

7 files changed

+425
-29
lines changed

7 files changed

+425
-29
lines changed

openapi.json

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,91 @@
599599
],
600600
"title": "TokenUpdateResponse"
601601
},
602+
"VMCreateSessionRequest": {
603+
"properties": {
604+
"permission": {
605+
"description": "Permission level for the session",
606+
"enum": ["read", "write"],
607+
"example": "write",
608+
"type": "string"
609+
},
610+
"session_id": {
611+
"description": "Unique identifier for the session",
612+
"example": "my-session-1",
613+
"type": "string"
614+
}
615+
},
616+
"required": ["session_id", "permission"],
617+
"title": "VMCreateSessionRequest",
618+
"type": "object"
619+
},
620+
"VMCreateSessionResponse": {
621+
"allOf": [
622+
{
623+
"properties": {
624+
"errors": {
625+
"items": [
626+
{
627+
"oneOf": [
628+
{ "type": "string" },
629+
{ "additionalProperties": true, "type": "object" }
630+
],
631+
"title": "Error"
632+
}
633+
],
634+
"type": "array"
635+
},
636+
"success": { "type": "boolean" }
637+
},
638+
"title": "Response",
639+
"type": "object"
640+
},
641+
{
642+
"properties": {
643+
"data": {
644+
"properties": {
645+
"capabilities": {
646+
"description": "List of capabilities granted to this session",
647+
"items": { "type": "string" },
648+
"type": "array"
649+
},
650+
"permissions": {
651+
"description": "Detailed permissions for this session",
652+
"type": "object"
653+
},
654+
"pitcher_token": {
655+
"description": "Token to authenticate with Pitcher",
656+
"type": "string"
657+
},
658+
"pitcher_url": {
659+
"description": "WebSocket URL to connect to Pitcher",
660+
"type": "string"
661+
},
662+
"user_workspace_path": {
663+
"description": "Path to the user's workspace in the VM",
664+
"type": "string"
665+
},
666+
"username": {
667+
"description": "The Linux username created for this session",
668+
"type": "string"
669+
}
670+
},
671+
"required": [
672+
"username",
673+
"pitcher_token",
674+
"user_workspace_path",
675+
"capabilities",
676+
"permissions",
677+
"pitcher_url"
678+
],
679+
"type": "object"
680+
}
681+
},
682+
"type": "object"
683+
}
684+
],
685+
"title": "VMCreateSessionResponse"
686+
},
602687
"VMHibernateRequest": { "properties": {}, "title": "VMHibernateRequest" },
603688
"VMHibernateResponse": {
604689
"allOf": [
@@ -1275,6 +1360,49 @@
12751360
"tags": ["vm"]
12761361
}
12771362
},
1363+
"/vm/{id}/sessions": {
1364+
"post": {
1365+
"callbacks": {},
1366+
"description": "Creates a new session on a running VM. A session represents an isolated Linux user, with their own container\nwhile their API token has specific permissions (currently, read or write).\nThe session is identified by a unique session ID, and the username is based on the session ID.\n\nThis endpoint requires the VM to be running. If the VM is not running, it will return a 404 error.\n",
1367+
"operationId": "vm/create_session",
1368+
"parameters": [
1369+
{
1370+
"description": "Sandbox ID",
1371+
"example": "new",
1372+
"in": "path",
1373+
"name": "id",
1374+
"required": true,
1375+
"schema": { "type": "string" }
1376+
}
1377+
],
1378+
"requestBody": {
1379+
"content": {
1380+
"application/json": {
1381+
"schema": {
1382+
"$ref": "#/components/schemas/VMCreateSessionRequest"
1383+
}
1384+
}
1385+
},
1386+
"description": "VM Create Session Request",
1387+
"required": false
1388+
},
1389+
"responses": {
1390+
"200": {
1391+
"content": {
1392+
"application/json": {
1393+
"schema": {
1394+
"$ref": "#/components/schemas/VMCreateSessionResponse"
1395+
}
1396+
}
1397+
},
1398+
"description": "VM Create Session Response"
1399+
}
1400+
},
1401+
"security": [{ "authorization": ["sandbox:read", "vm:manage"] }],
1402+
"summary": "Create a new session on a VM",
1403+
"tags": ["vm"]
1404+
}
1405+
},
12781406
"/vm/{id}/shutdown": {
12791407
"post": {
12801408
"callbacks": {},

src/browser.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
import { initPitcherClient } from "@codesandbox/pitcher-client";
1+
import {
2+
initPitcherClient,
3+
PitcherManagerResponse,
4+
} from "@codesandbox/pitcher-client";
25

3-
import { SandboxWithoutClient } from "./sandbox";
6+
import { SandboxSession } from "./sandbox";
47
import { DEFAULT_SUBSCRIPTIONS, type SandboxStartData } from "./sandbox-client";
8+
import { SessionConnectInfo } from "./sessions";
59

610
export { SandboxStartData };
711

12+
function isStartData(
13+
data: SandboxStartData | SessionConnectInfo
14+
): data is SandboxStartData {
15+
return "bootup_type" in data;
16+
}
17+
818
/**
919
* With this function you can connect to a sandbox from the browser.
1020
*
@@ -41,38 +51,59 @@ export { SandboxStartData };
4151
* ```
4252
*/
4353
export async function connectToSandbox(
44-
startInfo: SandboxStartData,
45-
): Promise<SandboxWithoutClient> {
54+
startInfo: SandboxStartData | SessionConnectInfo
55+
): Promise<SandboxSession> {
56+
const useStartData = isStartData(startInfo);
57+
58+
let requestPitcherInstance: () => Promise<PitcherManagerResponse>;
59+
if (useStartData) {
60+
requestPitcherInstance = async () => {
61+
const data = startInfo;
62+
63+
return {
64+
bootupType: data.bootup_type as "RUNNING" | "CLEAN" | "RESUME" | "FORK",
65+
pitcherURL: data.pitcher_url,
66+
workspacePath: data.workspace_path,
67+
userWorkspacePath: data.user_workspace_path,
68+
pitcherManagerVersion: data.pitcher_manager_version,
69+
pitcherVersion: data.pitcher_version,
70+
latestPitcherVersion: data.latest_pitcher_version,
71+
pitcherToken: data.pitcher_token,
72+
cluster: data.cluster,
73+
};
74+
};
75+
} else {
76+
requestPitcherInstance = async () => {
77+
const data = startInfo;
78+
79+
return {
80+
bootupType: "RESUME",
81+
cluster: "session",
82+
id: data.id,
83+
latestPitcherVersion: "1.0.0-session",
84+
pitcherManagerVersion: "1.0.0-session",
85+
pitcherToken: data.pitcher_token,
86+
pitcherURL: data.pitcher_url,
87+
pitcherVersion: "1.0.0-session",
88+
reconnectToken: "",
89+
userWorkspacePath: data.user_workspace_path,
90+
workspacePath: data.user_workspace_path,
91+
};
92+
};
93+
}
94+
4695
const pitcherClient = await initPitcherClient(
4796
{
4897
appId: "sdk",
4998
instanceId: startInfo.id,
5099
onFocusChange() {
51100
return () => {};
52101
},
53-
requestPitcherInstance: async () => {
54-
const data = startInfo;
55-
56-
return {
57-
bootupType: data.bootup_type as
58-
| "RUNNING"
59-
| "CLEAN"
60-
| "RESUME"
61-
| "FORK",
62-
pitcherURL: data.pitcher_url,
63-
workspacePath: data.workspace_path,
64-
userWorkspacePath: data.user_workspace_path,
65-
pitcherManagerVersion: data.pitcher_manager_version,
66-
pitcherVersion: data.pitcher_version,
67-
latestPitcherVersion: data.latest_pitcher_version,
68-
pitcherToken: data.pitcher_token,
69-
cluster: data.cluster,
70-
};
71-
},
102+
requestPitcherInstance,
72103
subscriptions: DEFAULT_SUBSCRIPTIONS,
73104
},
74-
() => {},
105+
() => {}
75106
);
76107

77-
return new SandboxWithoutClient(pitcherClient);
108+
return new SandboxSession(pitcherClient);
78109
}

src/client/sdk.gen.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

33
import { createClient, createConfig, type OptionsLegacyParser } from '@hey-api/client-fetch';
4-
import type { MetaInfoError, MetaInfoResponse, WorkspaceCreateData, WorkspaceCreateError, WorkspaceCreateResponse2, TokenCreateData, TokenCreateError, TokenCreateResponse2, TokenUpdateData, TokenUpdateError, TokenUpdateResponse2, SandboxListData, SandboxListError, SandboxListResponse2, SandboxCreateData, SandboxCreateError, SandboxCreateResponse2, SandboxGetData, SandboxGetError, SandboxGetResponse2, SandboxForkData, SandboxForkError, SandboxForkResponse2, VmHibernateData, VmHibernateError, VmHibernateResponse, VmUpdateHibernationTimeoutData, VmUpdateHibernationTimeoutError, VmUpdateHibernationTimeoutResponse, VmShutdownData, VmShutdownError, VmShutdownResponse, VmUpdateSpecsData, VmUpdateSpecsError, VmUpdateSpecsResponse, VmStartData, VmStartError, VmStartResponse, VmUpdateSpecs2Data, VmUpdateSpecs2Error, VmUpdateSpecs2Response } from './types.gen';
4+
import type { MetaInfoError, MetaInfoResponse, WorkspaceCreateData, WorkspaceCreateError, WorkspaceCreateResponse2, TokenCreateData, TokenCreateError, TokenCreateResponse2, TokenUpdateData, TokenUpdateError, TokenUpdateResponse2, SandboxListData, SandboxListError, SandboxListResponse2, SandboxCreateData, SandboxCreateError, SandboxCreateResponse2, SandboxGetData, SandboxGetError, SandboxGetResponse2, SandboxForkData, SandboxForkError, SandboxForkResponse2, VmHibernateData, VmHibernateError, VmHibernateResponse, VmUpdateHibernationTimeoutData, VmUpdateHibernationTimeoutError, VmUpdateHibernationTimeoutResponse, VmCreateSessionData, VmCreateSessionError, VmCreateSessionResponse, VmShutdownData, VmShutdownError, VmShutdownResponse, VmUpdateSpecsData, VmUpdateSpecsError, VmUpdateSpecsResponse, VmStartData, VmStartError, VmStartResponse, VmUpdateSpecs2Data, VmUpdateSpecs2Error, VmUpdateSpecs2Response } from './types.gen';
55

66
export const client = createClient(createConfig());
77

@@ -133,6 +133,22 @@ export const vmUpdateHibernationTimeout = <ThrowOnError extends boolean = false>
133133
});
134134
};
135135

136+
/**
137+
* Create a new session on a VM
138+
* Creates a new session on a running VM. A session represents an isolated Linux user, with their own container
139+
* while their API token has specific permissions (currently, read or write).
140+
* The session is identified by a unique session ID, and the username is based on the session ID.
141+
*
142+
* This endpoint requires the VM to be running. If the VM is not running, it will return a 404 error.
143+
*
144+
*/
145+
export const vmCreateSession = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<VmCreateSessionData, ThrowOnError>) => {
146+
return (options?.client ?? client).post<VmCreateSessionResponse, VmCreateSessionError, ThrowOnError>({
147+
...options,
148+
url: '/vm/{id}/sessions'
149+
});
150+
};
151+
136152
/**
137153
* Shutdown a VM
138154
* Stops a running VM, ending all currently running processes

src/client/types.gen.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,58 @@ export type TokenUpdateResponse = {
316316
};
317317
};
318318

319+
export type VMCreateSessionRequest = {
320+
/**
321+
* Permission level for the session
322+
*/
323+
permission: 'read' | 'write';
324+
/**
325+
* Unique identifier for the session
326+
*/
327+
session_id: string;
328+
};
329+
330+
/**
331+
* Permission level for the session
332+
*/
333+
export type permission = 'read' | 'write';
334+
335+
export type VMCreateSessionResponse = {
336+
errors?: Array<((string | {
337+
[key: string]: unknown;
338+
}))>;
339+
success?: boolean;
340+
} & {
341+
data?: {
342+
/**
343+
* List of capabilities granted to this session
344+
*/
345+
capabilities: Array<(string)>;
346+
/**
347+
* Detailed permissions for this session
348+
*/
349+
permissions: {
350+
[key: string]: unknown;
351+
};
352+
/**
353+
* Token to authenticate with Pitcher
354+
*/
355+
pitcher_token: string;
356+
/**
357+
* WebSocket URL to connect to Pitcher
358+
*/
359+
pitcher_url: string;
360+
/**
361+
* Path to the user's workspace in the VM
362+
*/
363+
user_workspace_path: string;
364+
/**
365+
* The Linux username created for this session
366+
*/
367+
username: string;
368+
};
369+
};
370+
319371
export type VMHibernateRequest = {
320372
[key: string]: unknown;
321373
};
@@ -594,6 +646,23 @@ export type VmUpdateHibernationTimeoutResponse = (VMUpdateHibernationTimeoutResp
594646

595647
export type VmUpdateHibernationTimeoutError = unknown;
596648

649+
export type VmCreateSessionData = {
650+
/**
651+
* VM Create Session Request
652+
*/
653+
body?: VMCreateSessionRequest;
654+
path: {
655+
/**
656+
* Sandbox ID
657+
*/
658+
id: string;
659+
};
660+
};
661+
662+
export type VmCreateSessionResponse = (VMCreateSessionResponse);
663+
664+
export type VmCreateSessionError = unknown;
665+
597666
export type VmShutdownData = {
598667
/**
599668
* VM Shutdown Request

0 commit comments

Comments
 (0)