effect 4.0.0-beta.62 → 4.0.0-beta.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,7 +77,7 @@ export const layer = <Id extends string, Groups extends HttpApiGroup.Any>(
77
77
  key.startsWith("effect/httpapi/HttpApiGroup/")
78
78
  )
79
79
  for (const group of Object.values(api.groups)) {
80
- const groupRoutes = services.mapUnsafe.get(group.key) as Array<HttpRouter.Route<any, any>>
80
+ const groupRoutes = services.mapUnsafe.get(group.key)?.routes as Array<HttpRouter.Route<any, any>>
81
81
  if (groupRoutes === undefined) {
82
82
  const available = availableGroups.length === 0 ? "none" : availableGroups.join(", ")
83
83
  return yield* Effect.die(
@@ -130,10 +130,15 @@ export const group = <
130
130
  ? (yield* result as Effect.Effect<any, any, any>)
131
131
  : result
132
132
  const routes: Array<HttpRouter.Route<any, any>> = []
133
- for (const item of handlers.handlers) {
133
+ for (const item of handlers.handlers.values()) {
134
134
  routes.push(handlerToRoute(group as any, item, services))
135
135
  }
136
- return Context.makeUnsafe(new Map([[group.key, routes]]))
136
+ return Context.makeUnsafe(
137
+ new Map([[group.key, {
138
+ routes,
139
+ handlers: handlers.handlers
140
+ }]])
141
+ )
137
142
  })) as any
138
143
 
139
144
  /**
@@ -162,7 +167,7 @@ export interface Handlers<
162
167
  _Endpoints: Covariant<Endpoints>
163
168
  }
164
169
  readonly group: HttpApiGroup.AnyWithProps
165
- readonly handlers: Set<Handlers.Item<R>>
170
+ readonly handlers: Map<string, Handlers.Item<R>>
166
171
 
167
172
  /**
168
173
  * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
@@ -449,7 +454,7 @@ const HandlersProto = {
449
454
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
450
455
  ) {
451
456
  const endpoint = this.group.endpoints[name]
452
- this.handlers.add({
457
+ this.handlers.set(name, {
453
458
  endpoint,
454
459
  handler,
455
460
  isRaw: false,
@@ -464,7 +469,7 @@ const HandlersProto = {
464
469
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
465
470
  ) {
466
471
  const endpoint = this.group.endpoints[name]
467
- this.handlers.add({
472
+ this.handlers.set(name, {
468
473
  endpoint,
469
474
  handler,
470
475
  isRaw: true,
@@ -479,7 +484,7 @@ const makeHandlers = <R, Endpoints extends HttpApiEndpoint.Any>(
479
484
  ): Handlers<R, Endpoints> => {
480
485
  const self = Object.create(HandlersProto)
481
486
  self.group = group
482
- self.handlers = new Set<Handlers.Item<R>>()
487
+ self.handlers = new Map<string, Handlers.Item<R>>()
483
488
  return self
484
489
  }
485
490
 
@@ -632,7 +637,8 @@ function handlerToHttpEffect(
632
637
  )
633
638
  }
634
639
 
635
- function handlerToRoute(
640
+ /** @internal */
641
+ export function handlerToRoute(
636
642
  group: HttpApiGroup.AnyWithProps,
637
643
  handler: Handlers.Item<any>,
638
644
  context: Context.Context<any>
@@ -175,7 +175,8 @@ type UrlBuilderTopLevelMethods<Groups extends HttpApiGroup.Any> = Extract<Groups
175
175
  : never :
176
176
  never
177
177
 
178
- const makeClient = <ApiId extends string, Groups extends HttpApiGroup.Any, E, R>(
178
+ /** @internal */
179
+ export const makeClient = <ApiId extends string, Groups extends HttpApiGroup.Any, E, R>(
179
180
  api: HttpApi.HttpApi<ApiId, Groups>,
180
181
  options: {
181
182
  readonly httpClient: HttpClient.HttpClient.With<E, R>
@@ -201,9 +202,9 @@ const makeClient = <ApiId extends string, Groups extends HttpApiGroup.Any, E, R>
201
202
  | undefined
202
203
  readonly baseUrl?: URL | string | undefined
203
204
  }
204
- ): Effect.Effect<void, unknown, unknown> =>
205
+ ): Effect.Effect<void> =>
205
206
  Effect.gen(function*() {
206
- const services = yield* Effect.context<any>()
207
+ const services = yield* Effect.context()
207
208
 
208
209
  const httpClient = options.httpClient.pipe(
209
210
  options?.baseUrl === undefined
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @since 4.0.0
3
+ */
4
+ import * as Context from "../../Context.ts"
5
+ import * as Effect from "../../Effect.ts"
6
+ import type { FileSystem } from "../../FileSystem.ts"
7
+ import * as Layer from "../../Layer.ts"
8
+ import type { Path } from "../../Path.ts"
9
+ import type { Scope } from "../../Scope.ts"
10
+ import type { Generator } from "../http/Etag.ts"
11
+ import * as HttpClient from "../http/HttpClient.ts"
12
+ import type { HttpPlatform } from "../http/HttpPlatform.ts"
13
+ import * as HttpRouter from "../http/HttpRouter.ts"
14
+ import * as HttpServerRequest from "../http/HttpServerRequest.ts"
15
+ import * as HttpServerResponse from "../http/HttpServerResponse.ts"
16
+ import type * as HttpApi from "./HttpApi.ts"
17
+ import type { Handlers } from "./HttpApiBuilder.ts"
18
+ import * as HttpApiBuilder from "./HttpApiBuilder.ts"
19
+ import * as HttpApiClient from "./HttpApiClient.ts"
20
+ import type * as HttpApiEndpoint from "./HttpApiEndpoint.ts"
21
+ import type * as HttpApiGroup from "./HttpApiGroup.ts"
22
+
23
+ /**
24
+ * @since 4.0.0
25
+ * @category Testing
26
+ */
27
+ export const groups = Effect.fnUntraced(function*<
28
+ ApiId extends string,
29
+ Groups extends HttpApiGroup.Any,
30
+ const Names extends ReadonlyArray<HttpApiGroup.Name<Groups>>,
31
+ SelectedGroups = HttpApiGroup.WithName<Groups, Names[number]>
32
+ >(
33
+ api: HttpApi.HttpApi<ApiId, Groups>,
34
+ groupNames: Names
35
+ ): Effect.fn.Return<
36
+ HttpApiClient.Client<Groups>,
37
+ never,
38
+ | HttpApiGroup.ToService<ApiId, SelectedGroups>
39
+ | HttpApiGroup.MiddlewareClient<Groups>
40
+ | HttpApiEndpoint.Middleware<HttpApiGroup.Endpoints<Groups>>
41
+ | FileSystem
42
+ | Generator
43
+ | HttpPlatform
44
+ | Path
45
+ | Scope
46
+ > {
47
+ let context = yield* Effect.context<HttpApiGroup.ToService<ApiId, SelectedGroups>>()
48
+
49
+ for (const name in api.groups) {
50
+ const group = api.groups[name]
51
+ if (groupNames.includes(name as any)) {
52
+ continue
53
+ }
54
+ const handlers = new Map<string, Handlers.Item<never>>()
55
+ const routes: Array<HttpRouter.Route<any, any>> = []
56
+ for (const endpointName in group.endpoints) {
57
+ const endpoint = group.endpoints[endpointName]
58
+ const handler: Handlers.Item<never> = {
59
+ endpoint: endpoint as any,
60
+ handler: () => Effect.die(new Error(`Unhandled endpoint: ${endpointName}`)),
61
+ isRaw: false,
62
+ uninterruptible: false
63
+ }
64
+ handlers.set(endpointName, handler)
65
+ routes.push(HttpApiBuilder.handlerToRoute(group as any, handler, context))
66
+ }
67
+ context = Context.add(context, group as any, { handlers, routes })
68
+ }
69
+
70
+ const layer: Layer.Layer<
71
+ never,
72
+ never,
73
+ | FileSystem
74
+ | Generator
75
+ | HttpPlatform
76
+ | HttpRouter.HttpRouter
77
+ | Path
78
+ > = HttpApiBuilder.layer(api).pipe(
79
+ Layer.provide(Layer.succeedContext(context))
80
+ ) as any
81
+ const handler = yield* HttpRouter.toHttpEffect(layer)
82
+ const httpClient = HttpClient.make(Effect.fnUntraced(function*(request) {
83
+ const serverRequest = HttpServerRequest.fromClientRequest(request)
84
+ const response = yield* handler.pipe(
85
+ Effect.provideService(HttpServerRequest.HttpServerRequest, serverRequest),
86
+ Effect.orDie
87
+ )
88
+ return HttpServerResponse.toClientResponse(response)
89
+ }, Effect.scoped))
90
+
91
+ return yield* HttpApiClient.makeWith(api, {
92
+ httpClient,
93
+ baseUrl: "http://localhost:3000"
94
+ })
95
+ })
@@ -85,6 +85,11 @@ export * as HttpApiSecurity from "./HttpApiSecurity.ts"
85
85
  */
86
86
  export * as HttpApiSwagger from "./HttpApiSwagger.ts"
87
87
 
88
+ /**
89
+ * @since 4.0.0
90
+ */
91
+ export * as HttpApiTest from "./HttpApiTest.ts"
92
+
88
93
  /**
89
94
  * @since 4.0.0
90
95
  */