@@ -2,15 +2,28 @@ import { listAdaptors } from "@/control-plane/adaptors"
22import { Workspace } from "@/control-plane/workspace"
33import { WorkspaceAdaptorEntry } from "@/control-plane/types"
44import * as InstanceState from "@/effect/instance-state"
5- import { Effect , Layer , Schema } from "effect"
5+ import { Instance } from "@/project/instance"
6+ import { Effect , Layer , Schema , Struct } from "effect"
67import { HttpApi , HttpApiBuilder , HttpApiEndpoint , HttpApiGroup , OpenApi } from "effect/unstable/httpapi"
78import { Authorization } from "./auth"
89
910const root = "/experimental/workspace"
11+ const CreatePayload = Schema . Struct ( Struct . omit ( Workspace . CreateInput . fields , [ "projectID" ] ) ) . annotate ( {
12+ identifier : "WorkspaceCreateInput" ,
13+ } )
14+ const SessionRestorePayload = Schema . Struct ( Struct . omit ( Workspace . SessionRestoreInput . fields , [ "workspaceID" ] ) ) . annotate ( {
15+ identifier : "WorkspaceSessionRestoreInput" ,
16+ } )
17+ const SessionRestoreResponse = Schema . Struct ( {
18+ total : Schema . Number ,
19+ } ) . annotate ( { identifier : "WorkspaceSessionRestoreResponse" } )
20+
1021export const WorkspacePaths = {
1122 adaptors : `${ root } /adaptor` ,
1223 list : root ,
1324 status : `${ root } /status` ,
25+ remove : `${ root } /:id` ,
26+ sessionRestore : `${ root } /:id/session-restore` ,
1427} as const
1528
1629export const WorkspaceApi = HttpApi . make ( "workspace" )
@@ -35,6 +48,16 @@ export const WorkspaceApi = HttpApi.make("workspace")
3548 description : "List all workspaces." ,
3649 } ) ,
3750 ) ,
51+ HttpApiEndpoint . post ( "create" , WorkspacePaths . list , {
52+ payload : CreatePayload ,
53+ success : Workspace . Info ,
54+ } ) . annotateMerge (
55+ OpenApi . annotations ( {
56+ identifier : "experimental.workspace.create" ,
57+ summary : "Create workspace" ,
58+ description : "Create a workspace for the current project." ,
59+ } ) ,
60+ ) ,
3861 HttpApiEndpoint . get ( "status" , WorkspacePaths . status , {
3962 success : Schema . Array ( Workspace . ConnectionStatus ) ,
4063 } ) . annotateMerge (
@@ -44,6 +67,27 @@ export const WorkspaceApi = HttpApi.make("workspace")
4467 description : "Get connection status for workspaces in the current project." ,
4568 } ) ,
4669 ) ,
70+ HttpApiEndpoint . delete ( "remove" , WorkspacePaths . remove , {
71+ params : { id : Workspace . Info . fields . id } ,
72+ success : Schema . UndefinedOr ( Workspace . Info ) ,
73+ } ) . annotateMerge (
74+ OpenApi . annotations ( {
75+ identifier : "experimental.workspace.remove" ,
76+ summary : "Remove workspace" ,
77+ description : "Remove an existing workspace." ,
78+ } ) ,
79+ ) ,
80+ HttpApiEndpoint . post ( "sessionRestore" , WorkspacePaths . sessionRestore , {
81+ params : { id : Workspace . Info . fields . id } ,
82+ payload : SessionRestorePayload ,
83+ success : SessionRestoreResponse ,
84+ } ) . annotateMerge (
85+ OpenApi . annotations ( {
86+ identifier : "experimental.workspace.sessionRestore" ,
87+ summary : "Restore session into workspace" ,
88+ description : "Replay a session's sync events into the target workspace in batches." ,
89+ } ) ,
90+ ) ,
4791 )
4892 . annotateMerge (
4993 OpenApi . annotations ( {
@@ -72,13 +116,51 @@ export const workspaceHandlers = Layer.unwrap(
72116 return Workspace . list ( ( yield * InstanceState . context ) . project )
73117 } )
74118
119+ const create = Effect . fn ( "WorkspaceHttpApi.create" ) ( function * ( ctx : { payload : typeof CreatePayload . Type } ) {
120+ const instance = yield * InstanceState . context
121+ return yield * Effect . promise ( ( ) =>
122+ Instance . restore ( instance , ( ) =>
123+ Workspace . create ( {
124+ ...Schema . decodeUnknownSync ( CreatePayload ) ( ctx . payload ) ,
125+ projectID : instance . project . id ,
126+ } ) ,
127+ ) ,
128+ )
129+ } )
130+
75131 const status = Effect . fn ( "WorkspaceHttpApi.status" ) ( function * ( ) {
76132 const ids = new Set ( Workspace . list ( ( yield * InstanceState . context ) . project ) . map ( ( item ) => item . id ) )
77133 return Workspace . status ( ) . filter ( ( item ) => ids . has ( item . workspaceID ) )
78134 } )
79135
136+ const remove = Effect . fn ( "WorkspaceHttpApi.remove" ) ( function * ( ctx : { params : { id : Workspace . Info [ "id" ] } } ) {
137+ const instance = yield * InstanceState . context
138+ return yield * Effect . promise ( ( ) => Instance . restore ( instance , ( ) => Workspace . remove ( ctx . params . id ) ) )
139+ } )
140+
141+ const sessionRestore = Effect . fn ( "WorkspaceHttpApi.sessionRestore" ) ( function * ( ctx : {
142+ params : { id : Workspace . Info [ "id" ] }
143+ payload : typeof SessionRestorePayload . Type
144+ } ) {
145+ const instance = yield * InstanceState . context
146+ return yield * Effect . promise ( ( ) =>
147+ Instance . restore ( instance , ( ) =>
148+ Workspace . sessionRestore ( {
149+ workspaceID : ctx . params . id ,
150+ sessionID : ctx . payload . sessionID ,
151+ } ) ,
152+ ) ,
153+ )
154+ } )
155+
80156 return HttpApiBuilder . group ( WorkspaceApi , "workspace" , ( handlers ) =>
81- handlers . handle ( "adaptors" , adaptors ) . handle ( "list" , list ) . handle ( "status" , status ) ,
157+ handlers
158+ . handle ( "adaptors" , adaptors )
159+ . handle ( "list" , list )
160+ . handle ( "create" , create )
161+ . handle ( "status" , status )
162+ . handle ( "remove" , remove )
163+ . handle ( "sessionRestore" , sessionRestore ) ,
82164 )
83165 } ) ,
84166)
0 commit comments