@@ -2,16 +2,15 @@ export * as MoveSession from "./move-session"
22
33import { Context , DateTime , Effect , Layer , Schema } from "effect"
44import { makeGlobalNode } from "../effect/app-node"
5- import { EventV2 } from "../event "
5+ import { FSUtil } from "../fs-util "
66import { Git } from "../git"
7- import { Location } from "../location "
7+ import { Global } from "../global "
88import { ProjectV2 } from "../project"
99import { SessionV2 } from "../session"
10- import { SessionEvent } from "../session/event"
1110import { SessionExecution } from "../session/execution"
1211import { SessionSchema } from "../session/schema"
1312import { SessionStore } from "../session/store"
14- import { AbsolutePath , RelativePath } from "../schema"
13+ import { AbsolutePath } from "../schema"
1514import path from "path"
1615
1716export const Destination = Schema . Struct ( {
@@ -34,6 +33,16 @@ export class DestinationProjectMismatchError extends Schema.TaggedErrorClass<Des
3433 } ,
3534) { }
3635
36+ export class DestinationNotFoundError extends Schema . TaggedErrorClass < DestinationNotFoundError > ( ) (
37+ "MoveSession.DestinationNotFoundError" ,
38+ { directory : AbsolutePath } ,
39+ ) { }
40+
41+ export class DestinationNotDirectoryError extends Schema . TaggedErrorClass < DestinationNotDirectoryError > ( ) (
42+ "MoveSession.DestinationNotDirectoryError" ,
43+ { directory : AbsolutePath } ,
44+ ) { }
45+
3746export class ApplyChangesError extends Schema . TaggedErrorClass < ApplyChangesError > ( ) ( "MoveSession.ApplyChangesError" , {
3847 message : Schema . String ,
3948} ) { }
@@ -57,6 +66,10 @@ export class ResetSourceChangesError extends Schema.TaggedErrorClass<ResetSource
5766export type Error =
5867 | SessionV2 . NotFoundError
5968 | DestinationProjectMismatchError
69+ | DestinationNotFoundError
70+ | DestinationNotDirectoryError
71+ | SessionV2 . DestinationNotFoundError
72+ | SessionV2 . DestinationNotDirectoryError
6073 | CaptureChangesError
6174 | ApplyChangesError
6275 | ResetSourceChangesError
@@ -71,23 +84,29 @@ const layer = Layer.effect(
7184 Service ,
7285 Effect . gen ( function * ( ) {
7386 const git = yield * Git . Service
74- const events = yield * EventV2 . Service
87+ const fs = yield * FSUtil . Service
88+ const global = yield * Global . Service
7589 const project = yield * ProjectV2 . Service
7690 const sessions = yield * SessionStore . Service
91+ const session = yield * SessionV2 . Service
7792 const execution = yield * SessionExecution . Service
7893
7994 const moveSession = Effect . fn ( "MoveSession.moveSession" ) ( function * ( input : Input ) {
8095 const current = yield * sessions . get ( input . sessionID )
8196 if ( ! current ) return yield * new SessionV2 . NotFoundError ( { sessionID : input . sessionID } )
82- const directory = AbsolutePath . make ( input . destination . directory )
97+ const value = input . destination . directory . trim ( )
98+ const expanded = value === "~" ? global . home : value . startsWith ( "~/" ) ? path . join ( global . home , value . slice ( 2 ) ) : value
99+ const directory = AbsolutePath . make ( path . resolve ( current . location . directory , expanded ) )
100+ const destinationInfo = yield * fs . stat ( directory ) . pipe ( Effect . catch ( ( ) => Effect . succeed ( undefined ) ) )
101+ if ( ! destinationInfo ) return yield * new DestinationNotFoundError ( { directory } )
102+ if ( destinationInfo . type !== "Directory" ) return yield * new DestinationNotDirectoryError ( { directory } )
83103 if ( current . location . directory === directory ) return
84104
85105 const source = yield * project . resolve ( current . location . directory )
86106 const destination = yield * project . resolve ( directory )
87- if ( current . projectID !== destination . id ) {
107+ if ( input . moveChanges && current . projectID !== destination . id ) {
88108 return yield * new DestinationProjectMismatchError ( { expected : current . projectID , actual : destination . id } )
89109 }
90-
91110 // A move must not race active execution: a mid-drain relocation would let
92111 // the source Location dispatch a request assembled under stale instructions
93112 // and history. Serialize like removal does — stop the drain, then move.
@@ -111,10 +130,9 @@ const layer = Layer.effect(
111130 . pipe ( Effect . mapError ( ( error ) => new ApplyChangesError ( { message : error . message } ) ) )
112131 }
113132
114- yield * events . publish ( SessionEvent . Moved , {
133+ yield * session . move ( {
115134 sessionID : input . sessionID ,
116- location : Location . Ref . make ( { directory } ) ,
117- subpath : RelativePath . make ( path . relative ( destination . directory , directory ) . replaceAll ( "\\" , "/" ) ) ,
135+ directory,
118136 } )
119137
120138 if ( patch ) {
@@ -151,5 +169,13 @@ const layer = Layer.effect(
151169export const node = makeGlobalNode ( {
152170 service : Service ,
153171 layer,
154- deps : [ Git . node , EventV2 . node , ProjectV2 . node , SessionStore . node , SessionExecution . node ] ,
172+ deps : [
173+ FSUtil . node ,
174+ Git . node ,
175+ Global . node ,
176+ ProjectV2 . node ,
177+ SessionV2 . node ,
178+ SessionStore . node ,
179+ SessionExecution . node ,
180+ ] ,
155181} )
0 commit comments