Skip to content

Commit 08ee941

Browse files
authored
Merge pull request #431 from ProverCoderAI/codex/openapi-effect-client
[codex] Use openapi-effect client
2 parents 126710b + 66b7611 commit 08ee941

19 files changed

Lines changed: 1304 additions & 760 deletions

bun.lock

Lines changed: 5 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/api/src/api/openapi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,8 @@ export const DockerGitApi = HttpApi.make("docker-git")
782782
// CHANGE: derive Swagger/OpenAPI from the Effect HttpApi contract.
783783
// WHY: frontend clients must be generated from one typed REST contract.
784784
// QUOTE(ТЗ): "Надо сделать REST API нормальный на базе Effect и использовать Swagger."
785-
// REF: user-message-2026-06-18-openapi-fetch
786-
// SOURCE: https://openapi-ts.dev/openapi-fetch/
785+
// REF: user-message-2026-06-19-openapi-effect
786+
// SOURCE: https://github.com/ProverCoderAI/openapi-effect
787787
// FORMAT THEOREM: forall endpoint e in DockerGitApi, e is represented in buildDockerGitOpenApi().paths.
788788
// PURITY: CORE
789789
// EFFECT: none

packages/api/src/http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ const textResponse = (data: string, contentType: string, status = 200) =>
317317
// CHANGE: expose browser-readable Swagger UI for the Effect REST contract.
318318
// WHY: generated clients and humans must inspect the same OpenAPI document.
319319
// QUOTE(ТЗ): "использовать Swagger"
320-
// REF: user-message-2026-06-18-openapi-fetch
321-
// SOURCE: n/a
320+
// REF: user-message-2026-06-19-openapi-effect
321+
// SOURCE: https://github.com/ProverCoderAI/openapi-effect
322322
// FORMAT THEOREM: docsPath(d) = p -> openApiPath(d) = sibling(p, "openapi.json")
323323
// PURITY: CORE
324324
// EFFECT: none

packages/app/src/web/api-create-project.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import type { Effect } from "effect"
1+
import { Effect, Match } from "effect"
22

3+
import { dockerGitOpenApi, renderDockerGitOpenApiFailure } from "./api-http.js"
34
import {
45
type BaseCreateProjectBody,
56
baseCreateProjectBody,
67
type CreateProjectRequestDraft,
78
optionalProjectResourceFields,
89
type OptionalProjectResourceFieldsBody
910
} from "./api-project-create-body.js"
10-
import { CreateProjectAcceptedResponseSchema } from "./api-schema.js"
1111
import type { CreateProjectAcceptedResponse } from "./api-schema.js"
12-
import { openApiJsonSchema } from "./openapi-client.js"
1312

1413
type CreateProjectAcceptedBody = Readonly<
1514
& BaseCreateProjectBody
@@ -39,10 +38,42 @@ export const createProjectAcceptedBody = (draft: CreateProjectRequestDraft): Cre
3938
...optionalProjectResourceFields(draft)
4039
})
4140

41+
// CHANGE: Publish the async project creation boundary with an explicit Effect signature.
42+
// WHY: exported web API helpers must expose typed success, error, and requirement channels.
43+
// QUOTE(ТЗ): "исправь"
44+
// REF: PR#431 CodeRabbit review 4535473023
45+
// SOURCE: n/a
46+
// FORMAT THEOREM: forall draft d: accepted(d) -> Effect<CreateProjectAcceptedResponse, string, never>.
47+
// PURITY: SHELL
48+
// EFFECT: Effect<CreateProjectAcceptedResponse, string, never>
49+
// INVARIANT: only HTTP 202 is accepted as the asynchronous creation success branch.
50+
// COMPLEXITY: O(1)/O(1), excluding HTTP transport.
51+
/**
52+
* Starts asynchronous project creation through the typed OpenAPI client.
53+
*
54+
* @param draft - Validated project creation draft plus optional resource limits.
55+
* @returns Effect that resolves to the accepted async creation response.
56+
*
57+
* @pure false - performs HTTP IO when the returned Effect is executed.
58+
* @effect Effect<CreateProjectAcceptedResponse, string, never>
59+
* @invariant HTTP 202 returns the accepted response; HTTP 201 is rejected as a sync branch mismatch.
60+
* @precondition draft fields were validated by the UI create flow.
61+
* @postcondition downstream callers observe only accepted async responses or string-rendered failures.
62+
* @complexity O(1)/O(1), excluding HTTP transport and response body size.
63+
* @throws Never - failures are represented in the Effect error channel.
64+
*/
4265
export const startCreateProject = (
4366
draft: CreateProjectRequestDraft
4467
): Effect.Effect<CreateProjectAcceptedResponse, string> =>
45-
openApiJsonSchema(CreateProjectAcceptedResponseSchema, (client) =>
46-
client.POST("/projects", {
47-
body: createProjectAcceptedBody(draft)
48-
}))
68+
dockerGitOpenApi.POST("/projects", {
69+
body: createProjectAcceptedBody(draft)
70+
}).pipe(
71+
Effect.mapError(renderDockerGitOpenApiFailure),
72+
Effect.flatMap((success) =>
73+
Match.value(success).pipe(
74+
Match.when({ status: 202 }, ({ body }) => Effect.succeed(body)),
75+
Match.when({ status: 201 }, () => Effect.fail("HTTP 201: unexpected synchronous project creation response")),
76+
Match.exhaustive
77+
)
78+
)
79+
)

0 commit comments

Comments
 (0)