Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit15d843e

Browse files
committed
Add xstate service
1 parent31f27bc commit15d843e

File tree

3 files changed

+258
-3
lines changed

3 files changed

+258
-3
lines changed

‎site/src/api/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,21 @@ export const getUsers = async (): Promise<Types.PagedUsers> => {
8585
})
8686
}
8787

88+
exportconstgetOrganizations=async():Promise<Types.Organization[]>=>{
89+
constresponse=awaitaxios.get<Types.Organization[]>("/api/v2/users/me/organizations")
90+
returnresponse.data
91+
}
92+
93+
exportconstgetWorkspace=async(organizationID:string,workspaceName:string):Promise<Types.Workspace>=>{
94+
constresponse=awaitaxios.get<Types.Workspace>(`/api/v2/organizations/${organizationID}/workspaces/me/${workspaceName}`)
95+
returnresponse.data
96+
}
97+
98+
exportconstgetWorkspaceResources=async(workspaceBuildID:string):Promise<Types.WorkspaceResource[]>=>{
99+
constresponse=awaitaxios.get<Types.WorkspaceResource[]>(`/api/v2/workspacebuilds/${workspaceBuildID}/resources`)
100+
returnresponse.data
101+
}
102+
88103
exportconstgetBuildInfo=async():Promise<Types.BuildInfoResponse>=>{
89104
constresponse=awaitaxios.get("/api/v2/buildinfo")
90105
returnresponse.data

‎site/src/api/types.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ export interface CreateWorkspaceRequest {
5555
template_id:string
5656
}
5757

58-
/**
59-
*@remarks Keep in sync with codersdk/workspaces.go
60-
*/
58+
exportinterfaceWorkspaceBuild{
59+
id:string
60+
}
61+
6162
exportinterfaceWorkspace{
6263
id:string
6364
created_at:string
@@ -67,6 +68,17 @@ export interface Workspace {
6768
name:string
6869
autostart_schedule:string
6970
autostop_schedule:string
71+
latest_build:WorkspaceBuild
72+
}
73+
74+
exportinterfaceWorkspaceResource{
75+
id:string
76+
agents:WorkspaceAgent[]
77+
}
78+
79+
exportinterfaceWorkspaceAgent{
80+
id:string
81+
name:string
7082
}
7183

7284
exportinterfaceAPIKeyResponse{
@@ -102,3 +114,9 @@ export interface UpdateProfileRequest {
102114
readonlyemail:string
103115
readonlyname:string
104116
}
117+
118+
exportinterfaceReconnectingPTYRequest{
119+
readonlydata:string
120+
readonlyheight:number
121+
readonlywidth:number
122+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import{assign,createMachine}from"xstate"
2+
import*asAPIfrom"../../api"
3+
import*asTypesfrom"../../api/types"
4+
5+
// TypeScript doesn't have the randomUUID type on Crypto yet. See:
6+
// https://github.com/denoland/deno/issues/12754#issuecomment-970386235
7+
declare global{
8+
interfaceCrypto{
9+
randomUUID:()=>string
10+
}
11+
}
12+
13+
exportinterfaceTerminalContext{
14+
organizationsError?:Error|unknown
15+
organizations?:Types.Organization[]
16+
workspaceError?:Error|unknown
17+
workspace?:Types.Workspace
18+
workspaceAgent?:Types.WorkspaceAgent
19+
workspaceAgentError?:Error|unknown
20+
21+
reconnection:string
22+
websocket?:WebSocket
23+
}
24+
25+
exporttypeTerminalEvent=
26+
|{type:"CONNECT"}
27+
|{type:"WRITE";data:Types.ReconnectingPTYRequest}
28+
|{type:"READ";data:string}
29+
30+
exportconstterminalMachine=
31+
/**@xstate-layout N4IgpgJg5mDOIC5QBcwCcC2BLAdgQwBsBlZPVAOhmWVygHk0o8csAvMrAex1gGIJuYcrgBunANZCqDJi3Y1u8JCAAOnWFgU5EoAB6IALAYAM5AwE5LANgAcAJgDsNqwGYrxqwBoQAT0QBWAEZTBysw8wc3W2NAg38AX3jvVExcQhIyKTBqWhlmNg5FXnQ0TjRyFQIyADMyjEpsvLlCnh1VdU0ubWV9BCNTC2t7J1d3L19EaPJIlzdzY39h20Tk9Gx8YlIKKhocKAB1MvFYFTwAYzB+QWEcMUkG5EO0Y9OLtrUNLTbe4ONzckClnMLjsBjcdg83j8CDc-jMszccRcCzsVgSSRAKXW6S2WRyeyeL3OlxKZQqVWQtUwD0JJ2J7w6Xx6iF+-0BlhBYKsEPG0P8BkC5BsCIMDgcBhsxkcdhWmLWaU2mQeuwORzpFwAgjAcMgrjghKIJHjaa8wFqwDqGZ8ut8WVZAnYhQ6LKKDFZrFDEHZkeR-AigsibGK7OYZRisQqMttsiqTcTzTrimhSuVKjU6jS1aaE8grZ1uLaEIF7Y6bM7zK73eZeYZjAMgUH7UHUeZZRGNlGhGduPqziq9QbbkbyN2cL3c8oPvnunovQ7HeYHe4bHFFjZ-J6i27yHXd-b5qN-OjVqkO7iRz2wH3aEmU+T09TR+O80zZwg7PPyIvUcYV0ebOum6ooK7h1oE4qBEEgLgW28pnkqT5XqgEC8PsABKACSAAqACiL42sy74uEY5AltybrulKDibvMX5AuY66-vYooOLBp44kqpJoLwADCdAAHL8ThPFYfhBaER+DHkHYjagi4K7ETYNE2Duu6-kxFj+BEiQYjgnAQHAbTthx0b4vQjD5PIXRKKAU6viAvQGHYm5WE55DybMcTCmEgQweGcEmXisZZvSk6MgRb4+TuoLVsCdigos1ETAgAY7mEti+X6aKWGx2KKqZwXPOqZrahOtnheJb4Og6Tqgg4gIOKiwoGJuLhHtMIqhC45j+E4uWRueiHXnsYkzg5LLrlY0zcv4riQQ6DjGC4QEgkKCJtX8s0uIEbj9fBFBDcho2Ft6bhCjNYrcqGqIbslgT2EKanVg48z2DYe2BeQEBYLAh2QMdhGxAY0keKi7oSrNELOclvUuO5wpRAxApBqx-nsflQhcQDb6nVNzh2L1oQhvFaKbgKU3dUCTiSo1LioyeeWdtj41Fkpd0OHRQJjEGgLOKjiRAA */
32+
createMachine(
33+
{
34+
tsTypes:{}asimport("./terminalXService.typegen").Typegen0,
35+
schema:{
36+
context:{
37+
reconnection:crypto.randomUUID(),
38+
}asTerminalContext,
39+
events:{}asTerminalEvent,
40+
services:{}as{
41+
getOrganizations:{
42+
data:Types.Organization[]
43+
}
44+
getWorkspace:{
45+
data:Types.Workspace
46+
}
47+
getWorkspaceAgent:{
48+
data:Types.WorkspaceAgent
49+
}
50+
connect:{
51+
data:WebSocket
52+
}
53+
},
54+
},
55+
id:"terminalState",
56+
initial:"gettingOrganizations",
57+
states:{
58+
gettingOrganizations:{
59+
invoke:{
60+
src:"getOrganizations",
61+
id:"getOrganizations",
62+
onDone:[
63+
{
64+
actions:["assignOrganizations","clearOrganizationsError"],
65+
target:"gettingWorkspace",
66+
},
67+
],
68+
onError:[
69+
{
70+
actions:"assignOrganizationsError",
71+
target:"error",
72+
},
73+
],
74+
},
75+
tags:"loading",
76+
},
77+
gettingWorkspace:{
78+
invoke:{
79+
src:"getWorkspace",
80+
id:"getWorkspace",
81+
onDone:[
82+
{
83+
actions:["assignWorkspace","clearWorkspaceError"],
84+
target:"gettingWorkspaceAgent",
85+
},
86+
],
87+
onError:[
88+
{
89+
actions:"assignWorkspaceError",
90+
target:"error",
91+
},
92+
],
93+
},
94+
},
95+
gettingWorkspaceAgent:{
96+
invoke:{
97+
src:"getWorkspaceAgent",
98+
id:"getWorkspaceAgent",
99+
onDone:[
100+
{
101+
actions:["assignWorkspaceAgent","clearWorkspaceAgentError"],
102+
target:"connecting",
103+
},
104+
],
105+
onError:[
106+
{
107+
actions:"assignWorkspaceAgentError",
108+
target:"error",
109+
},
110+
],
111+
},
112+
},
113+
connecting:{
114+
invoke:{
115+
src:"connect",
116+
id:"connect",
117+
onDone:[
118+
{
119+
actions:["assignWebsocket","clearWebsocketError"],
120+
target:"connected",
121+
},
122+
],
123+
onError:[
124+
{
125+
actions:"assignWebsocketError",
126+
target:"error",
127+
},
128+
],
129+
},
130+
},
131+
connected:{
132+
on:{
133+
WRITE:{
134+
actions:"sendMessage",
135+
},
136+
},
137+
},
138+
disconnected:{},
139+
error:{
140+
on:{
141+
CONNECT:{
142+
target:"gettingOrganizations",
143+
},
144+
},
145+
},
146+
},
147+
},
148+
{
149+
services:{
150+
getOrganizations:API.getOrganizations,
151+
getWorkspace:(context:TerminalContext)=>{
152+
returnAPI.getWorkspace(context.organizations![0].id,"")
153+
},
154+
getWorkspaceAgent:async(context:TerminalContext)=>{
155+
constresources=awaitAPI.getWorkspaceResources(context.workspace!.latest_build.id)
156+
for(leti=0;i<resources.length;i++){
157+
constresource=resources[i]
158+
if(resource.agents.length<=0){
159+
continue
160+
}
161+
returnresource.agents[0]
162+
}
163+
thrownewError("no agent found with id")
164+
},
165+
connect:(context:TerminalContext)=>(send)=>{
166+
returnnewPromise<WebSocket>((resolve,reject)=>{
167+
constsocket=newWebSocket(`/api/v2/workspaceagents/${context.workspaceAgent!.id}/pty`)
168+
socket.addEventListener("open",()=>{
169+
resolve(socket)
170+
})
171+
socket.addEventListener("error",(event)=>{
172+
reject("socket errored")
173+
})
174+
socket.addEventListener("close",(event)=>{
175+
reject(event.reason)
176+
})
177+
socket.addEventListener("message",(event)=>{
178+
send({
179+
type:"READ",
180+
data:event.data,
181+
})
182+
})
183+
})
184+
},
185+
},
186+
actions:{
187+
assignOrganizations:assign({
188+
organizations:(_,event)=>event.data,
189+
}),
190+
assignOrganizationsError:assign({
191+
organizationsError:(_,event)=>event.data,
192+
}),
193+
clearOrganizationsError:assign((context:TerminalContext)=>({
194+
...context,
195+
organizationsError:undefined,
196+
})),
197+
assignWorkspace:assign({
198+
workspace:(_,event)=>event.data,
199+
}),
200+
assignWorkspaceError:assign({
201+
workspaceError:(_,event)=>event.data,
202+
}),
203+
clearWorkspaceError:assign((context:TerminalContext)=>({
204+
...context,
205+
workspaceError:undefined,
206+
})),
207+
assignWorkspaceAgent:assign({
208+
workspaceAgent:(_,event)=>event.data,
209+
}),
210+
assignWorkspaceAgentError:assign({
211+
workspaceAgentError:(_,event)=>event.data,
212+
}),
213+
clearWorkspaceAgentError:assign((context:TerminalContext)=>({
214+
...context,
215+
workspaceAgentError:undefined,
216+
})),
217+
sendMessage:(context,event)=>{
218+
context.websocket!.send(JSON.stringify(event.data))
219+
},
220+
},
221+
},
222+
)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp