1import {
2 AuthOrchestrationReadScope,
3 EnvironmentHttpApi,
4 requiredScopesForProjectMutation,
5} from "@t3tools/contracts";
6import * as Effect from "effect/Effect";
7import * as HttpApiBuilder from "effect/http-api/HttpApiBuilder";
8
9import {
10 annotateEnvironmentRequest,
11 failEnvironmentInternal,
12 failEnvironmentInvalidRequest,
13 requireEnvironmentScope,
14} from "../auth/http.ts";
15import * as ServerRuntimeStartup from "../serverRuntimeStartup.ts";
16import * as ProjectService from "./ProjectService.ts";
17import { projectMutationOperation } from "./ProjectMutation.ts";
18
19export const failProjectMutation = Effect.fn("environment.projects.failMutation")(function* (
20 cause: ProjectService.ProjectServiceError | ServerRuntimeStartup.ServerRuntimeStartupError,
21) {
22 if (
23 cause._tag === "ProjectNotFoundError" ||
24 cause._tag === "ProjectConflictError" ||
25 cause._tag === "ProjectNotEmptyError"
26 ) {
27 return yield* failEnvironmentInvalidRequest("invalid_command");
28 }
29 return yield* failEnvironmentInternal("project_mutation_failed", cause);
30});
31
32export const layer = HttpApiBuilder.group(
33 EnvironmentHttpApi,
34 "projects",
35 Effect.fnUntraced(function* (handlers) {
36 const projects = yield* ProjectService.ProjectService;
37 const startup = yield* ServerRuntimeStartup.ServerRuntimeStartup;
38
39 return handlers
40 .handle(
41 "snapshot",
42 Effect.fn("environment.projects.snapshot")(function* (args) {
43 yield* annotateEnvironmentRequest(args.endpoint.name);
44 yield* requireEnvironmentScope(AuthOrchestrationReadScope);
45 return yield* projects.snapshot.pipe(
46 Effect.catch((cause) => failEnvironmentInternal("project_snapshot_failed", cause)),
47 );
48 }),
49 )
50 .handle(
51 "mutate",
52 Effect.fn("environment.projects.mutate")(function* (args) {
53 yield* annotateEnvironmentRequest(args.endpoint.name);
54 for (const scope of requiredScopesForProjectMutation(args.payload)) {
55 yield* requireEnvironmentScope(scope);
56 }
57 const operation = projectMutationOperation(projects, args.payload);
58 return yield* startup.enqueueCommand(operation).pipe(Effect.catch(failProjectMutation));
59 }),
60 );
61 }),
62);