88
99import * as FetchHttpClient from "@effect/platform/FetchHttpClient"
1010import type * as HttpClient from "@effect/platform/HttpClient"
11- import { Console , Effect , Exit , Match } from "effect"
12- import { createClient , type ClientOptions } from "../src/shell/api-client/create-client .js"
13- import { dispatchercreatePet , dispatchergetPet , dispatcherlistPets } from "../src/generated/dispatch .js"
11+ import { Cause , Console , Effect , Match } from "effect"
12+ import "../src/generated/dispatchers-by-path .js"
13+ import { type ClientOptions , createClient } from "../src/shell/api-client/create-client .js"
1414import type { Paths } from "../tests/fixtures/petstore.openapi.js"
1515
1616/**
@@ -21,6 +21,16 @@ const clientOptions: ClientOptions = {
2121 credentials : "include"
2222}
2323
24+ // CHANGE: Use default dispatcher registry (registered by generated module)
25+ // WHY: Call createClient(options) without passing dispatcher map
26+ // QUOTE(ТЗ): "const apiClient = createClient<Paths>(clientOptions)"
27+ // REF: user-msg-4
28+ // SOURCE: n/a
29+ // FORMAT THEOREM: ∀ op ∈ Operations: createClient(options) uses registered dispatchers
30+ // PURITY: SHELL
31+ // EFFECT: none
32+ // INVARIANT: default dispatchers registered before client creation
33+ // COMPLEXITY: O(1)
2434const apiClient = createClient < Paths > ( clientOptions )
2535
2636// =============================================================================
@@ -45,14 +55,9 @@ export const getPetStrictProgram: Effect.Effect<void, never, HttpClient.HttpClie
4555 yield * Console . log ( "=== getPet: Strict Error Handling ===" )
4656
4757 // Execute request - yields only on 200
48- const result = yield * apiClient . GET (
49- "/pets/{petId}" ,
50- dispatchergetPet ,
51- { params : { petId : "123" } }
58+ yield * apiClient . GET ( "/pets/{petId}" , { params : { petId : "123" } } ) . pipe (
59+ Effect . tap ( ( result ) => Console . log ( `Got pet: ${ result . body . name } ` ) )
5260 )
53-
54- // Success! TypeScript knows status is 200
55- yield * Console . log ( `Got pet: ${ result . body . name } ` )
5661} ) . pipe (
5762 // Handle HttpError with EXHAUSTIVE matching (no orElse!)
5863 Effect . catchTag ( "HttpError" , ( error ) =>
@@ -66,7 +71,7 @@ export const getPetStrictProgram: Effect.Effect<void, never, HttpClient.HttpClie
6671 // Handle ALL boundary errors
6772 Effect . catchTag ( "TransportError" , ( e ) => Console . log ( `Transport error: ${ e . error . message } ` ) ) ,
6873 Effect . catchTag ( "UnexpectedStatus" , ( e ) => Console . log ( `Unexpected status: ${ e . status } ` ) ) ,
69- Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual } ` ) ) ,
74+ Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual ?? "unknown" } ` ) ) ,
7075 Effect . catchTag ( "ParseError" , ( e ) => Console . log ( `Parse error: ${ e . error . message } ` ) ) ,
7176 Effect . catchTag ( "DecodeError" , ( e ) => Console . log ( `Decode error: ${ e . error . message } ` ) )
7277)
@@ -87,17 +92,15 @@ export const getPetStrictProgram: Effect.Effect<void, never, HttpClient.HttpClie
8792export const createPetStrictProgram : Effect . Effect < void , never , HttpClient . HttpClient > = Effect . gen ( function * ( ) {
8893 yield * Console . log ( "=== createPet: Strict Error Handling ===" )
8994
90- const result = yield * apiClient . POST (
95+ yield * apiClient . POST (
9196 "/pets" ,
92- dispatchercreatePet ,
9397 {
9498 // Body can be typed object - client will auto-stringify and set Content-Type
9599 body : { name : "Fluffy" , tag : "cat" }
96100 }
101+ ) . pipe (
102+ Effect . tap ( ( result ) => Console . log ( `Created pet: ${ result . body . id } ` ) )
97103 )
98-
99- // Success! TypeScript knows status is 201
100- yield * Console . log ( `Created pet: ${ result . body . id } ` )
101104} ) . pipe (
102105 // Handle HttpError with EXHAUSTIVE matching
103106 Effect . catchTag ( "HttpError" , ( error ) =>
@@ -110,7 +113,7 @@ export const createPetStrictProgram: Effect.Effect<void, never, HttpClient.HttpC
110113 // Handle ALL boundary errors
111114 Effect . catchTag ( "TransportError" , ( e ) => Console . log ( `Transport error: ${ e . error . message } ` ) ) ,
112115 Effect . catchTag ( "UnexpectedStatus" , ( e ) => Console . log ( `Unexpected status: ${ e . status } ` ) ) ,
113- Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual } ` ) ) ,
116+ Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual ?? "unknown" } ` ) ) ,
114117 Effect . catchTag ( "ParseError" , ( e ) => Console . log ( `Parse error: ${ e . error . message } ` ) ) ,
115118 Effect . catchTag ( "DecodeError" , ( e ) => Console . log ( `Decode error: ${ e . error . message } ` ) )
116119)
@@ -131,14 +134,13 @@ export const createPetStrictProgram: Effect.Effect<void, never, HttpClient.HttpC
131134export const listPetsStrictProgram : Effect . Effect < void , never , HttpClient . HttpClient > = Effect . gen ( function * ( ) {
132135 yield * Console . log ( "=== listPets: Strict Error Handling ===" )
133136
134- const result = yield * apiClient . GET (
135- "/pets" ,
136- dispatcherlistPets ,
137- { query : { limit : 10 } }
137+ yield * apiClient . GET ( "/pets" , { query : { limit : 10 } } ) . pipe (
138+ Effect . tap ( ( result ) => Console . log ( `Got ${ result . body . length } pets` ) )
138139 )
139140
140- // Success! TypeScript knows status is 200
141- yield * Console . log ( `Got ${ result . body . length } pets` )
141+ const pets = yield * apiClient . GET ( "/pets" , { query : { limit : 10 } } )
142+
143+ yield * Console . log ( `Got ${ pets . body . length } pets` )
142144} ) . pipe (
143145 // Handle HttpError with EXHAUSTIVE matching
144146 Effect . catchTag ( "HttpError" , ( error ) =>
@@ -150,7 +152,7 @@ export const listPetsStrictProgram: Effect.Effect<void, never, HttpClient.HttpCl
150152 // Handle ALL boundary errors
151153 Effect . catchTag ( "TransportError" , ( e ) => Console . log ( `Transport error: ${ e . error . message } ` ) ) ,
152154 Effect . catchTag ( "UnexpectedStatus" , ( e ) => Console . log ( `Unexpected status: ${ e . status } ` ) ) ,
153- Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual } ` ) ) ,
155+ Effect . catchTag ( "UnexpectedContentType" , ( e ) => Console . log ( `Unexpected content-type: ${ e . actual ?? "unknown" } ` ) ) ,
154156 Effect . catchTag ( "ParseError" , ( e ) => Console . log ( `Parse error: ${ e . error . message } ` ) ) ,
155157 Effect . catchTag ( "DecodeError" , ( e ) => Console . log ( `Decode error: ${ e . error . message } ` ) )
156158)
@@ -183,22 +185,19 @@ const mainProgram: Effect.Effect<void, never, HttpClient.HttpClient> = Effect.ge
183185 yield * Console . log ( "========================================" )
184186} )
185187
186- /**
187- * Execute the program
188- *
189- * CRITICAL: Since mainProgram has E=never, Effect.runPromiseExit
190- * will never fail with a typed error - only defects are possible.
191- */
188+ // CHANGE: Remove async/await entrypoint and handle defects in Effect
189+ // WHY: Lint rules forbid async/await and floating promises; defects are handled in Effect channel
190+ // QUOTE(ТЗ): "Запрещён async/await — используй Effect.gen / Effect.tryPromise."
191+ // REF: user-msg-2
192+ // SOURCE: n/a
193+ // FORMAT THEOREM: For all exits, mainProgram E=never implies failure(exit) -> defect(exit)
194+ // PURITY: SHELL
195+ // EFFECT: Effect<void, never, HttpClient> -> Promise<void> via Effect.runPromise
196+ // INVARIANT: Typed error channel remains never
197+ // COMPLEXITY: O(1)
192198const program = mainProgram . pipe (
193- Effect . provide ( FetchHttpClient . layer )
199+ Effect . provide ( FetchHttpClient . layer ) ,
200+ Effect . catchAllCause ( ( cause ) => Console . error ( `Unexpected defect: ${ Cause . pretty ( cause ) } ` ) )
194201)
195202
196- const main = async ( ) => {
197- const exit = await Effect . runPromiseExit ( program )
198- if ( Exit . isFailure ( exit ) ) {
199- // This can only be a defect (unexpected exception), not a typed error
200- console . error ( "Unexpected defect:" , exit . cause )
201- }
202- }
203-
204- main ( )
203+ void Effect . runPromise ( program )
0 commit comments