diff --git a/.changeset/forty-turtles-care.md b/.changeset/forty-turtles-care.md new file mode 100644 index 00000000000..f6e36fe713b --- /dev/null +++ b/.changeset/forty-turtles-care.md @@ -0,0 +1,38 @@ +--- +"@effect/platform": patch +--- + +add helper types for HttpApi + +Examples: + +```ts +const group1 = HttpApiGroup.make("Group1").add( + HttpApiEndpoint.get("Endpoint1")`/` +) +const group2 = HttpApiGroup.make("Group2").add( + HttpApiEndpoint.get("Endpoint2")`/` +) +const api = HttpApi.make("TestApi").add(group1).add(group2) + +// ┌─── | HttpApiGroup<"Group1", HttpApiEndpoint<"Endpoint1", "GET">, never> +// | | HttpApiGroup<"Group2", HttpApiEndpoint<"Endpoint2", "GET">, never> +// ▼ +type groups = HttpApi.HttpApi.Groups + +// ┌─── HttpApiEndpoint<"Endpoint1", "GET"> +// ▼ +type endpoints = HttpApi.HttpApi.EndpointsWithGroupName + +// ┌─── HttpApiEndpoint.Handler, never, never> +// ▼ +type handler = HttpApi.HttpApi.ExtractHandlerType< + typeof api, + "Group1", + "Endpoint1", + never, + never +> +``` + +the latter is useful when you want to extract the handler type of a specific endpoint within a group. diff --git a/packages/platform/dtslint/HttpApi.tst.ts b/packages/platform/dtslint/HttpApi.tst.ts new file mode 100644 index 00000000000..1f488f0033b --- /dev/null +++ b/packages/platform/dtslint/HttpApi.tst.ts @@ -0,0 +1,69 @@ +import type { HttpApiError } from "@effect/platform" +import { HttpApi, HttpApiEndpoint, HttpApiGroup } from "@effect/platform" +import { describe, expect, it } from "tstyche" + +const group1 = HttpApiGroup.make("Group1").add( + HttpApiEndpoint.get("Endpoint1")`/` +) +const group2 = HttpApiGroup.make("Group2").add( + HttpApiEndpoint.get("Endpoint2")`/` +) +const api = HttpApi.make("TestApi").add(group1).add(group2) + +describe("HttpApi", () => { + it("add", () => { + expect().type.toBe< + HttpApi.HttpApi< + "TestApi", + | HttpApiGroup.HttpApiGroup<"Group1", HttpApiEndpoint.HttpApiEndpoint<"Endpoint1", "GET">, never> + | HttpApiGroup.HttpApiGroup<"Group2", HttpApiEndpoint.HttpApiEndpoint<"Endpoint2", "GET">, never>, + HttpApiError.HttpApiDecodeError + > + >() + expect(api.add(HttpApiGroup.make("NewGroup"))).type.toBe< + HttpApi.HttpApi< + "TestApi", + | HttpApiGroup.HttpApiGroup<"Group1", HttpApiEndpoint.HttpApiEndpoint<"Endpoint1", "GET">, never> + | HttpApiGroup.HttpApiGroup<"Group2", HttpApiEndpoint.HttpApiEndpoint<"Endpoint2", "GET">, never> + | HttpApiGroup.HttpApiGroup<"NewGroup", never, never>, + HttpApiError.HttpApiDecodeError + > + >() + }) + + it("HttpApi.Groups", () => { + expect>().type.toBe< + | HttpApiGroup.HttpApiGroup<"Group1", HttpApiEndpoint.HttpApiEndpoint<"Endpoint1", "GET">, never> + | HttpApiGroup.HttpApiGroup<"Group2", HttpApiEndpoint.HttpApiEndpoint<"Endpoint2", "GET">, never> + >() + expect>>().type.toBe<"Group1" | "Group2">() + }) + + it("HttpApi.EndpointsWithGroupName", () => { + expect>().type.toBe< + HttpApiEndpoint.HttpApiEndpoint<"Endpoint1", "GET"> + >() + expect>().type.toBe< + HttpApiEndpoint.HttpApiEndpoint<"Endpoint2", "GET"> + >() + expect>>().type + .toBe< + "Endpoint1" + >() + expect>>().type + .toBe< + "Endpoint2" + >() + }) + + it("HttpApi.ExtractHandlerType", () => { + expect>() + .type.toBe< + HttpApiEndpoint.HttpApiEndpoint.Handler, never, never> + >() + expect>() + .type.toBe< + HttpApiEndpoint.HttpApiEndpoint.Handler, never, never> + >() + }) +}) diff --git a/packages/platform/src/HttpApi.ts b/packages/platform/src/HttpApi.ts index 2cbcf250648..e556e437f38 100644 --- a/packages/platform/src/HttpApi.ts +++ b/packages/platform/src/HttpApi.ts @@ -137,6 +137,39 @@ export declare namespace HttpApi { * @category models */ export type AnyWithProps = HttpApi + + /** + * @since 1.0.0 + * @category models + */ + export type Groups = Api extends HttpApi< + infer _Id, + infer _Groups, + infer _E, + infer _R + > ? _Groups + : never + + /** + * @since 1.0.0 + * @category models + */ + export type EndpointsWithGroupName>> = + GroupName extends HttpApiGroup.HttpApiGroup.Name> ? + HttpApiGroup.HttpApiGroup.EndpointsWithName, GroupName> + : never + + /** + * @since 1.0.0 + * @category models + */ + export type ExtractHandlerType< + Api extends HttpApi.Any, + GroupName extends HttpApiGroup.HttpApiGroup.Name>, + EndpointName extends HttpApiEndpoint.HttpApiEndpoint.Name>, + E = never, + R = never + > = HttpApiEndpoint.HttpApiEndpoint.HandlerWithName, EndpointName, E, R> } const Proto = { diff --git a/packages/platform/src/HttpApiBuilder.ts b/packages/platform/src/HttpApiBuilder.ts index 6cf568529a9..ba2e0414b67 100644 --- a/packages/platform/src/HttpApiBuilder.ts +++ b/packages/platform/src/HttpApiBuilder.ts @@ -517,8 +517,10 @@ export const handler = < Groups extends HttpApiGroup.HttpApiGroup.Any, ApiError, ApiR, - const GroupName extends Groups["identifier"], - const Name extends HttpApiGroup.HttpApiGroup.EndpointsWithName["name"], + const GroupName extends HttpApiGroup.HttpApiGroup.Name, + const Name extends HttpApiEndpoint.HttpApiEndpoint.Name< + HttpApiGroup.HttpApiGroup.EndpointsWithName + >, R >( _api: HttpApi.HttpApi, diff --git a/packages/platform/src/HttpApiClient.ts b/packages/platform/src/HttpApiClient.ts index 3c589a62ea7..d1c6b108fce 100644 --- a/packages/platform/src/HttpApiClient.ts +++ b/packages/platform/src/HttpApiClient.ts @@ -32,7 +32,7 @@ export type Client = Simplify< & { readonly [Group in Extract as HttpApiGroup.Name]: Client.Group< Group, - Group["identifier"], + HttpApiGroup.Name, E, R > @@ -51,7 +51,7 @@ export declare namespace Client { * @since 1.0.0 * @category models */ - export type Group = + export type Group, E, R> = [HttpApiGroup.WithName] extends [HttpApiGroup] ? { readonly [Endpoint in _Endpoints as HttpApiEndpoint.Name]: Method< diff --git a/packages/platform/src/HttpApiEndpoint.ts b/packages/platform/src/HttpApiEndpoint.ts index 7b383fd0424..b884c70d87f 100644 --- a/packages/platform/src/HttpApiEndpoint.ts +++ b/packages/platform/src/HttpApiEndpoint.ts @@ -509,19 +509,25 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type WithName = Extract + export type WithName> = Extract< + Endpoints, + { readonly name: Name } + > /** * @since 1.0.0 * @category models */ - export type ExcludeName = Exclude + export type ExcludeName> = Exclude< + Endpoints, + { readonly name: Name } + > /** * @since 1.0.0 * @category models */ - export type HandlerWithName = Handler< + export type HandlerWithName, E, R> = Handler< WithName, E, R @@ -531,41 +537,50 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type HandlerRawWithName = HandlerRaw< - WithName, - E, - R - > + export type HandlerRawWithName, E, R> = + HandlerRaw< + WithName, + E, + R + > /** * @since 1.0.0 * @category models */ - export type SuccessWithName = Success> + export type SuccessWithName> = Success< + WithName + > /** * @since 1.0.0 * @category models */ - export type ErrorWithName = Error> + export type ErrorWithName> = Error< + WithName + > /** * @since 1.0.0 * @category models */ - export type ContextWithName = Context> + export type ContextWithName> = Context< + WithName + > /** * @since 1.0.0 * @category models */ - export type ErrorContextWithName = ErrorContext> + export type ErrorContextWithName> = ErrorContext< + WithName + > /** * @since 1.0.0 * @category models */ - export type ExcludeProvided = Exclude< + export type ExcludeProvided, R> = Exclude< R, | HttpRouter.HttpRouter.DefaultServices | HttpRouter.HttpRouter.Provided diff --git a/packages/platform/src/HttpApiGroup.ts b/packages/platform/src/HttpApiGroup.ts index 60877abb79e..f869200e9cd 100644 --- a/packages/platform/src/HttpApiGroup.ts +++ b/packages/platform/src/HttpApiGroup.ts @@ -176,7 +176,10 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type WithName = Extract + export type WithName> = Extract< + Group, + { readonly identifier: Name } + > /** * @since 1.0.0 @@ -198,7 +201,9 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type EndpointsWithName = Endpoints> + export type EndpointsWithName> = Endpoints< + WithName + > /** * @since 1.0.0 @@ -227,7 +232,7 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type ErrorWithName = Error> + export type ErrorWithName> = Error> /** * @since 1.0.0 @@ -271,13 +276,13 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type ContextWithName = Context> + export type ContextWithName> = Context> /** * @since 1.0.0 * @category models */ - export type MiddlewareWithName = Middleware< + export type MiddlewareWithName> = Middleware< WithName > }