@@ -23,6 +23,7 @@ import {
2323 CreateProjectRequestSchema ,
2424 GithubAuthLoginRequestSchema ,
2525 GithubAuthLogoutRequestSchema ,
26+ ProjectDatabaseProfileRequestSchema ,
2627 ProjectAuthRequestSchema ,
2728 ProjectPortForwardRequestSchema ,
2829 StateCommitRequestSchema ,
@@ -76,6 +77,22 @@ import {
7677import { readProjectAuthSnapshot , runProjectAuthFlow } from "./services/project-auth.js"
7778import { readProjectBrowserSession , proxyProjectBrowser } from "./services/project-browser.js"
7879import { parseProjectBrowserProxyPath } from "./services/project-browser-core.js"
80+ import {
81+ deleteProjectDatabaseForward ,
82+ deleteProjectDatabaseProfile ,
83+ exposeProjectDatabaseProfile ,
84+ listProjectDatabaseForwards ,
85+ listProjectDatabaseProfiles ,
86+ openProjectDatabaseEditor ,
87+ proxyProjectDatabase ,
88+ readProjectDatabaseSession ,
89+ restartProjectDatabaseEditor ,
90+ saveProjectDatabaseProfile
91+ } from "./services/project-databases.js"
92+ import {
93+ parseProjectDatabaseProxyPath ,
94+ parseProjectDatabaseStatefulProxyPath
95+ } from "./services/project-databases-core.js"
7996import {
8097 createProjectPortForward ,
8198 deleteProjectPortForward ,
@@ -103,6 +120,11 @@ const ProjectPortForwardParamsSchema = Schema.Struct({
103120 targetPort : Schema . String
104121} )
105122
123+ const ProjectDatabaseProfileParamsSchema = Schema . Struct ( {
124+ projectId : Schema . String ,
125+ profileId : Schema . String
126+ } )
127+
106128const AgentParamsSchema = Schema . Struct ( {
107129 projectId : Schema . String ,
108130 agentId : Schema . String
@@ -264,6 +286,7 @@ const errorResponse = (error: ApiError | unknown) => {
264286
265287const projectParams = HttpRouter . schemaParams ( ProjectParamsSchema )
266288const projectPortForwardParams = HttpRouter . schemaParams ( ProjectPortForwardParamsSchema )
289+ const projectDatabaseProfileParams = HttpRouter . schemaParams ( ProjectDatabaseProfileParamsSchema )
267290const agentParams = HttpRouter . schemaParams ( AgentParamsSchema )
268291const terminalSessionParams = HttpRouter . schemaParams ( TerminalSessionParamsSchema )
269292const authTerminalSessionParams = HttpRouter . schemaParams ( AuthTerminalSessionParamsSchema )
@@ -279,6 +302,7 @@ const readCodexAuthLoginRequest = () => HttpServerRequest.schemaBodyJson(CodexAu
279302const readCodexAuthLogoutRequest = ( ) => HttpServerRequest . schemaBodyJson ( CodexAuthLogoutRequestSchema )
280303const readProjectAuthRequest = ( ) => HttpServerRequest . schemaBodyJson ( ProjectAuthRequestSchema )
281304const readProjectPortForwardRequest = ( ) => HttpServerRequest . schemaBodyJson ( ProjectPortForwardRequestSchema )
305+ const readProjectDatabaseProfileRequest = ( ) => HttpServerRequest . schemaBodyJson ( ProjectDatabaseProfileRequestSchema )
282306const readStateInitRequest = ( ) => HttpServerRequest . schemaBodyJson ( StateInitRequestSchema )
283307const readStateCommitRequest = ( ) => HttpServerRequest . schemaBodyJson ( StateCommitRequestSchema )
284308const readStateSyncRequest = ( ) => HttpServerRequest . schemaBodyJson ( StateSyncRequestSchema )
@@ -367,8 +391,20 @@ const projectProxyResponse = Effect.gen(function*(_) {
367391 if ( browserTarget !== null ) {
368392 return yield * _ ( proxyProjectBrowser ( request , browserTarget , resolveRequestOrigin ( request ) ) )
369393 }
394+ const databaseTarget = parseProjectDatabaseProxyPath ( pathname )
395+ if ( databaseTarget !== null ) {
396+ return yield * _ ( proxyProjectDatabase ( request , databaseTarget ) )
397+ }
370398 const target = parseProjectPortProxyPath ( pathname )
371399 if ( target === null ) {
400+ const statefulDatabaseTarget = parseProjectDatabaseStatefulProxyPath (
401+ pathname ,
402+ readHeader ( request , "referer" ) ,
403+ readHeader ( request , "cookie" )
404+ )
405+ if ( statefulDatabaseTarget !== null ) {
406+ return yield * _ ( proxyProjectDatabase ( request , statefulDatabaseTarget ) )
407+ }
372408 return yield * _ ( Effect . fail ( new ApiNotFoundError ( { message : `Route not found: ${ pathname } ` } ) ) )
373409 }
374410 return yield * _ ( proxyProjectPortForward ( request , target ) )
@@ -740,7 +776,91 @@ export const makeRouter = () => {
740776 const browser = yield * _ ( readProjectBrowserSession ( projectId , resolveRequestOrigin ( request ) ) )
741777 return yield * _ ( jsonResponse ( { browser } , 200 ) )
742778 } ) . pipe ( Effect . catchAll ( errorResponse ) )
779+ )
780+ )
781+
782+ const withProjectDatabases = withProjects . pipe (
783+ HttpRouter . get (
784+ "/projects/:projectId/databases/profiles" ,
785+ projectParams . pipe (
786+ Effect . flatMap ( ( { projectId } ) => listProjectDatabaseProfiles ( projectId ) ) ,
787+ Effect . flatMap ( ( profiles ) => jsonResponse ( { profiles } , 200 ) ) ,
788+ Effect . catchAll ( errorResponse )
789+ )
743790 ) ,
791+ HttpRouter . get (
792+ "/projects/:projectId/databases/forwards" ,
793+ projectParams . pipe (
794+ Effect . flatMap ( ( { projectId } ) => listProjectDatabaseForwards ( projectId ) ) ,
795+ Effect . flatMap ( ( forwards ) => jsonResponse ( { forwards } , 200 ) ) ,
796+ Effect . catchAll ( errorResponse )
797+ )
798+ ) ,
799+ HttpRouter . post (
800+ "/projects/:projectId/databases/profiles" ,
801+ Effect . gen ( function * ( _ ) {
802+ const { projectId } = yield * _ ( projectParams )
803+ const request = yield * _ ( readProjectDatabaseProfileRequest ( ) )
804+ const profile = yield * _ ( saveProjectDatabaseProfile ( projectId , request ) )
805+ return yield * _ ( jsonResponse ( { profile } , 201 ) )
806+ } ) . pipe ( Effect . catchAll ( errorResponse ) )
807+ ) ,
808+ HttpRouter . del (
809+ "/projects/:projectId/databases/profiles/:profileId" ,
810+ projectDatabaseProfileParams . pipe (
811+ Effect . flatMap ( ( { projectId, profileId } ) => deleteProjectDatabaseProfile ( projectId , profileId ) ) ,
812+ Effect . flatMap ( ( ) => jsonResponse ( { ok : true } , 200 ) ) ,
813+ Effect . catchAll ( errorResponse )
814+ )
815+ ) ,
816+ HttpRouter . post (
817+ "/projects/:projectId/databases/profiles/:profileId/expose" ,
818+ Effect . gen ( function * ( _ ) {
819+ const { projectId, profileId } = yield * _ ( projectDatabaseProfileParams )
820+ const serverRequest = yield * _ ( HttpServerRequest . HttpServerRequest )
821+ const forward = yield * _ ( exposeProjectDatabaseProfile (
822+ projectId ,
823+ profileId ,
824+ resolvePortPublicHost ( serverRequest )
825+ ) )
826+ return yield * _ ( jsonResponse ( { forward } , 201 ) )
827+ } ) . pipe ( Effect . catchAll ( errorResponse ) )
828+ ) ,
829+ HttpRouter . del (
830+ "/projects/:projectId/databases/profiles/:profileId/expose" ,
831+ projectDatabaseProfileParams . pipe (
832+ Effect . flatMap ( ( { projectId, profileId } ) => deleteProjectDatabaseForward ( projectId , profileId ) ) ,
833+ Effect . flatMap ( ( ) => jsonResponse ( { ok : true } , 200 ) ) ,
834+ Effect . catchAll ( errorResponse )
835+ )
836+ ) ,
837+ HttpRouter . get (
838+ "/projects/:projectId/databases/session" ,
839+ projectParams . pipe (
840+ Effect . flatMap ( ( { projectId } ) => readProjectDatabaseSession ( projectId ) ) ,
841+ Effect . flatMap ( ( session ) => jsonResponse ( { session } , 200 ) ) ,
842+ Effect . catchAll ( errorResponse )
843+ )
844+ ) ,
845+ HttpRouter . post (
846+ "/projects/:projectId/databases/open" ,
847+ projectParams . pipe (
848+ Effect . flatMap ( ( { projectId } ) => openProjectDatabaseEditor ( projectId ) ) ,
849+ Effect . flatMap ( ( session ) => jsonResponse ( { session } , 200 ) ) ,
850+ Effect . catchAll ( errorResponse )
851+ )
852+ ) ,
853+ HttpRouter . post (
854+ "/projects/:projectId/databases/restart" ,
855+ projectParams . pipe (
856+ Effect . flatMap ( ( { projectId } ) => restartProjectDatabaseEditor ( projectId ) ) ,
857+ Effect . flatMap ( ( session ) => jsonResponse ( { session } , 200 ) ) ,
858+ Effect . catchAll ( errorResponse )
859+ )
860+ )
861+ )
862+
863+ const withProjectLifecycle = withProjectDatabases . pipe (
744864 HttpRouter . del (
745865 "/projects/:projectId" ,
746866 projectParams . pipe (
@@ -816,7 +936,7 @@ export const makeRouter = () => {
816936 )
817937 )
818938
819- const withAgents = withProjects . pipe (
939+ const withAgents = withProjectLifecycle . pipe (
820940 HttpRouter . post (
821941 "/projects/:projectId/agents" ,
822942 Effect . gen ( function * ( _ ) {
0 commit comments