Showing the changes to apps/server/src/sourceControl/SourceControlRepositoryService.ts (1 of 2 files). Show all
Unified · Split
| @@ -39,41 +39,14 @@ export class SourceControlRepositoryService extends Context.Service< · 38 unmodified lines | |||
| 39 | } | 39 | } |
| 40 | >()("t3/sourceControl/SourceControlRepositoryService") {} | 40 | >()("t3/sourceControl/SourceControlRepositoryService") {} |
| 41 | 41 | ||
| 42 | function detailFromUnknown(cause: unknown): string { | ||
| 43 | if (typeof cause === "object" && cause !== null) { | ||
| 44 | if ("detail" in cause && typeof cause.detail === "string" && cause.detail.length > 0) { | ||
| 45 | return cause.detail; | ||
| 46 | } | ||
| 47 | if ("message" in cause && typeof cause.message === "string" && cause.message.length > 0) { | ||
| 48 | return cause.message; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | return "An unexpected source control error occurred."; | ||
| 53 | } | ||
| 54 | |||
| 55 | function repositoryError(input: { | ||
| 56 | readonly operation: string; | ||
| 57 | readonly provider: SourceControlProviderKind; | ||
| 58 | readonly detail: string; | ||
| 59 | readonly cause?: unknown; | ||
| 60 | }): SourceControlRepositoryError { | ||
| 61 | return new SourceControlRepositoryError({ | ||
| 62 | provider: input.provider, | ||
| 63 | operation: input.operation, | ||
| 64 | detail: input.detail, | ||
| 65 | ...(input.cause === undefined ? {} : { cause: input.cause }), | ||
| 66 | }); | ||
| 67 | } | ||
| 68 | |||
| 69 | function mapRepositoryError(operation: string, provider: SourceControlProviderKind) { | 42 | function mapRepositoryError(operation: string, provider: SourceControlProviderKind) { |
| 70 | return Effect.mapError((cause: unknown) => | 43 | return Effect.mapError((cause: unknown) => |
| 71 | isSourceControlRepositoryError(cause) | 44 | isSourceControlRepositoryError(cause) |
| 72 | ? cause | 45 | ? cause |
| 73 | : repositoryError({ | 46 | : new SourceControlRepositoryError({ |
| 74 | operation, | 47 | operation, |
| 75 | provider, | 48 | provider, |
| 76 | detail: detailFromUnknown(cause), | 49 | detail: "The source control operation could not be completed.", |
| 77 | cause, | 50 | cause, |
| 78 | }), | 51 | }), |
| 79 | ); | 52 | ); |
| @@ -130,7 +103,7 @@ export const make = Effect.gen(function* () { · 50 unmodified lines | |||
| 130 | } | 103 | } |
| 131 | 104 | ||
| 132 | return Effect.fail( | 105 | return Effect.fail( |
| 133 | repositoryError({ | 106 | new SourceControlRepositoryError({ |
| 134 | operation: input.operation, | 107 | operation: input.operation, |
| 135 | provider: input.provider, | 108 | provider: input.provider, |
| 136 | detail: "Choose a source control provider before continuing.", | 109 | detail: "Choose a source control provider before continuing.", |
| @@ -157,7 +130,7 @@ export const make = Effect.gen(function* () { · 20 unmodified lines | |||
| 157 | function* (destinationPath: string) { | 130 | function* (destinationPath: string) { |
| 158 | const trimmed = destinationPath.trim(); | 131 | const trimmed = destinationPath.trim(); |
| 159 | if (trimmed.length === 0) { | 132 | if (trimmed.length === 0) { |
| 160 | return yield* repositoryError({ | 133 | return yield* new SourceControlRepositoryError({ |
| 161 | operation: "cloneRepository", | 134 | operation: "cloneRepository", |
| 162 | provider: "unknown", | 135 | provider: "unknown", |
| 163 | detail: "Choose a destination path before cloning.", | 136 | detail: "Choose a destination path before cloning.", |
| @@ -171,21 +144,22 @@ export const make = Effect.gen(function* () { · 7 unmodified lines | |||
| 171 | const prepareDestination = Effect.fn("SourceControlRepositoryService.prepareDestination")( | 144 | const prepareDestination = Effect.fn("SourceControlRepositoryService.prepareDestination")( |
| 172 | function* (destinationPath: string) { | 145 | function* (destinationPath: string) { |
| 173 | const normalizedDestination = yield* normalizeDestinationPath(destinationPath); | 146 | const normalizedDestination = yield* normalizeDestinationPath(destinationPath); |
| 174 | if (yield* fileSystem.exists(normalizedDestination).pipe(Effect.orElseSucceed(() => false))) { | 147 | if (yield* fileSystem.exists(normalizedDestination)) { |
| 175 | const entries = yield* fileSystem | 148 | const entries = yield* fileSystem |
| 176 | .readDirectory(normalizedDestination, { recursive: false }) | 149 | .readDirectory(normalizedDestination, { recursive: false }) |
| 177 | .pipe( | 150 | .pipe( |
| 178 | Effect.mapError((cause) => | 151 | Effect.mapError( |
| 179 | repositoryError({ | 152 | (cause) => |
| 180 | operation: "cloneRepository", | 153 | new SourceControlRepositoryError({ |
| 181 | provider: "unknown", | 154 | operation: "cloneRepository", |
| 182 | detail: "Destination path already exists and is not a directory.", | 155 | provider: "unknown", |
| 183 | cause, | 156 | detail: "Destination path already exists and is not a directory.", |
| 184 | }), | 157 | cause, |
| 158 | }), | ||
| 185 | ), | 159 | ), |
| 186 | ); | 160 | ); |
| 187 | if (entries.length > 0) { | 161 | if (entries.length > 0) { |
| 188 | return yield* repositoryError({ | 162 | return yield* new SourceControlRepositoryError({ |
| 189 | operation: "cloneRepository", | 163 | operation: "cloneRepository", |
| 190 | provider: "unknown", | 164 | provider: "unknown", |
| 191 | detail: "Destination path already exists and is not empty.", | 165 | detail: "Destination path already exists and is not empty.", |
| @@ -222,7 +196,7 @@ export const make = Effect.gen(function* () { · 30 unmodified lines | |||
| 222 | } | 196 | } |
| 223 | 197 | ||
| 224 | if (!remoteUrl) { | 198 | if (!remoteUrl) { |
| 225 | return yield* repositoryError({ | 199 | return yield* new SourceControlRepositoryError({ |
| 226 | operation: "cloneRepository", | 200 | operation: "cloneRepository", |
| 227 | provider, | 201 | provider, |
| 228 | detail: "Enter a repository path or clone URL before cloning.", | 202 | detail: "Enter a repository path or clone URL before cloning.", |